flutter-permission-handler icon indicating copy to clipboard operation
flutter-permission-handler copied to clipboard

Storage Permission not working

Open gegobyte opened this issue 1 year ago • 9 comments

🔙 Regression

I have an app which asks user for storage permission and then proceeds to download a file in the Download directory on the device. I am using the latest version of Permission Handler which is 10.0.0 but on my new app created with the latest version of Flutter, getting this error:

FileSystemException: Cannot open file, path = '/storage/emulated/0/Download/abc.pdf' (OS Error: Permission denied, errno = 13)

Here is the code for request permission and saving the file to Download folder:

try {
      final output = await getExternalStorageDirectory();
      RegExp pathToDownloads = RegExp(r'.+0\/');
      final outputPath = '${pathToDownloads.stringMatch(output!.path).toString()}Download'; // returns /storage/emulated/0/Download
      final filePath = '$outputPath/abc.pdf';
      var file = File(filePath);

      // Ask for storage permission
      if (await Permission.storage.request().isGranted) {
        await file.writeAsBytes(pdfBytes);
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text('File has been downloaded'),
            duration: Duration(seconds: 2),
          ),
        );
      }
    } catch (error) {
      print(error);
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text(
              'Allow storage permission so that file pdf can be saved'),
          duration: Duration(seconds: 2),
        ),
      );
    }

The above code asks for permission but despite tapping on Allow, the catch part is triggered and it gives the above permission error. Permission is also set in the manifest file:

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

Old (and correct) behavior

The above code used to work flawlessly on my old app and still works with the latest version 10.0.0 but my new app created with latest version of Flutter does not work.

Current behavior

These are the minimum and target sdk version in build.gradle

minSdkVersion 21
targetSdkVersion 33

Configuration

Permission Handler Version: 10.0.0 Flutter Version: 3.0.5

Platform:

  • [ ] :iphone: iOS
  • [x] :robot: Android

gegobyte avatar Aug 04 '22 12:08 gegobyte

Hi @gegobyte, It seems like I can reproduce it half of the time using your code strange enough. I had it succeeded, where the file abc.pdf is created. But also times where he said the permission wasn't granted.

I tested it on API 31 (Android 12).

Can you provide me a bit more information, and tell me on what Android version you're testing this?

JDDV avatar Aug 08 '22 11:08 JDDV

Can you provide me a bit more information, and tell me on what Android version you're testing this?

I've also tested on Android 12. I am also getting the same result - sometimes it downloads successfully, sometimes I get permission error.

gegobyte avatar Aug 09 '22 09:08 gegobyte

@JDDV Do you recommend any temporary solution until this is fixed?

gegobyte avatar Aug 24 '22 15:08 gegobyte

Any fix for this?

armandojimenez avatar Aug 30 '22 01:08 armandojimenez

@gegobyte you need to use "manageExternalStorage" permission both at runtime and in manifest along with storage permission.

naumanmir avatar Sep 01 '22 08:09 naumanmir

The temporary solution is to go to the app's settings and revoke the file permission, then regrant the permission. Then you can open the app again and it should have file access.

PeterNjeim avatar Sep 01 '22 17:09 PeterNjeim

Android 13: works fine Android 12 and 12.1/12L: permission is "fake" granted, user needs to go to app's settings (in Android settings) and revoke and regrant the file access permission for it to actually apply. Android 11: needs testing Android 10: needs testing

This is with WRITE_EXTERNAL_STORAGE permission with a targetSdkVersion of 29 (Android 10), that way I can use the requestLegacyExternalStorage="true" option.

Someone else should test this on Android 11 and Android 10 to see if it's limited to Android 12 and 12.1 / 12L only

PeterNjeim avatar Sep 01 '22 18:09 PeterNjeim

@gegobyte you need to use "manageExternalStorage" permission both at runtime and in manifest along with storage permission.

Would the app not get rejected after using manage external storage permission? I have read a few instances of apps getting rejected using this permission and targeting Android 11 without giving a good reason.

gegobyte avatar Sep 14 '22 11:09 gegobyte

Can people try my workaround? I'm waiting to see if it's a real workaround or not, 2 people have had success with it so far

Edit: 4 now

PeterNjeim avatar Sep 14 '22 14:09 PeterNjeim

Android 33 Emulator not working

Shvet avatar Sep 30 '22 10:09 Shvet

I have the exact same problem, very similar code with:

minSdkVersion 21 targetSdkVersion 33

Checking on a physical device, there is no permission popup.

dsingh06 avatar Oct 16 '22 14:10 dsingh06

@dsingh06 can you try my workaround and reply back to me?

PeterNjeim avatar Oct 16 '22 14:10 PeterNjeim

@dsingh06 can you try my workaround and reply back to me?

Hi, it is not fully clear to me what your workaround is and steps to be followed.

When I goto app settings, I cannot see individual permissions mentioned where I can revoke them (mentioning it in case this is part of your workaround)

dsingh06 avatar Oct 16 '22 16:10 dsingh06

@dsingh06 See the attached images. Press "Don't allow" then "Allow" Screenshot_20221016-134754_Settings~2.png

Screenshot_20221016-134625_Permission_controller~2.png

Screenshot_20221016-134923_Permission_controller~2.png

PeterNjeim avatar Oct 16 '22 16:10 PeterNjeim

I do not see 'Files Permission' mentioned anywhere (neither in 'Allowed' nor 'Not Allowed'. My Manifest files do have external storage mentioned. Screenshot 2022-10-16 at 23 33 56

dsingh06 avatar Oct 16 '22 22:10 dsingh06

@dsingh06 The lack of the permission in the permissions list is probably your problem, not related to this issue. Since you're targeting Android SDK 33, I don't believe you can use external storage permission anymore. Target a lower SDK version and try again

PeterNjeim avatar Oct 16 '22 22:10 PeterNjeim

I change permmission in settings ,and it work.but it's not a good method for user.

StarkZzzOoo avatar Nov 21 '22 10:11 StarkZzzOoo

I have the same problem. Emulator does not ask External Storage Permission. I load the .apk to my Android 11, API 33 phone, and it works fine. I use the latest Android Studio. Both Emulator and Phone ask AUDIO permission though.

aacsus avatar Dec 05 '22 17:12 aacsus

@aacsus can you try my workaround and see if it works?

PeterNjeim avatar Dec 05 '22 22:12 PeterNjeim

@aacsus can you try my workaround and see if it works?

I tried to downgrade SDK 33 to SDK 30. Everything got screwed up. A lot of errors. I then lowered the other components' versions too. No help. SDK 30 was pushing me to SDK 31. When switched to 31, it in turn pushed me to 32. I ended up going back to SDK 33. Now, it stopped asking AUDIO too. No permissions asked, it runs the program (in emulator)!

aacsus avatar Dec 09 '22 18:12 aacsus

@aacsus Which permission are you requesting? If you can't see the permission in the settings page, then you probably are using a deprecated permission.

PeterNjeim avatar Dec 09 '22 20:12 PeterNjeim

@PeterNjeim FILE and AUDIO permissions (multi permissions). I improved the code little bit, it started asking AUDIO again (in SDK 33). However, FILE permission is still the same; works in Android phone (V11, API 33), but does not work in the Emulator. The SETTINGS page in Emulator does not show FILE permission, while both are visible in phone.

aacsus avatar Dec 28 '22 16:12 aacsus

Does anyone have a real fix for this issue yet? Please don't tell me that the user has to revoke rights in the settings and regrant them, that is not a fix 😂

await Permission.storage.request().isGranted does not show a popup to grant permission. Other permissions work fine.

aeaevo avatar Jan 02 '23 20:01 aeaevo

It's fine to say you want a fix (that's what everyone here is for anyways), it's not fine to say someone else is lying about their "fix". I never said it was a fix, I said it was a workaround, which is a big difference. My message only serves to help people temporarily while a fix is waited for. Please adjust your comment to say that you don't care about workarounds, instead of misrepresenting my comments

PeterNjeim avatar Jan 02 '23 21:01 PeterNjeim

@PeterNjeim I really did not mean to offend you at all and I do appreciate everyone's efforts here! Classic misunderstanding... Let's just concentrate on solving this issue. I am curious how such a major bug persists since August last year - is there a bigger underlying problem?

Did someone try to switch from stable flutter version to master?

aeaevo avatar Jan 03 '23 05:01 aeaevo

Same issue for flutter latest stable & master channel

aeaevo avatar Jan 03 '23 06:01 aeaevo

Same here, https://github.com/Baseflow/flutter-permission-handler/issues/972

blue492 avatar Jan 03 '23 08:01 blue492

I guess @PeterNjeim already did mention the main reason why most of us (maybe even all of us) are facing this problem earlier in this thread. We don't need to ask for the READ_EXTERNAL_STORAGE permission since targetSDK 33 anymore. Check this thread on StackOverflow.

So this works without any permission request:

Directory? storageDirectory; 
if (Platform.isAndroid) {
  storageDirectory = await getExternalStorageDirectory();
} else if (Platform.isIOS) {
  storageDirectory = await getApplicationDocumentsDirectory();
}

aeaevo avatar Jan 03 '23 08:01 aeaevo

this issue still presents till today

NawrasBukhari avatar Mar 15 '23 15:03 NawrasBukhari

I had the same problem as described here and I haven't found any definitive solution so far. Here's what I did to resolve it: 1o. I put this permission in the AndroidManifest.xml: <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

2o. I updated the package_info_plus, file_picker, permission_handler and device_info_plus to the latest versions and everything is working again.

3o. However, it is worth remembering that it is necessary to treat the SDK version to verify the permissions and plataform (IOS or Android) commands:

  Future<bool> ePermitidoGravar() async {
    DeviceInfoPlugin plugin = DeviceInfoPlugin();
    AndroidDeviceInfo android = await plugin.androidInfo;
    if( android.version.sdkInt < 33 ){
      var status = Platform.isAndroid
        ? await Permission.storage.status
        : await Permission.photos.status;               //https://github.com/Baseflow/flutter-permission-handler/issues/440
      if (!status.isGranted) {
        if(Platform.isAndroid){
          status = await Permission.storage.request();
          if(status.isPermanentlyDenied){
            await openAppSettings();
            status = await Permission.storage.status;              //https://github.com/Baseflow/flutter-permission-handler/issues/440
          }
        }else{
          status = await Permission.photos.request();
          if(status.isPermanentlyDenied){
            await openAppSettings();
            status = await Permission.photos.status;               //https://github.com/Baseflow/flutter-permission-handler/issues/440
          }
        }
        if(!status.isGranted){
          return false;
        }
      }
    }else {
      var status = Platform.isAndroid
        ? await Permission.manageExternalStorage.status
        : await Permission.photos.status;                 //https://github.com/Baseflow/flutter-permission-handler/issues/440
      if (!status.isGranted) {
        if (Platform.isAndroid) {
          status = await Permission.manageExternalStorage.request();
          if(status.isPermanentlyDenied){
            await openAppSettings();
            status = await Permission.storage.status;              //https://github.com/Baseflow/flutter-permission-handler/issues/440
          }
        } else {
          status = await Permission.photos.request();
          if (status.isPermanentlyDenied) {
            await openAppSettings();
            status = await Permission.photos.status;
          }
        }
      }
    }
    return true;
  }

AndersonMichellin avatar Apr 26 '23 23:04 AndersonMichellin