Creating Files in Android 11 gives Access Denied error.

Gayatri Gokhale 1 Reputation point
2021-03-12T11:41:37.157+00:00

I am trying to create file at Downloads Directory. Basically I want user to download excel file that resides in my app(In Android Assets folder). User will fill and upload it again. For downloading I do as follows

public async void DownloadSupplierSample(object sender, EventArgs e)
    {
        try
        {
            string basepath;
            if (Device.RuntimePlatform == Device.Android)
                basepath = DependencyService.Get<IDownloadPath>().GetDownloadsPath();
            else
                basepath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "..", "Library");

            PermissionStatus readstatus = await Permissions.CheckStatusAsync<Permissions.StorageRead>();
            PermissionStatus writestatus = await Permissions.CheckStatusAsync<Permissions.StorageWrite>();

            if (readstatus == PermissionStatus.Granted && writestatus == PermissionStatus.Granted)
            {
                DownloadSupplier(basepath);
            }
            else
            {
                var read = await Permissions.RequestAsync<Permissions.StorageRead>();
                var write = await Permissions.RequestAsync<Permissions.StorageWrite>();

                if (read == PermissionStatus.Granted && write == PermissionStatus.Granted)
                {
                    DownloadSupplier(basepath);
                }
            }
            await DisplayAlert("", "Sample is downaloaded at Downloads directory","Ok");
        }
        catch (Exception ex)
        {
        }
    }

    async void DownloadSupplier(string basepath)
    {
        using (var stream = await FileSystem.OpenAppPackageFileAsync("SupplierMaster.xlsx"))
        {
            string filename = $"SupplierMaster_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx";
            string filepath = Path.Combine(basepath, filename);

            byte[] bytes = Utils.Common.StreamToBytes(stream);
            File.WriteAllBytes(filepath, bytes);
            //using (Stream filestream = File.Create(filepath))
            //{
            //    //stream.Seek(0, SeekOrigin.Begin);
            //    stream.CopyTo(filestream);
            //}
        }
    }

even if I give required permission and set flag in AndroidManifest.xml, I am getting this error.

I had asked on SO as well. Here is the linklink I tried to implement answer as well. It worked for few times but after that same error comes.

Please help.

Thank you

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,362 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Alessandro Caliaro 4,186 Reputation points
    2021-03-12T12:04:21.353+00:00

    Android 11 has a new storage update

    storage

    take a look to this:

    xamarin-forms-accessing-external-storage-on-android-11-target-sdk-version-is-29

    0 comments No comments

  2. JessieZhang-MSFT 7,711 Reputation points Microsoft Vendor
    2021-03-30T07:33:17.523+00:00

    Hello,

    Welcome to our Microsoft Q&A platform!

    1.Try to create a service class in Android project, just as follows:

     private class ActivityResultListener  
        {  
            private readonly TaskCompletionSource<Intent> Complete = new TaskCompletionSource<Intent>();  
            public Task<Intent> Task { get { return this.Complete.Task; } }  
    
            public ActivityResultListener(MainActivity activity)  
            {  
                // subscribe to activity results  
                activity.ActivityResult += OnActivityResult;  
            }  
    
            private void OnActivityResult(int requestCode, Result resultCode, Intent data)  
            {  
                if(requestCode != CREATE_FILE_REQUEST_CODE)  
                {  
                    return;  
                }  
    
                // unsubscribe from activity results  
                var activity = (MainActivity)_context;  
                activity.ActivityResult -= OnActivityResult;  
    
                // process result  
                if (resultCode == Result.Ok)  
                {  
                    Complete.TrySetResult(data);  
                }  
                else  
                {  
                    Complete.TrySetResult(null);  
                }  
            }  
        }  
    }  
    

    2.In MainActivity.cs, add the following code:

     public event Action<int, Result, Intent> ActivityResult;  
    
    protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)   
    {  
        ActivityResult?.Invoke(requestCode, resultCode, data);   
    }  
    

    3.call Init method after Forms.Init:

     FilesManager.Init(this);  
    

    Refer: https://stackoverflow.com/questions/66560359/xamarin-forms-how-to-define-scoped-storage-for-android-and-how-can-i-implement

    Best Regards,

    Jessie Zhang


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.