21

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 required permission in Android Manifest file.

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

Download Path:

Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads) 

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)

I am using Xamarin.Forms v2.4.0.282 and Xamarin.Android.Support packages v25.4.0.2.

Note: The code was woking fine when use Xamarin.Forms version 2.3.5.256-pre2 and Xamarin.Android.Support packages v23.3.0 Please suggest your ideas to resolve the issue.

Thanks in Advance.

5
  • What version of Android are you on because anything api 23 and newer requires explicit permission granted by the user to access files Commented Oct 24, 2017 at 14:43
  • I am facing the issue from android v5.1 to v7.0 Commented Oct 24, 2017 at 14:51
  • 1
    On one of the devices I'd go into settings>apps click on the app and check to see if the storage permission is enabled and retry. If it afterward it works then you'll just need to prompt the user to enable permission Commented Oct 24, 2017 at 17:19
  • @Nick Thank you. It is working after enabled permission as you said. Now i have added the code to ask runtime permission. Commented Oct 25, 2017 at 8:18
  • The following answer could be helpful stackoverflow.com/a/66515458/7149454 Commented Mar 7, 2021 at 10:27

5 Answers 5

36

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.

Sign up to request clarification or add additional context in comments.

5 Comments

This should be marked as correct answer. Works perfectly fine.
I'm using this snippet and it returns "Granted" for both permissions but I'm still getting Access Denied. Any ideas?
It may not like the location you are trying to read/write from/to. Try checking the location or changing it to another path that you know exists.
Perfectly fine.
Granting the app permission in the phone settings works very well for this error
23

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.

5 Comments

How do you do that?
Hi, I am now targeting API 30. My app was storing log file and taking database backup in location "/storage/emulated/0/SpecialDir/LogFile.txt". Now I am facing access denied issue. Can you please guide me what should i do.
you saved my day! Thanks. (Note: I'm using unity and got the access denial issue even after I gave external storage permission. Now it is fixed by adding 'android:requestLegacyExternalStorage="true"' to the application tag in my custom manifest)
It is worth mentioning that this is just a temporary solution and its better to make your app compatible with Scoped Storage: After you update your app to target Android 11 (API level 30), the system ignores the requestLegacyExternalStorage attribute when your app is running on Android 11 devices, so your app must be ready to support scoped storage and to migrate app data for users on those devices. Android Source: developer.android.com/training/data-storage/…
@SnapADragon yes I did mention that. "you are saved until you start targeting API 30".
9

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;

this is the corret answer!!!

Comments

1

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); 

Comments

0

replace

Android.OS.Environment.ExternalStorageDirectory.AbsolutePath; 

with

Android.App.Application.Context.GetExternalFilesDir("").AbsolutePath; 

1 Comment

Hi! Adding a bit of context might improve the quality of the answer a lot imho. You might also find the infor in here useful for future answers,

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.