ivehement / saf

Flutter plugin that leverages Storage Access Framework (SAF) API to get access and perform the operations on files and folders.
https://pub.dev/packages/saf
MIT License
17 stars 17 forks source link

Bug: getDirectoryPermission does not work for `!isDynamic` #8

Open 4ntoine opened 2 years ago

4ntoine commented 2 years ago

Here is the code i use:

var saf = Saf("/storage/emulated/0/MyApp");

Then i check the permission:

   var permission = await _saf!.getDirectoryPermission(
        grantWritePermission: true,
        isDynamic: false
    );

Before the file manager is shown the uri is content://com.android.externalstorage.documents/tree/primary%3A%2Fstorage%2Femulated%2F0%2FMyApp. The file manager is shown and i just click "Use this directory" and tap "Allow". After the file manager is shown the uri becomes content://com.android.externalstorage.documents/tree/primary%3AMyApp (selectedDirectoryUri value).

So the following is true and the permission is released:

   if (!isDynamic && selectedDirectoryUri != _uriString) {
        releasePersistableUriPermission(selectedDirectoryUri);
        return false;
      }

As a result, no permission is granted.

4ntoine commented 2 years ago

PS. It works for isDynamic: true, but i'd like to persist the access across app relaunches.

4ntoine commented 2 years ago

It looks like the following:

    if (isDynamic) {
        _uriString = selectedDirectoryUri;
        _directory = makeDirectoryPath(_uriString!);
      }

should be done independent of isDynamic value. What do you think?

jvoltci commented 2 years ago

Hi @4ntoine , You can achieve the mentioned use case using static call. await Saf.getDynamicDirectoryPermission()

4ntoine commented 2 years ago

@jvoltci How do i get the path then? Also i need persistable permission

jvoltci commented 2 years ago

It looks like the following:

    if (isDynamic) {
        _uriString = selectedDirectoryUri;
        _directory = makeDirectoryPath(_uriString!);
      }

should be done independent of isDynamic value. What do you think?

Interesting. Surely we can, let's improve a bit here and there.

Hey! just curious, is this your channel? saf featured in top 10

4ntoine commented 2 years ago

@jvoltci nope

jvoltci commented 2 years ago

@jvoltci How do i get the path then? Also i need persistable permission

You can get it by using again a static method call! await Saf.getPersistedPermissionDirectories()

Hope it helps!

4ntoine commented 2 years ago

@jvoltci Thank you, will take a look tomorrow

4ntoine commented 2 years ago

@jvoltci i can't understand where is the bug, but the paths look strange.

As reported earlier, i use the "MyApp" directory in external storage root. Then _saf!.getDirectoryPermission() is called and the initialUri="content://com.android.externalstorage.documents/tree/primary%3A%2Fstorage%2Femulated%2F0/document/primary%3A%2Fstorage%2Femulated%2F0%2FMyApp". It's navigated in File manager correctly and i just click "Use this directory" and the selectedDirectoryUri= "content://com.android.externalstorage.documents/tree/primary%3AMyApp".

I'd expect it to be not changed (as i haven't changed the dir), but URI is different!

As a result the selectedDirectoryUri != _uriString is "true" and releasePersistableUriPermission is called and false returned.

Am i missing anything?

PS.

If i remove isDynamic check as i suggested it works (i'm able to get the list of the files in the directory), but due to _directory = makeDirectoryPath(_uriString!) i get "MyApp" as full path and some other functions (like Saf.getPersistedPermissionDirectories()) return list of "MyApp" instead of "/storage/emulated/0/MyApp" (which is incorrect).

PPS.

I see you implemented Uri <-> String convertation yourself, how about using (or at least comparing with) existing "uri_to_file" pub?

Ruwasoft commented 2 years ago

also I have the issue,

Saf saf = Saf(path);

      await saf.getDirectoryPermission(isDynamic: true);

      var cachedFilesPath = await saf.cache();

      for (String path in cachedFilesPath!) {
        if (path.endsWith(images ? 'jpg' : 'mp4')) {
          photos.add(File(path));
        }
      }

I'm using this codes to request directory permission and read the files inside the path, Its working fine. But My issue is its Always requesting the permission every time when I open the app. How to request permission only once if granted.

Jaganvk29 commented 2 years ago

DID YOU FIND A WAY?

dhaval-k-simformsolutions commented 2 years ago

Check shared_storage as an alternate solution to this.

ashwin066 commented 1 year ago

Its Always requesting the permission every time when I open the app. How to request permission only once if granted. Is there any solution for this?

path "/storage/emulated/0/Android/media/com.whatsapp/WhatsApp/Media/.Statuses" bool? isGranted = await saf.getDirectoryPermission(isDynamic: true);

ATOISABOY commented 6 months ago

Did anybody found a way ? Permission does not persist after relaunch

ATOISABOY commented 6 months ago

Its Always requesting the permission every time when I open the app. How to request permission only once if granted. Is there any solution for this?

path "/storage/emulated/0/Android/media/com.whatsapp/WhatsApp/Media/.Statuses" bool? isGranted = await saf.getDirectoryPermission(isDynamic: true);

Did you find a solution ?

sumit-chavla-hra commented 2 weeks ago

Its Always requesting the permission every time when I open the app. How to request permission only once if granted. Is there any solution for this? path "/storage/emulated/0/Android/media/com.whatsapp/WhatsApp/Media/.Statuses" bool? isGranted = await saf.getDirectoryPermission(isDynamic: true);

Did you find a solution ?

@ATOISABOY similar feature is implemented at https://github.com/krupal4/StatusSaver using this package.

@dhaval-k-simformsolutions @4ntoine @Ruwasoft @ashwin066 @Jaganvk29