user6159419
user6159419

Reputation: 247

Xamarin.Android : System.UnauthorizedAccessException: Access to the path is denied

I am targeting Android API 30. My app was storing log file and taking database backup in location "/storage/emulated/0/SpecialDir/". Now I am facing access denied issue while my app was workinng fine previously. I got an overview about scoped storage and came to know that we have some managed locaitons where we can store our data accordingly. i.e Audio, Video, Images, and Download

Can anyone please guide me what should i do.

string dir = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.ToString(), "LogFolder");
if (Directory.Exists(dir))
{
    return Path.Combine(dir, "MyLogFile.txt");
}
try
{
   string newDirectory = Directory.CreateDirectory(dir).FullName;
   path = Path.Combine(newDirectory, "MyLogFile.txt");
   System.IO.File.WriteAllText(path, "This is some testing log.");
}
catch (Exception ex)
{
   string msg = ex.Message;
}

The above code is used to make 'LogFolder' if not exist and 'MyLogFile' as well. What changes do i needed to make it compatiable to Android 10. Thankyou

Upvotes: 0

Views: 3205

Answers (1)

Leo Zhu
Leo Zhu

Reputation: 15021

In Android 10, Google has introduced a new feature for external Storage. Its name is Scoped Storage. Google officially translates it as partitioned Storage, or Scoped Storage.The intent is to limit what programs can do with public directories in external storage. Partitioned storage has no effect on either the internal storage private directory or the external storage private directory.In short, in Android 10, there is no change to private directory reads and writes, and you can still use the File set without any permissions. For reading and writing to public directories, you must use the API provided by MediaStore or the SAF (storage access framework), which means you can no longer use the File set to manipulate public directories at will.

If you set targetSdkVersion above 29,you could try to add below codes into your AndroidManifest.Then you could access the File as before.

<manifest ... >
   <application android:requestLegacyExternalStorage="true" ... >
       ...
   </application>
</manifest>

Update (you could try this for public external storage ):

var path = Android.OS.Environment.GetExternalStoragePublicDirectory("LogFolder").AbsolutePath;
Java.IO.File file = new Java.IO.File(path);


if (!file.Exists())
   {
     file.Mkdirs();
   }
try
   {
     FileWriter fw = new FileWriter(path + Java.IO.File.Separator + "MyLogFile.txt");
     fw.Write("This is some testing log.");
     fw.Close();
   }
catch (Exception ex)
   {

      string msg = ex.Message;
   }

Update for Android 11:

add MANAGE_EXTERNAL_STORAGE permission in your AndroidManifest.

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

in your activity:

  if (Environment.IsExternalStorageManager)
        {
            var path = Android.OS.Environment.GetExternalStoragePublicDirectory("LogFolder").AbsolutePath;
            Java.IO.File file = new Java.IO.File(path);

            if (!file.Exists())
            {
                file.Mkdirs();
            }
            try
            {
                FileWriter fw = new FileWriter(path + Java.IO.File.Separator + "MyLogFile.txt");
                fw.Write("This is some testing log.");
                fw.Close();
            }
            catch (Exception ex)
            {

                string msg = ex.Message;
            }
   
        }
        else
        {
         
            StartActivityForResult(new Intent(Settings.ActionManageAllFilesAccessPermission), 0);
        }
 

Upvotes: 2

Related Questions