I\'m trying to download a file and I\'m getting System.UnauthorizedAccessException: Access to the path \"/storage/emulated/0/Download/test.pdf\" is denied. I have set requir
Those of you who are facing this issue after your app is Targeting API29 or higher, please go to this link and check LandLu's Answer:
https://forums.xamarin.com/discussion/171039/saving-files-to-external-storage
Earlier I was accessing Folder path using return Android.OS.Environment.ExternalStorageDirectory.AbsolutePath; But using this line solved my problem: return Android.App.Application.Context.GetExternalFilesDir("").AbsolutePath;
You need user's permission on run time even you have mentioned them in your manifest file if you are running Android api level 23 or greater. Check and if user has not yet granted granted READ_EXTERNAL_STORAGE
& WRITE_EXTERNAL_STORAGE
, use the bellow code;
var permissions = new string[] { Manifest.Permission.ReadExternalStorage, Manifest.Permission.WriteExternalStorage };
RequestPermissions(permissions, 77);
If i use the below path as my download path i can able to download the file. But i cant able to share the PDF file to google drive, drop box or any other System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal)
You are storing files on app's private storage. All files saved to the internal storage are private to your application and other applications ( google drive, drop box or any other ) cannot access them (nor can the user). You can use any public folder for that purpose;
var finalPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads);
If targeting API 29+, you will get the error even if you request the permission and user grants it, because they changed how storage works.
The correct solution is to look how it should be done on API 29+ and do it.
But if you are like me, tired of Android making things more complicated every day, just add android:requestLegacyExternalStorage="true"
to your manifest <application>
tag and you are saved until you start targeting API 30.
Depending on the version of Android you are using even with the permissions added in the manifest in 6.0 or up the user has to explicitly enable the permission when the app runs and on lower versions permission is asked during install. For example, on startup of the app I created a method to check if it is enabled and request permission if it's not.
private void CheckAppPermissions()
{
if ((int)Build.VERSION.SdkInt < 23)
{
return;
}
else
{
if (PackageManager.CheckPermission(Manifest.Permission.ReadExternalStorage, PackageName) != Permission.Granted
&& PackageManager.CheckPermission(Manifest.Permission.WriteExternalStorage, PackageName) != Permission.Granted)
{
var permissions = new string[] { Manifest.Permission.ReadExternalStorage, Manifest.Permission.WriteExternalStorage };
RequestPermissions(permissions, 1);
}
}
}
You can also use the support library to do this, which is simpler and allows you to not have to check the Android version. For more info check out google's documentation.