如何在Android 11中检测权限的永久拒绝?

9

在Android 11中,当用户对任何权限请求选择了“拒绝”选项超过一次时,系统将标记它为“永久拒绝”。一旦永久拒绝,用户必须在设置中启用。从此时开始,shouldShowRequestPermissionRationale() 开始返回 false

权限窗口提供了三个选项,“拒绝”、“允许所有时间”和“仅允许本次”。但在设置中,“拒绝”、“始终允许”和“每次询问”都存在。

如何确定用户何时从设置中选择“每次询问”,因为 checkSelfPermission() 返回 PackageManager.PERMISSION_DENIED,而 shouldShowRequestPermissionRationale()返回 false。此时我想显示权限窗口,而不是转到设置。 类似于谷歌地图权限的处理方式


我相信这是有意为之的行为,每当用户拒绝权限时,我会显示一个“Toast”消息:“要重新启用此功能,请前往应用程序设置授予XX权限。” - Sam Chen
4个回答

9

使用新的ActivityResultsContract,您可以按以下方式实现此目的


    private val requestPermissionLauncher =
        registerForActivityResult(
            ActivityResultContracts.RequestMultiplePermissions()
        ) { result: MutableMap<String, Boolean> ->
            val deniedList: List<String> = result.filter {
                !it.value
            }.map {
                it.key
            }

            when {
                deniedList.isNotEmpty() -> {
                    val map = deniedList.groupBy { permission ->
                        if (shouldShowRequestPermissionRationale(permission)) DENIED else EXPLAINED
                    }
                    map[DENIED]?.let {
                        // request denied , request again
                    }
                    map[EXPLAINED]?.let {
                        //request denied ,send to settings 

                    }

                }
                else -> {
                   //All request are permitted
                }
            }
        }


在OnCreate()函数中[确保在OnCreate函数中请求权限,否则应用程序将崩溃],请求权限:
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        requestPermissionLauncher.launch(REQUIRED_PERMISSIONS)
    }

请按以下方式询问requiredPermissions:

private val REQUIRED_PERMISSIONS = arrayOf(
    Manifest.permission.CAMERA,
    Manifest.permission.READ_EXTERNAL_STORAGE
)


工作中。谢谢。 - RajaKumar
2
请分享您的导入内容,这里是指被拒绝的内容或解释。 - Krishna
1
两个常量变量用于定义哪些权限被拒绝和哪些已解释。只需声明为const val DENIED = "denied"和const val EXPLAINED = "explained"即可。 - Karunesh Palekar
3
如果用户取消了权限对话框,这将无法工作。 - Kairat
1
嘿@Kairat,上面的代码不是为了满足您的要求而设计的,它只是完成了上述问题中要求的任务。您需要为自己的用例设计代码,如果遇到任何问题,请在此提出问题并@我。 - Karunesh Palekar

2
实际上还有一种情况: 如果用户允许您请求权限,但不选择任何选项并通过点击外部关闭对话框,则请求将以拒绝的方式结束,shouldShowRequestPermissionRationale()返回false。 这与用户选择不再询问的行为完全相同。 权限已经被请求过一次,结果是被拒绝的,我们不应该显示解释。
因此,我们必须追踪shouldShowRequestPermissionRationale()是否至少返回过一次true。如果它切换回false,那么它就是永久拒绝了。

shouldExplainPermissionRational() 函数在哪里?我找不到它... 你是不是指的 shouldShowRequestPermissionRationale() - RealityExpander
1
是的,抱歉。已经更正了那个。 - Basur

0

在您的活动中使用以下方法(此示例中使用相机权限):

private fun requestPermission() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
        if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
            //Permission is denied
        } else {
            //ask permission
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQUEST_CODE_CAMERA)
        }
    }
}

有时候,如果权限只被拒绝了一次,这将会触发。 - Nick

-2

在用户拒绝权限后,您只需要检查shouldShowRequestPermissionRationale()即可。

val requestPermissionLauncher = registerForActivityResult(
    ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
    if (isGranted) {

    } else {
        if(shouldShowRequestPermissionRationale(Manifest.permission.YOUR_RUNTIME_PERMISSION)){
            //user hasn't denied permission permanently
        }else{
            //user has denied permanently,
            //you should try to redirect user to settings
            //to ask user grant it manually
        }
    }
}
requestPermissionLauncher.launch(Manifest.permission.YOUR_RUNTIME_PERMISSION)

shouldShowRequestPermissionRationale函数有两个参数,而不是一个。 - ShadeToD
当用户关闭权限对话框时,shouldShowRequestPermissionRationale也可能返回false。 - ShadeToD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接