SNNafi / media_store_plus

To use Android MediaStore API in Flutter
https://pub.dev/packages/media_store_plus
MIT License
34 stars 17 forks source link

MediaStorePlugin.saveFile add .mp3 to file and not delete existing file (API 29) #4

Open Fifut opened 1 year ago

Fifut commented 1 year ago

Hello!

MediaStorePlugin.saveFile add .mp3 to file and not delete existing file. Instead, create a new file with (1) on the name. Only on API 29. No problem on API 29 to 33

Here the log:

D/DirName (19015): Notifications
D/DisplayName My sound.wav(19015): null
D/saveFile(19015): My sound.wav

2023-01-25 20_50_45-Emulator

SNNafi commented 1 year ago

Did you add this in the manifest ?

<uses-permission
        android:name="android.permission.READ_EXTERNAL_STORAGE" <!-- To read all files until API level 32 -->
        android:maxSdkVersion="32" />

    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE" <!-- To write all files until API level 29. We will MediaStore from API level 30 -->
        android:maxSdkVersion="29" />

    <application
        ---------------------------
        android:requestLegacyExternalStorage="true"> 
        <!-- Need for API level 29. Scoped Storage has some issue in Android 10. So, google recommanded to add this. -->
        <!-- Read more from here: https://developer.android.com/training/data-storage/shared/media#access-other-apps-files-->
    </application>
Fifut commented 1 year ago

Yes

SNNafi commented 1 year ago

Just have tested it with my device (API 29). Couldn't reproduce.

Fifut commented 1 year ago

Maybe a problem with my API29 emulator?

SNNafi commented 1 year ago

Yes, I think so. Can you manage to test with a real device? Then we can be sure about this.

Fifut commented 1 year ago

Unfortunately, I don't have a real device with API 29.

SNNafi commented 1 year ago

This is an edge case. In your case, there is no record of your file in the media store internal db (That's why the log says i.e.D/DisplayName My sound.wav(19015): null) BUT there is an actual file that exists in that location. So we need first to check if any actual file (not only the media store record) exists with the same name, then overwrite that file while saving.

KyleKun commented 1 year ago

Facing the same issue on API 33, any plans on implementing this fix @SNNafi ? Do you believe if I add the file exists check here it will suffice? I don't have much experience with Kotlin...

Edit: I found a dirty workaround far from perfect, which prevents me from opening a PR, but at least it works:

First I force MediaStore to scan the file using the getUriFromFilePath. Even after this, for some reason the regular delete method still fails, so I edited the deleteFileUsingUri to allow using contentResolver.delete in this commit. Basically, this works by deleting the file with the URI after forcing MediaStore to scan it. Then in Flutter, deleting a file looks like this:

await mediaStore.getUriFromFilePath(path: filePath).then((uri) async {
  await mediaStore.deleteFileUsingUri(
    uriString: uri.toString(),
    forceUseMediaStore: true,
  );
});

The only problem is that after accepting the popup to modify the file, the action isn't performed (I have to call it again). Will try to investigate this further.

SNNafi commented 5 months ago

I am checking this now. How did you reproduce this? @KyleKun

SNNafi commented 5 months ago

It will also create duplicate files If you don't have read permission. In this case, the plugin can't check for existing files. You can check this thread for detailed info. Is this your case?

SNNafi commented 5 months ago

@Fifut, How did you reproduce this?

afghandev5 commented 1 day ago

Hey guys @SNNafi and @KyleKun Is there any way to delete files from desired folders i mean something like this folder android/emulated/0/Songs/ABFolder/NextFolder/1234.mp3 I looked at the package there was nothing for deleting files from desired folders!!

SNNafi commented 17 hours ago

There is

deleteFile({required String fileName, required DirType dirType, required DirName dirName, String? relativePath}) → Future<bool>

function to delete a file. (The doc text is wrong. I will update it.)

BUT Do you understand the MediaStore API? There is no directory called Songs in MediaStore collections.

Here are the directories that are available with MediaStore API. https://developer.android.com/training/data-storage/shared/media

You can't use any other directory with MediaStore API besides these directories.

SNNafi commented 17 hours ago

However, there is a method called requestForAccess() to request access to particular files and it returns DocumentTree. That contains uriString.

Then you can use deleteFileUsingUri() with the URI to delete the file.