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

Flutter permission_handler:如何判断权限是否被请求及状态异常问题

问题描述

我正在使用permission_handler包,目前功能正常,但现在需要判断某个Permission是否曾被请求过。我想寻找类似PermissionStatus.notDetermined的功能,已知firebase_messaging包中有类似功能,但未在该包中找到,这对我来说十分重要。我仅想在系统权限从未被请求过时显示弹窗,虽可通过SharedPreferences存储"wasRequested"这类值实现,但认为应有现成功能。

另外我发现获取的权限状态与request方法返回的状态不一致,这让我十分困惑:

final stat = await Permission.notification.status; // -> denied
final req = await Permission.notification.request(); // -> permanentlyDenied

1. 判断权限是否曾被请求过

permission_handler包本身没有提供直接标记“是否请求过权限”的状态值——系统层面的权限状态仅记录当前权限的允许/拒绝/永久拒绝等状态,不会追踪权限是否被请求过。你提到的firebase_messaging中的类似逻辑,本质也是封装了本地存储的判断逻辑,并非系统原生提供。

所以目前最可靠的方案还是通过本地存储(比如SharedPreferences)记录权限请求状态:

// 初始化SharedPreferences
final prefs = await SharedPreferences.getInstance();
const notificationPermissionKey = 'notification_permission_requested';

// 读取是否请求过权限,默认未请求
bool wasRequested = prefs.getBool(notificationPermissionKey) ?? false;

if (!wasRequested) {
  // 显示自定义弹窗
  // ...
  
  // 请求权限后标记为已请求
  await Permission.notification.request();
  await prefs.setBool(notificationPermissionKey, true);
}

2. 状态不一致的原因

你遇到的status返回denied但request返回permanentlyDenied的情况,是因为两次调用之间权限状态被用户操作改变了:

  • Android平台:当权限处于denied状态时,再次调用request()会弹出带有“不再询问”选项的系统弹窗。如果用户勾选该选项并拒绝权限,权限状态会直接变为permanentlyDenied,所以request()返回的是更新后的状态。
  • iOS平台:当权限处于denied状态时,调用request()会直接跳转到系统设置页。如果用户在设置中保持权限拒绝状态并返回App,权限状态会更新为permanentlyDenied。

简单来说,status获取的是调用瞬间的静态状态,而request()会触发交互流程,用户的操作会动态改变权限状态,导致返回值与之前的status不一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 14:47:06