Android 11 如何检测权限永久拒绝并区分设置中的“每次询问”选项
Android 11+ 权限场景判断逻辑实现
核心问题说明
Android 11+ 中 shouldShowRequestPermissionRationale() == false 对应三种场景:
- 首次申请权限,从未向用户弹出过申请弹窗
- 用户多次点击权限申请的「拒绝」选项,触发了永久拒绝
- 用户手动在系统设置中将权限切换为「每次询问」
你遇到的冲突就是后两种场景的返回值完全一致,需要通过额外的状态标记做区分,即可实现和谷歌地图一致的交互逻辑。
实现步骤
- 第一步:本地持久化(推荐用SharedPreferences)存储标记位,例如
hasRequestedPermission,记录是否已经向用户发起过对应权限的申请 - 第二步:每次需要校验权限时,先调用
checkSelfPermission判断权限状态:- 返回
PERMISSION_GRANTED:直接执行业务逻辑即可 - 返回
PERMISSION_DENIED:进入下一步判断
- 返回
- 第三步:判断
shouldShowRequestPermissionRationale()的返回值:- 返回
true:说明用户之前拒绝过但未触发永久拒绝,先弹权限用途说明弹窗,用户确认后再拉起系统权限申请框 - 返回
false:进入第四步判断
- 返回
- 第四步:判断本地存储的
hasRequestedPermission标记位:- 标记位为
false:属于首次申请/用户在设置中切换为「每次询问」场景,直接拉起系统权限申请框,同时把标记位改为true - 标记位为
true:属于永久拒绝场景,弹出提示引导用户跳转到系统设置开启权限
- 标记位为
代码示例(Kotlin)
// 读取本地存储的权限申请标记 val hasRequestedLocationPerm = sharedPreferences.getBoolean("has_requested_location_perm", false) when { ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED -> { // 权限已授权,执行业务逻辑 startLocationService() } shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION) -> { // 非永久拒绝,先弹说明再申请 AlertDialog.Builder(this) .setMessage("需要位置权限为您提供周边搜索、导航服务") .setPositiveButton("去授权") { _, _ -> requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQ_CODE_LOCATION_PERM) } .setNegativeButton("取消", null) .show() } else -> { if (!hasRequestedLocationPerm) { // 首次申请/每次询问场景,直接弹权限申请框 requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQ_CODE_LOCATION_PERM) sharedPreferences.edit().putBoolean("has_requested_location_perm", true).apply() } else { // 永久拒绝场景,引导跳设置 AlertDialog.Builder(this) .setMessage("位置权限已被永久拒绝,请在系统设置中手动开启后使用相关功能") .setPositiveButton("去设置") { _, _ -> val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { data = Uri.fromParts("package", packageName, null) } startActivity(intent) } .setNegativeButton("取消", null) .show() } } }
注意事项
用户从系统设置页面返回应用时,需要重置hasRequestedPermission标记位,因为用户可能把权限从「永久拒绝」修改为「每次询问」,重置后即可再次弹出权限申请框。
内容的提问来源于stack exchange,提问作者RajaKumar
相关产品推荐
相关产品推荐

