You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()会直接返回拒绝状态,但无前置检查的直接请求可能触发系统重复弹窗;另外,权限状态的持久化读取异常也可能导致每次都判定权限未授予。

解决步骤

  1. 先检查权限状态,再发起请求
    修改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';
}
  1. 处理"永久拒绝"的情况
    当权限状态为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';
}
  1. 验证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,按需补充即可。

  1. 避免重复触发权限检查
    确保checkPermission()仅在应用启动时调用一次,比如在main()初始化后、首页加载前执行,不要在页面build方法中重复调用,防止页面重建时反复触发权限请求。

内容的提问来源于stack exchange,提问作者Joonseo Park

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 14:05:26