Home > Back-end >  deleting a file on Maui app platform Android
deleting a file on Maui app platform Android

Time:08-12

I have a maui app which reads a data log on an SD card (in Android the SD card is in a USB reader attached - filemanagers and the maui file picker happily see hte usb external drive and read and open file) Info is extracted from the file (csv) written to SQL then the file is backed up to cloud It is important now to remove datalog from the SD card -

the problem appears to be only on Android and even then it performs the deletion on teh emulator as expected. On Android >10 (Iam targetting 11 sdk 31) on real phones it says it has deleted the file (file.exists returns false) but the file still exists on sd card

I know Android tightened up permissions and I have the request permissions in the manifest file I also have code whihc requests user to confirm permission but still delete does not work as stated in Microsoft Docs

I am aware but dont quite understand the mechanism where Android makes a copy of an opened file but this doesnt seem relevant as Ive already opened and read the file. I am also not sure this has anything to do with the fact that I am trying to delete a file on external USB-SD storage - the problem persists if I move the datalog to internal storage such as download.

Android permissions: (you can see Ive thrown kitchen sink at it ;-)

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.MANAGE_USB" />
  <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.USE_CREDENTIALS" />
  <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
  <uses-permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS" />
  <uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Key code is shown below (in this case if the datalog contains less than 300 lines it does not contain useful data so is to be deleted - but the principle is the same once a datalog is fully processed and to be disposed of NB this is on MAUI using VS 2022 17.3 preview 6 fwiw the xamarin Android sdk is v 13 the file delete works on windows - I haven't tried IOS yet as I have had huge difficulty getting my MAC to sync with my VS on windows

In summary the c# code is doing what it says in microsoft docs deleting and reporting file does not exist but in actual fact not doing that!! This is beyond me

does anyone have any ideas please

       var ff1 = System.IO.File.ReadAllLines(csvorig);
       var csvlen= ff1.Length;
        if (csvlen < 300)   // one line per second means 5 mins ignore
        {
            var nl = System.Environment.NewLine;
            var answ = await DisplayAlert(dbpath   nl   "Small file", "the file you've 
               selected contains no flight"   nl   "prob cause = switching on avionics for < 
               5min "   nl   " file should be deleted", "DELETE", "ignore");
        if (answ)
        {
        status = await Permissions.CheckStatusAsync<Permissions.StorageWrite>();
        if (status == PermissionStatus.Denied)
        {
            PermissionStatus status2=awaitPermissions.RequestAsync<Permissions.StorageWrite>();
        }
              /// check permissions AGAIN !! in case problem there
        status = await Permissions.CheckStatusAsync<Permissions.StorageWrite>();
        if (status == PermissionStatus.Denied)
        {
        await DisplayAlert("warn", "Sorry cannot grant permission \n you will need to delete this file using filemanager \n"   csvorig, "cancel");
        return;
        }
        try
            {
             // ensure that file attribs are normal // saw this in one post on file 
             //deleting but not ref maui
            File.SetAttributes(csvorig, FileAttributes.Normal);
            File.Delete(csvorig);
            }
        catch (Exception ee)
            {
          // code never throws exception
            var m = ee.Message;
            await DisplayAlert("", m, "Cancel");
            }
    
        if (File.Exists(csvorig))
        {           
            await DisplayAlert("warn", "failed to delete", "cancel");
        }
        else
        { // file is ALWAYS reported as 'not existing' but is still there next 
          //time use filepicker
        await DisplayAlert(csvorig, "has been deleted", "back"); }
        }
    }










CodePudding user response:

I have done a sample to test, if the app just has the permission about read and write the storage, it can't delete the file in the sdcard or the storage. It can just delete the file in the app's own private folder.

So it need the user to grant the app the permission about managing the storage. You can try to put the following code in the mainactivity.

 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);
}

CodePudding user response:

Thanks to Liyun Zhang I've worked something out I am trying to delete hte 'cahced' file thus - name derived from filepicker that filename is reported as "storage/emulated/0/Android/data/com.companyname.flymaui6/cache/xxxxxxxxxxxxxx/log_2206260834_EGJB.csv"

But actually what I want is the name of the file on the SD card. Filemanager gave me a clue - in properties of a log file on the usb sd card reader it says the path is "/mnt/media_rw/547e-78ae/data_log/log220715_0834XXX.csv" the 547e-78ae is a unique ref of the actual sd card so thats tricky but I know the sd reader will prob be only one with /mnt/media_rw in it so I've implemented this method to get the current SD card path - it just searches for any path with /mnt/media_rw/ and assumes it is the sd card reader (hope that's not too unreliable an assumption.

 private async void chkSD()
{
    try
    {
        var xxx = System.Environment.GetLogicalDrives();
        var messtmp = "";
        foreach (string foldnm in xxx)
        {
            if (foldnm.IndexOf("/mnt/media_rw", StringComparison.OrdinalIgnoreCase) >= 0)
            {
                messtmp = foldnm;
                break;
            }
            else
            {
                messtmp = "..";
            }
        }

        sdcardpath = messtmp   "/data_log/";
        if (messtmp.Contains(".."))
        {
            await DisplayAlert("", "could not find SD card \n Only temporary cached files will be deleted", "cancel");
        }
    } catch
    { 
    }
}

Now I just add the "sdcardpath" to the filename before deleting

this should work universally as one is unlikely to get 2 SD card readers on Android machine and this method picks up the unique sd identifier

I dont yet know if the meadia_rw bit of the path is unuversal but so far it does delete the file on the SD card

If I have copied the log file from the sd card to a dolder on hte Androi machine - that is still a work in progress to find the true path of the file when it is in say \download
But I can live with that it is important to have a clean SD card and avoid having user to mess around with filemanager.

All the other stuff is also true - one needs permissions but it turned out to be about finding the true path (hmm sounds like we need a hallelujah here) . the cached file created by Android is deleted anyway

It would be a lot simpler if I could get the 'true' path somehow from FilePicker

thanks for all help

  • Related