Search code examples
c#androidmaui

MAUI on Android : listing folder contents of an SD Card and writing in it


I've been trying to listing folder contents of an SD Card and write in it in my Android phone using MAUI.

My target is to access a folder (namely : SD card/DCIM/Test EXIF, list its contents and modify/delete file metadata in a batch.

I've been trying for days to no avail, I cannot access the SD Card and have no clues on how to do it. I tried a simple file picker like this :

var result = await FilePicker.Default.PickAsync();
if (result != null)
{
     // Do Stuff
}

The access to the SD Card works but that's not what I want : the file is apparently copied in the cache, and I want the original file to be editable. And I want multiple files to be process, not one by one.

I tried another approach : with GetLogicalDrives()

   string folders = "";
   var xxx = System.Environment.GetLogicalDrives();

   foreach (string foldnm in xxx)
       folders = folders + foldnm + ";";

And in the list, I found "/storage/emulated/0/Android/data" which seems to be the base of the one I'm looking for. So I tried the following :

var files = Directory.GetFiles("/storage/emulated/0/Android/data", "*");

But I have an access denied : System.UnauthorizedAccessException: 'Access to the path '/storage/emulated/0/Android/data' is denied.'. I thought it was a Right Issue, so in Android/Resources.AndroidManifest.xml I added the following lines :

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

Uninstalled / Reinstalled the app and got the same result, so I added in the code a prompt to check and request the read (for now) permission, but the grant prompt never appears :

        PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.StorageRead>();
        if (status == PermissionStatus.Denied)
        {
            await DisplayAlert("Alert", "Permission Denied", "OK");
            // Ask for permission
            status = await Permissions.RequestAsync<Permissions.StorageRead>();
        }

        if (status == PermissionStatus.Granted)
        {
            var files = Directory.GetFiles("/storage/emulated/0/Android/data", "*");
        }

On my device's Settings > Apps > App Info > My App > Permissions : no permission is listed at all.

Any clues ? I'm pulling the rest of my hair out for some days now !

Maybe I'm wrong in my approach, but I'm trying to read/write to my external storage in Android

EDIT : My path was wrong. The address of my SD Card is /storage/3439-3532/. I can list its directories successfully but when trying to access the files, I have an access denied error :

string[] dirs1 = Directory.GetDirectories("/storage/3439-3532/", "*"); // works OK
string[] dirs2 = Directory.GetDirectories("/storage/3439-3532/BEB/", "*"); // works OK
string[] theFiles = Directory.GetFiles("/storage/3439-3532/BEB/", "*"); // KO !

Solution

  • I think I got it. I have to implement the rights differently : In my Android Manifest, just the MANAGE_EXTERNAL_STORAGE was needed :

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

    In my Android >MainActivity.cs, I added a new intent. At the first app launch, it'll ask for the permission :

    public class MainActivity : MauiAppCompatActivity
    {
        // Added this v
        protected override void OnCreate(Bundle savedInstanceState)
        {
            if (!Android.OS.Environment.IsExternalStorageManager)
            {
                Intent intent = new Intent();
                intent.SetAction(Android.Provider.Settings.ActionManageAppAllFilesAccessPermission);
                Android.Net.Uri uri = Android.Net.Uri.FromParts("package", this.PackageName, null);
                intent.SetData(uri);
                StartActivity(intent);
            }
            base.OnCreate(savedInstanceState);
        }
    
    }
    

    Now I can list the files I want, create new directories, new file, etc...

    string[] theFiles = Directory.GetFiles("/storage/3439-3532/DCIM/Camera", "*");
    
    Directory.CreateDirectory("/storage/3439-3532/BEB");
    
    using FileStream outputStream = File.OpenWrite("/storage/3439-3532/BEB/test.txt");
    using StreamWriter streamWriter = new StreamWriter(outputStream);
    await streamWriter.WriteAsync("OKAY");
    

    I still find the hardcoded part of the /storage/thingy/ ugly, but this will do for now.