I try to download file from web and save to any of Environment.SpecialFolder locations. No matter of what approach I try - I always get
System.UnauthorizedAccessException: 'Access to the path 'any possible path I try (even beyond Environment.SpecialFolder)' is denied.'
I tried accessing filesystem on UWP and Android - both same exception.
What I tried with no luck so far:
var webClient = new WebClient();
webClient.DownloadDataCompleted += (s, e) => {
var bytes = e.Result;
string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
string localFilename = "downloaded.jpg";
string localPath = Path.Combine(documentsPath, localFilename);
File.WriteAllBytes(localPath, bytes);
};
webClient.DownloadDataAsync(new Uri(url));
You are facing a permissions issue.
First, you will have to add in your AndroidManifest:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
And since Android Marshmallow, you need to ask the user for the permissions, so I advise to use the package Permissions.Plugin
And add in your MainActivity:
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
You can check in runtime if you have the permissions by:
var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);
if (status != PermissionStatus.Granted)
{
if(await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Storage))
{
await DisplayAlert("Need storage, "Request storage permission", "OK");
}
var results = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Storage);
//Best practice to always check that the key exists
if(results.ContainsKey(Permission.Storage))
status = results[Permission.Storage];
}
For further information you can check this blog post explaining all the permissions in Android - https://devblogs.microsoft.com/xamarin/requesting-runtime-permissions-in-android-marshmallow/
In addition to Bruno Caceiro's accepted answer, the UWP permissions you want to declare are as follows: DocumentsLibrary
for documents, MusicLibrary
for the music folder and so on.
You can get to these graphically via Right click project -> Properties and then clicking Package Manifest and going to the capabilities tab as shown in the screenshot, or alternatively right-clicking package.appxmanifest
and selecting view code to edit the xml. See the code excerpt for how to declare capabilities. Some won't have a representation in the dialog.
<Capabilities>
<Capability Name="internetClient" />
<uap:Capability Name="documentsLibrary"/>
<uap:Capability Name="picturesLibrary" />
</Capabilities>
Edit additionally, you can also access some restricted folders by using the rescap
(restricted capability) namespace to add <rescap:Capability Name="broadFileSystemAccess" />
to gain access to any file/folder the user has access to.
I Had the Same problem on Android, i realized the problem is because
I Had to ask permission on Runtime , keep in mind that you need both ACCESS_COARSE_LOCATION and WRITE_EXTERNAL_STORAGE permissions
I was using wrong Path, my main problem was to get the path pragmatically which i couldn't solve and I solved it by typing the path Manually. i believe if you use the correct full path(etc storage/emulated/0/) you're not going to face any problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With