Baseflow / flutter-permission-handler

Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions.
https://baseflow.com
MIT License
1.99k stars 814 forks source link

A request for permissions is already running - How stop request? - 5.0.0+hotfix.3 #245

Closed pks-1981 closed 4 years ago

pks-1981 commented 4 years ago

Up to permission_handler 5.0.0+hotfix.2. Problem is still here.

Flutter 1.12.13+hotfix.8 • channel stable • https://github.com/flutter/flutter.git Framework • revision 0b8abb4724 (7 weeks ago) • 2020-02-11 11:44:36 -0800 Engine • revision e1e6ced81d Tools • Dart 2.7.0

I have a simple app, where i ask permission storage.

Future<void> _attachFile() async {
    requestPermission(Permission.storage);

    bool storage = await isPermissionGranted(Permission.storage);

    if (!storage) {
      _showInSnackBar(Localization.of(context).translate('access_file'));
      return;
    }
    _attachedFile = await FilePicker.getFilePath(type: FileType.any);
    setState(() {});
  }

  Future<bool> isPermissionGranted(Permission permission) async {
    return await permission.isGranted;
  }

  Future<void> requestPermission(Permission permission) async {
    await permission.request();
  }

1 - Ask a permission, and say "no" (run Future _attachFile()) 2- When ask again (run Future _attachFile()) i have a error E/flutter (11118): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: PlatformException(PermissionHandler.PermissionManager, A request for permissions is already running, please wait for it to finish before doing another request (note that you can request multiple permissions at the same time)., null) - in log And nothing happens in mobile

What i'am doing wrong? Or in new version need work only with status? Like this:


var status = await Permission.camera.status;
if (status.isUndetermined) {
  // We didn't ask for permission yet.
}

You can can also directly ask the permission about its status.
if (await Permission.location.isRestricted) {
  The OS restricts access, for example because of parental controls.
}

PS Sorry for my English :-)

jesusmgg commented 4 years ago

I'm also having this same problem. Is there a certain way to determine if a permission request is already running?

If there is no such feature and it makes sense to you, I can try to add it.

pks-1981 commented 4 years ago

I expect the following: Access request If the user replied "Deny" - the end of this request Message output - access is needed for ... A new access request, if the user decides to give permission - now this is possible only if you restart the application How do I implement this?

PS Sorry for my English :-)

pks-1981 commented 4 years ago

Update to hotfix3. My problem is still here.

E/flutter ( 7630): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: PlatformException(PermissionHandler.PermissionManager, A request for permissions is already running, please wait for it to finish before doing another request (note that you can request multiple permissions at the same time)., null) E/flutter ( 7630): #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:569:7) E/flutter ( 7630): #1 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:321:33) E/flutter ( 7630): E/flutter ( 7630): #2 MethodChannelPermissionHandler.requestPermissions (package:permission_handler_platform_interface/src/method_channel/method_channel_permission_handler.dart:66:30) E/flutter ( 7630): #3 PermissionListActions.request (package:permission_handler/permission_handler.dart:104:16) E/flutter ( 7630): #4 PermissionActions.request (package:permission_handler/permission_handler.dart:44:26) E/flutter ( 7630): #5 _State._attachFile (package:easy_ticket_creator/data/pages/etc_edit.dart:283:30) E/flutter ( 7630): #6 _State._addFile (package:easy_ticket_creator/data/pages/etc_edit.dart:265:11) E/flutter ( 7630): #7 AnimatedChild._performAction (package:flutter_speed_dial/src/animated_child.dart:71:24) E/flutter ( 7630): #8 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:706:14) E/flutter ( 7630): #9 _InkResponseState.build. (package:flutter/src/material/ink_well.dart:789:36) E/flutter ( 7630): #10 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24) E/flutter ( 7630): #11 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:486:11) E/flutter ( 7630): #12 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:264:5) E/flutter ( 7630): #13 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:199:7) E/flutter ( 7630): #14 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:467:9) E/flutter ( 7630): #15 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:76:12) E/flutter ( 7630): #16 PointerRouter._dispatchEventToRoutes. (package:flutter/src/gestures/pointer_router.dart:117:9) E/flutter ( 7630): #17 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:379:8) E/flutter ( 7630): #18 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:115:18) E/flutter ( 7630): #19 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:101:7) E/flutter ( 7630): #20 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:218:19) E/flutter ( 7630): #21 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:198:22) E/flutter ( 7630): #22 GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:156:7) E/flutter ( 7630): #23 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:102:7) E/flutter ( 7630): #24 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:86:7) E/flutter ( 7630): #25 _rootRunUnary (dart:async/zone.dart:1138:13) E/flutter ( 7630): #26 _CustomZone.runUnary (dart:async/zone.dart:1031:19) E/flutter ( 7630): #27 _CustomZone.runUnaryGuarded (dart:async/zone.dart:933:7) E/flutter ( 7630): #28 _invoke1 (dart:ui/hooks.dart:273:10) E/flutter ( 7630): #29 _dispatchPointerDataPacket (dart:ui/hooks.dart:182:5) E/flutter ( 7630):

mvanbeusekom commented 4 years ago

Hi @KirillNNRUS, it is a bit hard to judge what really is going on since the code sample is a bit limited. I do however noticed that you are not awaiting the call to requestPermission(Permission.storage). Theoretically this could cause code to continue running into for example the FilePicker code (which also internally can take care of permission handling), which might cause the conflict.

I am trying to reproduce it but the example app doesn't show this behaviour, maybe it is helpful for you to have a look there: https://github.com/Baseflow/flutter-permission-handler/tree/develop/permission_handler/example

If you could supply a sample to reproduce the problem I would be more then happy to have a more detailed look.

pks-1981 commented 4 years ago

@mvanbeusekom Please check your email :-)

pks-1981 commented 4 years ago

Upgrade Flutter to: Flutter 1.12.13+hotfix.9 • channel stable • https://github.com/flutter/flutter.git Framework • revision f139b11009 (2 days ago) • 2020-03-30 13:57:30 -0700 Engine • revision af51afceb8 Tools • Dart 2.7.2

Problem is still here :-(

ajviera commented 4 years ago

Same problem here. Any solutions?

pks-1981 commented 4 years ago

Same problem here. Any solutions?

I haven't solution. All hope in Maurits, which I allowed access to my application :-)

mvanbeusekom commented 4 years ago

I can indeed reproduce the issue in the code base of @KirillNNRUS but I was not yet able to find a solution unfortunately.

In the Android code I do the following:

permissionRegistry.addListener(
        new RequestPermissionsListener(
                activity,
                requestResults,
                (Map<Integer, Integer> results) -> {
                    ongoing = false;
                    successCallback.onSuccess(results);
                })
);

ongoing = true;

ActivityCompat.requestPermissions(
        activity,
        requestPermissions,
        PermissionConstants.PERMISSION_CODE);

This is the part where we request the permissions on the native side. As you can see I set the ongoing boolean to true just before we start and it is set to false when the RequestPermissionListener is called. This particular exception is thrown when the ongoing variable is still on true when the next request comes in.

Strange thing is that I cannot reproduce it with the example app or a new app if I create it. But somehow it does show up in @KirillNNRUS (and I guess others) applications. Maybe somebody has an idea that could put me on the right track?

anisalibegic commented 4 years ago

I have the same problem and only workaround that worked for me is checking if permission is already granted before requesting it.

final granted = await permission.isGranted;
if (granted ?? false) {
    return true;
}

return await permission.request().isGranted;

I hope it works for you also until author takes a look at this problem.

pks-1981 commented 4 years ago

a new app if I create it.

@mvanbeusekom - Are your create new app with Kotlin support? My app maded with main.kt (Kotlin support) - maybe problem in this?

I will try soon create new project, and "copy" "Dart" files, and "Android properties" files to him. And I will write whether it helped or not.

mvanbeusekom commented 4 years ago

@KirillNNRUS yes I noticed you used Kotlin in your App, so I made sure I also created a new App using Kotlin.

I am still not sure what is going on, I took the implementation that I posted above from one of the Flutter camera plugin (more specifically: https://github.com/flutter/plugins/blob/3af2bfa201744f8c4949c874bfebd8a4070e2636/packages/camera/android/src/main/java/io/flutter/plugins/camera/CameraPermissions.java#L25).

Maybe someone can compare the requestPermissions method from my PermissionManager class with the requestPermissions method from the CamaraPermissions class of the Flutter camera plugin to see if they can spot something which could cause this bug?

pks-1981 commented 4 years ago

@mvanbeusekom Here is the result: I created new Flutter projects (with and without Kotlin support) And... All work fine :-) in the both project :-) I swear, i did "flutter clean" many time! Maybe "New Flutter Project" creates Project which is very different from "My Old Flutter Project", i mean Android components, settings and other? My project was created "in time" Flutter 1.0...

I'll try to compare what I can. And write what I found.

PS Many thanks to all for the help and support, and especially Maurits :-) And need to remember another way to work with Flutter bugs :-)

mvanbeusekom commented 4 years ago

I have been going over this and turns out you need to migrate your app if you have created it using the pre-1.12 flutter templates. Here is a guide to do so: https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects (or you could of course copy your code over to a newly generated App ;) )

I will also add this to the README.md for further references. Thanks for thinking with me everybody!

oliverbytes commented 3 years ago

I'm using permission_handler: 5.1.0+2, Android v2 embedding but still getting this error via Crashlytics.

Non-fatal Exception: io.flutter.plugins.firebase.crashlytics.FlutterError
PlatformException(PermissionHandler.PermissionManager, A request for permissions is already running, please wait for it to finish before doing another request (note that you can request multiple permissions at the same time)., null, null)
StandardMethodCodec.decodeEnvelope (StandardMethodCodec.java:581)
MethodChannel._invokeMethod (MethodChannel.java:158)
MethodChannelPermissionHandler.requestPermissions (MethodChannelPermissionHandler.java:66)
PermissionActions.request (PermissionActions.java:49)
FuturePermissionStatusGetters.isGranted (FuturePermissionStatusGetters.java:93)
UIUtils.download (UIUtils.java:129)

code

final downloadsPermission = Platform.isIOS ? Permission.photos : Permission.storage;
if (!await downloadsPermission.request().isGranted) return;

doctor

✓] Flutter (Channel stable, 2.0.1, on macOS 11.1 20C69 darwin-x64, locale en-PH)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.1)
[✓] VS Code (version 1.54.2)
[✓] Connected device (4 available)
XuanTung95 commented 3 years ago

I ran into the same issue. Turn out, the reason is I override this method without calling super()

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
}

in MainActivity.java. Remove this method do the work.

kamami commented 2 years ago

Still in issue in flutter 2.10

sunilguptasg commented 1 year ago

For now this is what I have done:

while (true) { try { permissionStatus = await permission.request(); break; } catch (e) { await Future.delayed(Duration(milliseconds: 500), () {}); } }

BuildFaild commented 5 days ago

Still in issue in flutter 3.22.2