运行时权限:Android(如果用户拒绝权限,则调用两次)

Runtime permission: Android (called twice if user deny permission)

提问人:Viacheslav Khailenko 提问时间:10/16/2022 最后编辑:Selim ÖzbayViacheslav Khailenko 更新时间:11/2/2022 访问量:5742

问:

我的运行时权限警报对话框有问题。这是我的代码:

button.setOnClickListener{
    requestPermissionLauncher.launch(android.Manifest.permission.CAMERA)
}

val requestPermissionLauncher =
        registerForActivityResult(
            ActivityResultContracts.RequestPermission()
        ) { isGranted: Boolean ->
            if (isGranted) {
                presenter.openCamera()
            } else {
                showMessage(getString(R.string.permission_needed))
            }
        }

如果用户单击“相机”btn,用户将看到此对话框(如预期):enter image description here

然后,如果用户单击“使用应用程序时”或“仅此一次”->一切正常,则没有问题

但是,如果用户单击“不允许”,>他会看到错误消息(如预期的那样),但如果用户第二次单击“相机”,则>权限警报对话框再次出现。(第二次后,此对话框将不再出现)

如果用户第一次拒绝权限,为什么此警报对话框会显示两次?它应该只出现一次,第二次单击后,用户可能会立即看到错误消息

android android 权限 权限被拒绝

评论


答:

15赞 Sasa Arsenovic 11/2/2022 #1

简而言之:对话框出现两次,因为如果用户第一次点击“拒绝”,下次系统建议在请求权限之前显示一个理由对话框,并且应该ShowRequestPermissionRationale(android.Manifest.permission.CAMERA) 返回 true。您可以检查这是否属实,并且不再显示您的权限对话框。如果您不手动检查此布尔值,如果为 true,系统将再次自动显示权限对话框。 请记住,如果用户在权限对话框之外单击,则其处理方式与用户单击“拒绝”相同。

当用户第二次拒绝权限时,您将无法再次显示权限对话框。用户允许权限的唯一方法是转到系统设置中的应用程序信息并手动允许请求的权限(不建议这样做)。

文档

请求权限的工作流 =>

...

第 4 步。检查用户是否已经授予了运行时权限。如果没有,请继续执行下一步。

第 5 步。检查你的应用是否应向用户显示理由,解释你的应用需要用户授予权限的原因。

...

来自 developer.android.com 的权限图

例:

if (checkSelfPermission(android.Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
        // Application can use camera
    } else if (shouldShowRequestPermissionRationale(android.Manifest.permission.CAMERA)) {
        /*
        This is the second time when system is about to show permission dialog.

        You can show your alert dialog here if you want to explain to user what are benefits if allow your requested permission (CAMERA in this case). Also, you can show
        permission dialog on "OK" click, and do nothing on "No, thank you".

        KEEP IN MIND THAT WITH THIS APPROACH YOU WILL SHOW ALERT DIALOG TO THE USER EVERY TIME YOU CHECK IF PERMISSION IS NOT GRANTED BUT
        shouldShowRequestPermissionRationale(android.Manifest.permission.CAMERA) RETURNS TRUE. THIS CAN BE ANNOYING TO THE USER AND YOU SHOULD
        AVOID THIS PART OF CODE. THIS IS JUST FOR TESTING PURPOSES.

        *** YOU SHOULD SHOW THIS ALERT DIALOG WHEN REGISTERING YOUR ACTIVITY FOR PERMISSION RESULT, IF PERMISSION IS NOT GRANTED!!!***
         */
        AlertDialog.Builder(this@YourActivity)
            .setMessage(
                "Your message"
            )
            .setPositiveButton(
                "OK"
            ) { _, _ ->
                // Show permission dialog
                requestPermissionLauncher.launch(android.Manifest.permission.CAMERA)
            }
            .setNegativeButton(
                "No, thank you"
            ) { _, _ -> }
            .create().show()

        /*
        IF YOU DON'T WANT TO SHOW ALERT_DIALOG FROM ABOVE, HERE YOU CAN SIMPLY SHOW PERMISSION DIALOG
        
        requestPermissionLauncher.launch(android.Manifest.permission.CAMERA)
         */
    } else {
        /*
        This part of code is active first time when you are going to request the permission, and last time (after second "Deny" by a user,
        or simply, when permission is not granted and shouldShowRequestPermissionRationale(android.Manifest.permission.CAMERA) returns false
         */
        requestPermissionLauncher.launch(android.Manifest.permission.CAMERA)
    }

正如我在开头提到的,您可以将用户导航到可以允许权限的应用程序设置,但根据 Google 的文档,您应该避免这种情况。 来自文档的消息:“......尊重用户的决定。不要链接到系统设置以说服用户改变他们的决定。

即使你想导航用户,也可以用下一个代码块来做到这一点:

val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val uri = Uri.fromParts("package", packageName, null)
intent.data = uri
startActivity(intent)

评论

0赞 Eselfar 8/31/2023
“当用户第二次拒绝权限时,您将无法再次显示权限对话框。”有没有办法知道用户已经两次拒绝了权限?
1赞 Sasa Arsenovic 9/8/2023
@Eselfar 您可以为此添加另一个检查: .第一次也是如此,但如果你把 if 语句写得好,它甚至不应该到达这一行。如果需要,可以在 check 之后和之前添加此检查。希望这会有所帮助。很抱歉回复晚了。if (checkSelfPermission(android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && !shouldShowRequestPermissionRationale(android.Manifest.permission.CAMERA) { // Permission is fully denied by a user (Denied twice) }shouldShowRequestPermissionRationaleelse statement
1赞 Eselfar 9/8/2023
嗨,@Sasa,感谢您的回复。我不确定如何做那部分:.你能再详细一点吗?This is also true at first time, but if you write if statement well, it shouldn't even reach this line