Download Files Using Dependency Service

.NET standard application

MainPage.xaml.cs

public partial class MainPage : ContentPage
{
  IDownloader downloader = DependencyService.Get<IDownloader>();

  public MainPage()
  {
    InitializeComponent();
    downloader.OnFileDownloaded += Downloader_OnFileDownload;
  }

  private void Downloader_OnFileDownload(object sender, DownloadEventArgs e)
  {
    if (e.FileSaved)
    {
      //File Saved Successfully. Do some action.
    }
    else
    {
      //Error while saving the file. Do some action.
    }
  }

  //download method
  protected void DownloadMethod()
  {
    downloader.DownloadFile("url of the download item");
  }
}


IDownloader.cs

namespace Xamarin
{
    public interface IDownloader
    {
        void DownloadFile(string url);
        event EventHandler<DownloadEventArgs> OnFileDownloaded;
    }

    public class DownloadEventArgs : EventArgs
    {
        public bool FileSaved = false;
        public DownloadEventArgs(bool fileSaved)
        {
            FileSaved = fileSaved;
        }
    }
}


Android App

AndroidDownloader.cs

[assembly: Dependency(typeof(AndroidDownloader))]
namespace Xamarin.Droid
{
    public class AndroidDownloader : IDownloader
    {
        public event EventHandler<DownloadEventArgs> OnFileDownloaded;

        public void DownloadFile(string url)
        {
            var context = Android.App.Application.Context;
            var pathToNewFolder = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);
            
            if (!Directory.Exists(pathToNewFolder))
            {
                _ = Directory.CreateDirectory(pathToNewFolder);
            }

            try
            {
                Uri uri = new UriBuilder(url).Uri;
                WebClient webClient = new WebClient();
                ServicePointManager.ServerCertificateValidationCallback = new
                RemoteCertificateValidationCallback
                (
                   delegate { return true; }
                );

                webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
                string pathToNewFile = Path.Combine(pathToNewFolder, Path.GetFileName(url));
                webClient.DownloadFileAsync(uri, pathToNewFile);
                webClient.Dispose();
            }
            catch(Exception)
            {
                if(OnFileDownloaded != null)
                {
                    OnFileDownloaded.Invoke(this, new DownloadEventArgs(false));
                }
            }
        }


        private void Completed(object sender, AsyncCompletedEventArgs e)
        {
            if(e.Error != null)
            {
                if (OnFileDownloaded != null)
                {
                    OnFileDownloaded.Invoke(this, new DownloadEventArgs(false));
                }
            }
            else
            {
                if (OnFileDownloaded != null)
                {
                    OnFileDownloaded.Invoke(this, new DownloadEventArgs(true));
                }
            }
        }
    }
}


AndroidManifest.xml

Add the following two permissions:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />


iOS App

IosDownloader.cs

[assembly: Dependency(typeof(IosDownloader))]
namespace Xamarin.iOS
{
    public class IosDownloader : IDownloader
    {
        public event EventHandler<DownloadEventArgs> OnFileDownloaded;

        public void DownloadFile(string url)
        {
            string pathToNewFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal));
            
            if (!Directory.Exists(pathToNewFolder))
            {
                _ = Directory.CreateDirectory(pathToNewFolder);
            }

            try
            {
                Uri uri = new UriBuilder(url).Uri;
                WebClient webClient = new WebClient();
                ServicePointManager.ServerCertificateValidationCallback = new
                RemoteCertificateValidationCallback
                (
                   delegate { return true; }
                );

                webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
                string pathToNewFile = Path.Combine(pathToNewFolder, Path.GetFileName(url));
                webClient.DownloadFileAsync(uri, pathToNewFile);
                webClient.Dispose();
            }
            catch (Exception)
            {
                if (OnFileDownloaded != null)
                {
                    OnFileDownloaded.Invoke(this, new DownloadEventArgs(false));
                }
            }
        }


        private void Completed(object sender, AsyncCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                if (OnFileDownloaded != null)
                {
                    OnFileDownloaded.Invoke(this, new DownloadEventArgs(false));
                }
            }
            else
            {
                if (OnFileDownloaded != null)
                {
                    OnFileDownloaded.Invoke(this, new DownloadEventArgs(true));
                }
            }
        }
    }
}


Info.plist

Add the following two permissions:

<key>Privacy - Media Library Usage Description</key>
<string>The app requires access to media.</string>

<key>Privacy - Photo Library Usage Description</key>
<string>The app requires access to photo.</string>

<key>Privacy - Photo Library Additions Usage Description</key>
<string>The app requires access to photo gallery.</string>

You must reboot your iPhone for the changes to take effect.