Currently, the Xamarin Android app uses GetExternalStoragePublicDirectory (deprecated as of API level 29) with the requestLegacyExternalStorage enabled to download a file from Azure Blob Storage endpoint into the downloads directory directly.
The official way out of this is to use Storage Access Framework (SAF) and allow the user to select the destination to save the file. Registered a dependency service as follows:
FileDownloader.cs
public void DownloadFile(string url, string fileName)
{
Intent intent = new Intent(Intent.ActionCreateDocument);
intent.AddCategory(Intent.CategoryOpenable);
intent.PutExtra(Intent.ExtraTitle, fileName);
intent.PutExtra("download_url", url);
intent.SetType("application/pdf");
var activity = MainActivity.Instance;
activity.StartActivityForResult(intent, CREATE_PDF_REQUEST);
}
And then in the onActivityResult, handling the request code and result to download the data from the url
MainActivity.cs
// rest of MainActivity.cs
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
try
{
switch (requestCode)
{
case CREATE_PDF_REQUEST:
string url = data.GetStringExtra("download_url");
Webclient client = new Webclient();
client.DownloadFile(url, data.DataString);
break;
default:
// do something
}
}
catch (Exception ex)
{
//do something
}
}
The flow is activated on taping a button which has an event listener and calls the dependency service as follows:
ViewModel.cs
DependencyService.Get<FileDownloaderInterface>().DownloadFile(url, fileName);
However, the url is always null. Thus leading to malformed Uri exception. What am I doing wrong here?
Also, I want to await an async call inside the onActivityResult. Is it possible or do I have to run Task.Run(() => await client.DownloadFileAysnc())?
Xamarin Forms version 4.6.0