How to detect permission's permanent deny in Android 11?

Viewed 2206

In Android 11, when user select "deny" option for more than once for any permission request, then system will mark it as "Permanently denied".Once permanently denied, user has to enable in settings.From this time shouldShowRequestPermissionRationale() start's to return false

Three options are available for permission window , "Deny","Allow All time","Allow only this time". But in settings "Deny","Allow all the time","Ask every time" are present.

How to find when user selects "Ask me every time" from settings, because, checkSelfPermission() returns PackageManager.PERMISSION_DENIED,and shouldShowRequestPermissionRationale() return false. In this time I want to show permission window, instead of move to settings. Something similar to google map permission

3 Answers

Using the new ActivityResultsContract you can do this in the following manner


    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
                }
            }
        }

In OnCreate()[Make sure you ask permission in OnCreate , else application will crash] , ask the permission :

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        requestPermissionLauncher.launch(REQUIRED_PERMISSIONS)
    }

Ask requiredPermissions in the following manner :

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

Actually there is one more scenario: if the user let you request the permission but don't chose any option and dismissed the dialog by tapping outside, the request finishes with denied and shouldShowRequestPermissionRationale() returns false. That is the exact same behaviour as if the user selects don't ask again. the permission where requested once, it results in denied and we should not show a explanation.

therefore we have to track if shouldShowRequestPermissionRationale() has returned true for once. if it switches back to false its denied permanent.

In activity use below method, Camera permission is used in this example

    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)
        }
    }
}
Related