0

I have config files which I am trying to save to device and read them in run time. But now my permission is denied when I upgraded from Android10 to Android13. Could you please help here.

Need to read and write file in Device storage for A13.

Need to read or write files to download directory in Xamarin with Android 13.

I need help to Read and Write files in Download directory with Android 13 in Xamarin.

Anubhav
  • 1
  • 1

2 Answers2

0

The permission had been changed in the Android 11 update. You can read the Storage updates in Android 11 to use the MANAGE_EXTERNAL_STORAGE.

It depends on the new granular permissions you want to use. So you can check this issue thread Storage permissions Android 13 api 33 for more information .

Guangyu Bai - MSFT
  • 2,555
  • 1
  • 2
  • 8
  • Most of the comments are related to camera permissions only and this issue is still open. Did not get anything from above link. I need to read and write the file in download directory by providing the permission from code only. – Anubhav Apr 24 '23 at 02:58
  • You can check this [Permissions and access to external storage](https://developer.android.com/training/data-storage#permissions) to use the `MANAGE_EXTERNAL_STORAGE`. – Guangyu Bai - MSFT Apr 25 '23 at 05:32
0

I was getting the same issue, I kept getting an unauthorized access exception on file writes even when writing to internal app data locations such as when trying to write to Xamarin.Essentials.FileSystem.AppDataDirectory, Xamarin.Essentials.FileSystem.CacheDirectory or System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal).

It seems using Java.IO.File instead of System.File fixed the issue on Android for me.

I saved to internal App storage root = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); since I only needed the file in my own app, but it seems like root = Android.OS.Environment.ExternalStorageDirectory.ToString(); doesn't throw an exception either. Haven't tested the external storage method much though.

I created this class in my Xamarin.Android project:

[assembly: Xamarin.Forms.Dependency(typeof(FileStorageService))]
namespace MyApp.Droid.Services
{
    public class FileStorageService: IFileStorageService
    {
        private string _rootPath;
        private const string _appFolder = "MyAppFolder";

        public FileStorageService()
        {
            var root = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
            _rootPath = $"{root}/{_appFolder}";
        }

        public async Task WriteFile(string fileName, MemoryStream stream, string relativePath = "")
        {
            try
            {
                if(!relativePath.IsNullOrEmpty() && relativePath?[0] != '/')
                {
                    relativePath = $"/{relativePath}";
                }

                var fileDirectory = new Java.IO.File($"{_rootPath}{relativePath}");
                fileDirectory.Mkdir();
                var file = new Java.IO.File(fileDirectory, fileName);

                if (file.Exists())
                {
                    file.Delete();
                }

                using (var outputStream = new FileOutputStream(file))
                {
                    await outputStream.WriteAsync(stream.ToArray());

                    outputStream.Flush();
                    outputStream.Close();
                }
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex.ToString());
            }
        }

        public async Task<byte[]> ReadFile(string fileName, string relativePath = "")
        {
            try
            {
                if (!relativePath.IsNullOrEmpty() && relativePath?[0] != '/')
                {
                    relativePath = $"/{relativePath}";
                }

                var fileDirectory = new Java.IO.File($"{_rootPath}{relativePath}");
                var file = new Java.IO.File(fileDirectory, fileName);

                if (!file.Exists())
                {
                    return null;
                }

                byte[] fileContent = new byte[file.Length()];

                using (var inputStream = new FileInputStream(file))
                {
                    await inputStream.ReadAsync(fileContent);
                    inputStream.Close();
                }

                return fileContent;

            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex.ToString());
            }
        }
    }
}

And its interface in my Xamarin.Forms project:

    public interface IFileStorageService
    {
        Task WriteFile(string fileName, MemoryStream stream, string relativePath = "");
        Task<byte[]> ReadFile(string fileName, string relativePath = "");
    }

Where you want to save your file in your shared code:

await DependencyService.Get<IFileStorageService>().WriteFile(fileName, memoryStream, relativePath);

Where you want to read your file in your shared code:

var fileContent = await DependencyService.Get<IFileStorageService>().ReadFile(fileName, relativePath);

Hope this helps!

CVStrydom
  • 11
  • 5