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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 02:15:04