9

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

RajaKumar
  • 1,509
  • 1
  • 10
  • 11
  • I believe that is intentional behavior, I would show a `Toast` message anytime the user deny the permission: "To reactivate this feature, please go to app settings to grant XX permmission." – Sam Chen Aug 24 '21 at 14:22

4 Answers4

9

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
)

Karunesh Palekar
  • 2,190
  • 1
  • 9
  • 18
2

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.

Basur
  • 339
  • 1
  • 14
0

Use the following method in your activity (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)
        }
    }
}
Mike Grimm
  • 941
  • 11
  • 17
Ahmet B.
  • 1,290
  • 10
  • 20
-2

You only need to check the shouldShowRequestPermissionRationale() after user deny the permission

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)