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
相关产品推荐
相关产品推荐

