Ошибка обработчика разрешений с несколькими разрешениями

#flutter #dart #permissions #android-permissions

Вопрос:

Я пытаюсь добавить два разрешения, т. е. хранилище и камеру. Я выполнил необходимую настройку в androidmanifest.xml файл и в main.dart вызывали оба запроса с помощью переключателя. Это выдает ошибку, но приложение работает, и разрешения также обновляются

 import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:firebase_core/firebase_core.dart';

import 'package:teamup/Connectivity/network_binding.dart';
import 'package:teamup/Views/Login/sign_in.dart';
import 'package:teamup/Views/OnboardingScreen/onboarding_screen.dart';
import 'Views/OnboardingScreen/onboarding_constants.dart';

void main() async {
  await GetStorage.init();
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late Permission cameraPermission;
  late Permission storagePermission;
  PermissionStatus cameraPermissionStatus = PermissionStatus.denied;
  PermissionStatus storagePermissionStatus = PermissionStatus.denied;

  void _listenForPermission() async {
    final cameraStatus = await Permission.camera.status;
    final storageStatus = await Permission.storage.status;
    setState(() {
      cameraPermissionStatus = cameraStatus;
      storagePermissionStatus = storageStatus;
    });

    switch (cameraStatus) {
      case PermissionStatus.denied:
        requestForPermission();
        break;
      case PermissionStatus.granted:
        break;
      case PermissionStatus.restricted:
        Navigator.pop(context);
        break;
      case PermissionStatus.limited:
        Navigator.pop(context);
        break;
      case PermissionStatus.permanentlyDenied:
        Navigator.pop(context);
        break;
    }

    switch (storageStatus) {
      case PermissionStatus.denied:
        requestForPermission();
        break;
      case PermissionStatus.granted:
        break;
      case PermissionStatus.restricted:
        Navigator.pop(context);
        break;
      case PermissionStatus.limited:
        Navigator.pop(context);
        break;
      case PermissionStatus.permanentlyDenied:
        Navigator.pop(context);
        break;
    }
  }

  Future<void> requestForPermission() async {
    final cameraStatus = await Permission.camera.request();
    final storageStatus = await Permission.storage.request();
    setState(() {
      cameraPermissionStatus = cameraStatus;
      storagePermissionStatus = storageStatus;
    });
  }

  @override
  void initState() {
    super.initState();
    _listenForPermission();
    isViewed.writeIfNull('key', 0);
    print(isViewed.read('key'));
  }

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(primarySwatch: Colors.blue, fontFamily: 'Glory'),
      initialBinding: NetworkBinding() ,
      home: isViewed.read('key') != 0
          ? const SignInPage()
          : const OnboardingPage(),
    );
  }
}
 

Это сообщение, которое было отображено после установки

 Launching libmain.dart on Redmi Note 4 in debug mode...
Running Gradle task 'assembleDebug'...
√  Built buildappoutputsflutter-apkapp-debug.apk.
Installing buildappoutputsflutter-apkapp.apk...
W/FlutterActivityAndFragmentDelegate(21677): A splash screen was provided to Flutter, but this is deprecated. See flutter.dev/go/android-splash-migration for migration steps.
Debug service listening on ws://127.0.0.1:56092/dh3Yn3XCkGg=/ws
Syncing files to device Redmi Note 4...
I/FA      (21677): Tag Manager is not found and thus will not be used
I/flutter (21677): 0
[GETX] Instance "GetMaterialController" has been created
[GETX] Instance "GetMaterialController" has been initialized
[GETX] Instance "GetXNetworkManager" has been created
[GETX] Instance "GetXNetworkManager" has been initialized
I/Timeline(21677): Timeline: Activity_launch_request time:267480997 intent:Intent { act=android.content.pm.action.REQUEST_PERMISSIONS pkg=com.google.android.packageinstaller (has extras) }
E/flutter (21677): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] 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, null)
E/flutter (21677): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:607:7)
E/flutter (21677): #1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:156:18)
E/flutter (21677): <asynchronous suspension>
E/flutter (21677): #2      MethodChannelPermissionHandler.requestPermissions (package:permission_handler_platform_interface/src/method_channel/method_channel_permission_handler.dart:71:9)
E/flutter (21677): <asynchronous suspension>
E/flutter (21677): #3      PermissionActions.request (package:permission_handler/permission_handler.dart:44:31)
E/flutter (21677): <asynchronous suspension>
E/flutter (21677): #4      _MyAppState.requestForPermission (package:teamup/main.dart:75:26)
E/flutter (21677): <asynchronous suspension>
E/flutter (21677): 
I/Timeline(21677): Timeline: Activity_launch_request time:267501469 intent:Intent { act=android.content.pm.action.REQUEST_PERMISSIONS pkg=com.google.android.packageinstaller (has extras) }
 

Ответ №1:

Операторы переключения в _listenForPermission вызовут requestForPermission дважды, если оба cameraStatus и storageStatus имеют статус PermissionStatus.denied . Поэтому вы получаете исключение:

 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)
 

Пакет permission_handler позволяет запрашивать несколько разрешений за один вызов, как это:

 // You can request multiple permissions at once.
Map<Permission, PermissionStatus> statuses = await [
  Permission.location,
  Permission.storage,
].request();
print(statuses[Permission.location]);