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

flutter app crashes after pressing back button

Open SashaMyh opened this issue 4 years ago • 7 comments

🐛 Bug Report

when you are in the app permission setting i.e : openAppSettings() and then if you press back button. flutter app crashes.

Expected behavior

if you are in the openAppSettings() and then press back button to return in your app. it should not crashing the app

Example of code :

Map<Permission, PermissionStatus> result = await [
        Permission.storage,
        Permission.manageExternalStorage
      ].request();

if (result[Permission.storage].isGranted && result[Permission.manageExternalStorage].isGranted) {
        print("permission granted");
 } else {
      if(result[Permission.manageExternalStorage].isPermanentlyDenied || result[Permission.storage].isPermanentlyDenied){
          print("Storage permission is permanently Denied");
          openAppSettings();
      }
 }

error after crashing :

D/AndroidRuntime(18500): Shutting down VM
E/AndroidRuntime(18500): FATAL EXCEPTION: main
E/AndroidRuntime(18500): Process: com.example.ebag, PID: 18500
E/AndroidRuntime(18500): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=210, result=0, data=null} to activity {com.example.ebag/com.example.ebag.MainActivity}: java.lang.IllegalStateException: Reply already submitted
E/AndroidRuntime(18500): 	at android.app.ActivityThread.deliverResults(ActivityThread.java:5304)
E/AndroidRuntime(18500): 	at android.app.ActivityThread.handleSendResult(ActivityThread.java:5343)
E/AndroidRuntime(18500): 	at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:54)
E/AndroidRuntime(18500): 	at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45)
E/AndroidRuntime(18500): 	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
E/AndroidRuntime(18500): 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
E/AndroidRuntime(18500): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2214)
E/AndroidRuntime(18500): 	at android.os.Handler.dispatchMessage(Handler.java:106)
E/AndroidRuntime(18500): 	at android.os.Looper.loopOnce(Looper.java:201)
E/AndroidRuntime(18500): 	at android.os.Looper.loop(Looper.java:288)
E/AndroidRuntime(18500): 	at android.app.ActivityThread.main(ActivityThread.java:7842)
E/AndroidRuntime(18500): 	at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(18500): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
E/AndroidRuntime(18500): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
E/AndroidRuntime(18500): Caused by: java.lang.IllegalStateException: Reply already submitted
E/AndroidRuntime(18500): 	at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:164)
E/AndroidRuntime(18500): 	at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.success(MethodChannel.java:238)
E/AndroidRuntime(18500): 	at com.baseflow.permissionhandler.-$$Lambda$fOfJ7OpNBkhP48Mtzqs01exhUJs.onSuccess(Unknown Source:2)
E/AndroidRuntime(18500): 	at com.baseflow.permissionhandler.PermissionManager.onActivityResult(PermissionManager.java:100)
E/AndroidRuntime(18500): 	at io.flutter.embedding.engine.FlutterEngineConnectionRegistry$FlutterEngineActivityPluginBinding.onActivityResult(FlutterEngineConnectionRegistry.java:741)
E/AndroidRuntime(18500): 	at io.flutter.embedding.engine.FlutterEngineConnectionRegistry.onActivityResult(FlutterEngineConnectionRegistry.java:426)
E/AndroidRuntime(18500): 	at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.onActivityResult(FlutterActivityAndFragmentDelegate.java:749)
E/AndroidRuntime(18500): 	at io.flutter.embedding.android.FlutterActivity.onActivityResult(FlutterActivity.java:651)
E/AndroidRuntime(18500): 	at android.app.Activity.dispatchActivityResult(Activity.java:8382)
E/AndroidRuntime(18500): 	at android.app.ActivityThread.deliverResults(ActivityThread.java:5297)
E/AndroidRuntime(18500): 	... 13 more
I/flutter (18500): permission storage is permanently denied
I/flutter (18500): Permission denied storage permission is PermissionStatus.permanentlyDenied and External storage permission is null
I/Process (18500): Sending signal. PID: 18500 SIG: 9
Lost connection to device.

Configuration

Pixel 4 XL API 31 Version: 8.3.0

Platform:

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

SashaMyh avatar Dec 25 '21 19:12 SashaMyh

i recorded 26seconds video for this issue :

https://cdn.discordapp.com/attachments/924570284441346118/924570433188155423/vokoscreen-2021-12-26_11-19-06.mkv

SashaMyh avatar Dec 26 '21 07:12 SashaMyh

i recorded 26seconds video for this issue :

https://cdn.discordapp.com/attachments/924570284441346118/924570433188155423/vokoscreen-2021-12-26_11-19-06.mkv

even if i enable the permission and press backbutton it will still crashes

SashaMyh avatar Dec 26 '21 07:12 SashaMyh

there is a requestCode clash, flutter sends the same result to all listeners, you should avoid at least:

    static final int PERMISSION_CODE = 24;
    static final int PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS = 209;
    static final int PERMISSION_CODE_MANAGE_EXTERNAL_STORAGE = 210;
    static final int PERMISSION_CODE_SYSTEM_ALERT_WINDOW = 211;
    static final int PERMISSION_CODE_REQUEST_INSTALL_PACKAGES = 212;
    static final int PERMISSION_CODE_ACCESS_NOTIFICATION_POLICY = 213;

just pick a fortunate number like 0x1337 :)

sherpya avatar Feb 03 '22 18:02 sherpya

I have the same issue with iOS @sherpya Could you please elaborate your answer a bit?

YuriHeiko avatar Feb 05 '22 11:02 YuriHeiko

I have the same issue with iOS @sherpya Could you please elaborate your answer a bit?

I suppose iOS work differently, but anyway on android you call startActivityForResult() passing an int code, when the activity is closed the data you put as result using setResult() is passed on each Activity() (or other listener) with same code. If another Activity uses the result because listen for the same code, it can expose unespected results. My app registered for the 213 code and the Activity (or listener) this package exponed was picking my result as PERMISSION_CODE_ACCESS_NOTIFICATION_POLICY. I think the whole system is wrongly designed, the Activity/listener called startActivityForResult() should receive only his own results

sherpya avatar Feb 06 '22 10:02 sherpya

@SashaMyh I had been confused for a few days until I saw the message of @sherpya. I change List<Permission>.request() to Permission.request(), request a permission at a time. It works perfectly.

    final permissions = [
      Permission.storage,
      Permission.manageExternalStorage,
    ];
    if (widget.permissions != null) {
      permissions.addAll(widget.permissions!);
    }
    log(permissions.toString());

    bool f = true;

    for (var permission in permissions) {
      final state = await permission.request();
      if (!f || state != PermissionStatus.granted) {
        f = false;
      }
    }

KuiyuanFu avatar Mar 06 '22 21:03 KuiyuanFu

Is there a solution to this problem? I have the same problem, I requested the "manageExternalStorage" permission and the application crashed directly after returning. I also tried just requesting the permission individually, but that didn't work either.

luomo-pro avatar Jul 06 '22 02:07 luomo-pro

I solve such problem with this code

More about here

// dont forget add import
import 'dart:io';

WillPopScope(
            child: ..., // you app, maybe navigation stack
            onWillPop: () async {
              BuildContext? context = navigatorKeys[_selectedIndex].currentState.context;

              bool maybePop = await Navigator.maybePop(context);

                // if maybePop equal to false, then exit, else return false to prevent exit from app
                if(!maybePop) {
                  exit(0);
                }

              return false;
            },
),

Yaolegol avatar Aug 25 '23 11:08 Yaolegol

I have started investigating, and the problem lies in requesting multiple permissions of which one opens the app's settings. The minimal code that reproduces the crash is

[Permission.storage, Permission.manageExternalStorage].request();

JeroenWeener avatar Aug 31 '23 14:08 JeroenWeener