Flutter使用permission_handler出现重复权限请求问题求助
问题描述
我正在开发一款需要电话和相机权限的Flutter应用,希望在启动时检查权限是否授予,以此决定是否允许应用运行。使用permission_handler库(版本10.4.3)编写了依次请求电话和相机权限的代码,但出现重复请求权限的问题:其他应用首次请求后后续不会弹窗,而我的应用每次启动都会重复请求。测试环境为Android 12系统的SM-N971机型,该问题曾自行解决但现在再次出现。我尝试过修改请求代码、调整请求时机、切换库版本到10.4.1,问题依然存在。
相关代码如下:
// Check the required permissions to use the app import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; import 'package:permission_handler/permission_handler.dart'; import '../messagebox/bloc/message_box_state.dart'; import '../messagebox/page/message_box_page.dart'; /// It sequentially asks for the necessary permissions: phone and camera. Future<String> callPermissions() async { PermissionStatus phoneStatus = await Permission.phone.request(); if (!phoneStatus.isGranted) { return 'failed'; } else { //phoneStatus.isGranted == true PermissionStatus cameraStatus = await Permission.camera.request(); if (!cameraStatus.isGranted) { return 'failed'; } else { return 'success'; } } } /// Check permissions and, if you do not have the permissions, perform permission derivation, such as providing a page to set permissions. void checkPermission(BuildContext context) async { if (await callPermissions() == "success") { //If allowed } else { // If not allowed bool? permissionResult = await MessageBoxPage.popUpMessageBox( context, 'Camera permission and phone permission must be allowed to use the app. Would you like to go to the settings page to allow?', MessageBoxType.ReplyTwoMessageBox); if (permissionResult == true) { bool? permissionResult2 = await MessageBoxPage.popUpMessageBox( context, 'When you press OK, the app will automatically close to go to the settings page. Please run it again after setting.', MessageBoxType.ReplyOneMessageBox); if (permissionResult2 == true) { // When you press Yes, you will be moved to settings. openAppSettings(); SystemNavigator.pop(); } } else { bool? permissionResult2 = await MessageBoxPage.popUpMessageBox( context, 'The app cannot proceed because the required permissions to use the app are not granted. The app quits.', MessageBoxType.ReplyOneMessageBox); if (permissionResult2 == true) { SystemNavigator.pop(); } } } }
我也曾单独测试修改PermissionStatus phoneStatus = await Permission.phone.request()的相关逻辑,但问题仍持续。
问题分析与解决方案
核心原因
当前代码每次启动都直接调用request()方法,未提前检查权限的当前状态。Android系统中,若用户拒绝权限并勾选"不再询问",request()会直接返回拒绝状态,但无前置检查的直接请求可能触发系统重复弹窗;另外,权限状态的持久化读取异常也可能导致每次都判定权限未授予。
解决步骤
- 先检查权限状态,再发起请求
修改callPermissions()方法,先获取当前权限状态,仅当状态为denied(首次未授权)时才发起请求,避免无效弹窗:
Future<String> callPermissions() async { // 先检查电话权限状态 PermissionStatus phoneStatus = await Permission.phone.status; if (phoneStatus.isDenied) { phoneStatus = await Permission.phone.request(); } if (!phoneStatus.isGranted) { return 'failed'; } // 再检查相机权限状态 PermissionStatus cameraStatus = await Permission.camera.status; if (cameraStatus.isDenied) { cameraStatus = await Permission.camera.request(); } if (!cameraStatus.isGranted) { return 'failed'; } return 'success'; }
- 处理"永久拒绝"的情况
当权限状态为permanentlyDenied时,直接引导用户前往设置页,避免无意义的请求尝试:
Future<String> callPermissions() async { PermissionStatus phoneStatus = await Permission.phone.status; if (phoneStatus.isDenied) { phoneStatus = await Permission.phone.request(); } // 永久拒绝或未授予时返回失败 if (phoneStatus.isPermanentlyDenied || !phoneStatus.isGranted) { return 'failed'; } PermissionStatus cameraStatus = await Permission.camera.status; if (cameraStatus.isDenied) { cameraStatus = await Permission.camera.request(); } if (cameraStatus.isPermanentlyDenied || !cameraStatus.isGranted) { return 'failed'; } return 'success'; }
- 验证Android权限配置
检查android/app/src/main/AndroidManifest.xml是否正确声明权限:
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- 若需拨打电话等功能,补充对应权限 -->
Android 12及以上系统部分权限有额外要求,比如读取手机号需添加android.permission.READ_PHONE_NUMBERS,按需补充即可。
- 避免重复触发权限检查
确保checkPermission()仅在应用启动时调用一次,比如在main()初始化后、首页加载前执行,不要在页面build方法中重复调用,防止页面重建时反复触发权限请求。
内容的提问来源于stack exchange,提问作者Joonseo Park
相关产品推荐
相关产品推荐

