Q: Why isn't my app working?

Arthur Van Loo 41 Reputation points
2020-12-17T10:47:18.717+00:00

I am trying to make a YouTube-downloader, but when I insert a link and click download nothing happens. (I've already enabled the permissions for storage, but somehow they also don't show up when I test).
Here's my code:

using System.Threading.Tasks;
using Xamarin.Forms;
using YoutubeExplode;
using YoutubeExplode.Videos.Streams;

namespace YouTubeDL
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }
        async Task btnDownload_ClickedAsync(System.Object sender, System.EventArgs e)
        {
            var youtube = new YoutubeClient();
            var streamManifest = await youtube.Videos.Streams.GetManifestAsync(iptLink.Text);
            if (btnVideo.IsChecked)
            {
                var streamInfo = streamManifest.GetMuxed().WithHighestVideoQuality();
                if (streamInfo != null)
                {
                    var stream = await youtube.Videos.Streams.GetAsync(streamInfo);
                    await youtube.Videos.Streams.DownloadAsync(streamInfo, $"video.{streamInfo.Container}");
                }
            }
            else if (btnAudio.IsChecked)
            {
                var streamInfo = streamManifest.GetAudioOnly().WithHighestBitrate();
                if (streamInfo != null)
                {
                    var stream = await youtube.Videos.Streams.GetAsync(streamInfo);
                    await youtube.Videos.Streams.DownloadAsync(streamInfo, $"video.{streamInfo.Container}");
                }
            }

        }
    }
}

MainPage.xml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:YouTubeDL;assembly=YouTubeDL"
             x:Class="YouTubeDL.MainPage"
             BackgroundColor="White">
    <StackLayout Padding="24" Spacing="30">
        <Frame BackgroundColor="#E62117" Padding="24" CornerRadius="0">
            <Label Text="Youtube downloader" HorizontalTextAlignment="Center" TextColor="White" FontSize="36"/>
        </Frame>
        <Entry Text="Yt-link"
               x:Name="iptLink"
               TextColor="Black"/>
        <local:PatchedRadioButton Text="Video"
                     x:Name="btnVideo"
                     GroupName="Options"
                     IsChecked="True"
                     TextColor="Black"/>
        <local:PatchedRadioButton Text="Only audio"
                     x:Name="btnAudio"
                     GroupName="Options"
                     TextColor="Black"/>
        <Button Text="Download"
                x:Name="btnDownload"
                TextColor="White"
                FontSize="Large"
                BackgroundColor="#E62117"
                CornerRadius="15"
                />
    </StackLayout>
</ContentPage>
Developer technologies .NET Xamarin
{count} votes

Accepted answer
  1. Anonymous
    2020-12-18T08:18:03.6+00:00

    Hello,​

    Welcome to our Microsoft Q&A platform!

    but I still can't figure out how to use the

    await youtube.Videos.Streams.DownloadAsync(streamInfo, $"video.{streamInfo.Container}");

    I open the DownloadAsync method, I found we can add path to it like following code.

       string folder = FileSystem.AppDataDirectory;  
                           string path =Path.Combine(folder, "MAudio.mp4");  
                           await youtube.Videos.Streams.DownloadAsync(streamInfo, path, null);  
    

    49356-image.png

    I change background code.

       public AboutPage()  
               {  
    
                   InitializeComponent();  
    
                    btnDownload.Clicked += BtnDownload_Clicked;  
    
                }  
    
    
    
               private async void BtnDownload_Clicked(object sender, EventArgs e)  
               {  
                   var youtube = new YoutubeClient();  
                   var streamManifest = await youtube.Videos.Streams.GetManifestAsync(iptLink.Text);  
                   if (btnVideo.IsChecked)  
                   {  
                       var streamInfo = streamManifest.GetMuxed().WithHighestVideoQuality();  
                       if (streamInfo != null)  
                       {  
                           var stream = await youtube.Videos.Streams.GetAsync(streamInfo);  
    
                           string folder = FileSystem.AppDataDirectory;  
                           string path =Path.Combine(folder, "MAudio.mp4");  
                           await youtube.Videos.Streams.DownloadAsync(streamInfo, path, null);  
                       }  
                   }  
                   else if (btnAudio.IsChecked)  
                   {  
                       var streamInfo = streamManifest.GetAudioOnly().WithHighestBitrate();  
                       if (streamInfo != null)  
                       {  
                           var stream = await youtube.Videos.Streams.GetAsync(streamInfo);  
                           string folder = FileSystem.AppDataDirectory;  
                           string path = Path.Combine(folder, "MAudio.mp3");  
    
                           await youtube.Videos.Streams.DownloadAsync(streamInfo, path, null);  
                       }  
                   }  
    
               }  
    

    I set it path with Xamarin.Essentials: File System Helpers https://learn.microsoft.com/en-us/xamarin/essentials/file-system-helpers?context=xamarin%2Fandroid&tabs=android

    It store files in the internal storage. In the Android, it store /data/data/com.companyname.shellnavi/files/

    49452-image.png

    ================
    Update====================

    If you want to see the download file in your emulator and target framework is blew Android 10(Android 11 or later, Google do not allow store file in the external folder), you can store it in the external folder, add following permission and add android:requestLegacyExternalStorage="true" to the application tag.

       <application android:label="ShellNavi.Android" android:theme="@style/MainTheme" android:requestLegacyExternalStorage="true"></application>  
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />  
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
    

    Then Add following code to request run-time permission. For testing, I add following code to OnCreate method of MainActivity normally

       if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) != (int)Permission.Granted)  
                   {  
                       RequestPermissions(new string[] { Manifest.Permission.ReadExternalStorage, Manifest.Permission.WriteExternalStorage }, 0);  
                   }  
    

    If you want to store the file in download folder. You need to use dependenceService to the path of download folder.

    50855-image.png 50809-image.png

    Create an interface.

       public interface IgetFile1  
           {  
    
              string getExternalFile();  
           }  
    

    Achieve it in android project .

       [assembly: Dependency(typeof(getFileService))]  
       namespace ShellNavi.Droid  
       {  
           class getFileService : IgetFile1  
           {  
    
               public string getExternalFile()  
               {  
                   string path= Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath;  
                   return path;  
               }  
           }  
       }  
    

    Use it when you want to download .

       private async void BtnDownload_Clicked(object sender, EventArgs e)  
               {  
                   var youtube = new YoutubeClient();  
                   var streamManifest = await youtube.Videos.Streams.GetManifestAsync(iptLink.Text);  
                   if (btnVideo.IsChecked)  
                   {  
                       var streamInfo = streamManifest.GetMuxed().WithHighestVideoQuality();  
                       if (streamInfo != null)  
                       {  
                           var stream = await youtube.Videos.Streams.GetAsync(streamInfo);  
                           string folder=  DependencyService.Get<IgetFile1>().getExternalFile();  
                          // string folder = FileSystem.AppDataDirectory;  
                           string path =Path.Combine(folder, "MAudio.mp4");  
                           await youtube.Videos.Streams.DownloadAsync(streamInfo, path, null);  
                       }  
                   }  
                   else if (btnAudio.IsChecked)  
                   {  
                       var streamInfo = streamManifest.GetAudioOnly().WithHighestBitrate();  
                       if (streamInfo != null)  
                       {  
                           var stream = await youtube.Videos.Streams.GetAsync(streamInfo);  
                           string folder = DependencyService.Get<IgetFile1>().getExternalFile();  
                          // string folder = FileSystem.AppDataDirectory;  
                           string path = Path.Combine(folder, "MAudio.mp3");  
    
                           await youtube.Videos.Streams.DownloadAsync(streamInfo, path, null);  
                       }  
                   }  
    
               }  
    

    Best Regards,

    Leon Lu


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. Alessandro Caliaro 4,196 Reputation points
    2020-12-17T11:22:32.14+00:00

    I think you have to write something like

    btnDownload.Clicked += btnDownload_ClickedAsync; (I think the syntax is not correct...)

    under the InitializeComponent()


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.