6

Since introducing new location permission changes on Android 11 (https://developer.android.com/about/versions/11/privacy/location) there is a need to more carefully work with permissions. We are now able to request background location permission only twice

I want to show the user a dialog dependent on the state of their location permission.

The issue is that system handles click outside of the dialog the same as denying the permission, but it apparently doesn't count it in PermissionsUtil.shouldShowRequestStoragePermissionRationale limit. So it is then hard to distinguish which state the user is in.

My initial question was: How to deal with this specific situation?

But I guess more useful is the general question:
How to recognize if the user pressed outside of the system permission dialog or if he directly denied the permission?.

Smeagol
  • 593
  • 9
  • 23
  • You were always only ever able to request twice before the dialog was not shown again – tyczj Sep 08 '21 at 13:48
  • To answer your question, you cannot know if the user denied the permission or clicked outside the dialog, Its a system dialog not yours – tyczj Sep 08 '21 at 13:53
  • I believe you can, try this: https://stackoverflow.com/a/41304699/1388084 – msc87 Nov 04 '22 at 10:19

2 Answers2

0

Here is how I solved it:

private val btRequestPermissionLauncher =
    registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
        val allPermissionsGranted = permissions.values.none { !it }
        if (allPermissionsGranted) {
            callback?.invoke().apply { this@PermissionActivity.callback = null }
        } else if (Manifest.permission.BLUETOOTH_CONNECT in requiredPermissions || Manifest.permission.ACCESS_FINE_LOCATION in requiredPermissions) {
            if (!shouldShowRequestPermissionRationale(Manifest.permission.BLUETOOTH_CONNECT) && !shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION) && (this.getPreferenceBoolean("NEVER_SHOW_AGAIN", false) || shouldShowRationaleBefore)) {
                this.getPreferenceBoolean("NEVER_SHOW_AGAIN", true)
                //A dialog box with GO TO SETTING button
            } else {
                shouldShowRationaleBefore = true
                requestBluetoothPermissions()
            }
        } else
            requestBluetoothPermissions()

    }


private var shouldShowRationaleBefore = false
protected fun requestBluetoothPermissions(callBack: (() -> Unit)? = null) {
    this.callback = callBack

    when {
        areAllPermissionsGranted() -> {
            callBack?.invoke()
        }
        shouldShowRequestPermissionRationale(Manifest.permission.BLUETOOTH_CONNECT) -> {
            //A dialog box with CONTINUE button and callBack to btRequestPermissionLauncher.launch(...) 
        }
        shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION) -> {
            //A dialog box with CONTINUE button and callBack to btRequestPermissionLauncher.launch(...) 
        }
        !areAllPermissionsGranted() -> {
            if (!shouldShowRationaleBefore)
                btRequestPermissionLauncher.launch(requiredPermissions)
            else { 
                 private var shouldShowRationale = false
                //A dialog box with CONTINUE button and callBack to btRequestPermissionLauncher.launch(...) 
                //This is where the click outside the permission dialog box is handled
            }
        }

    }
}
msc87
  • 943
  • 3
  • 17
  • 39
-1

Based on the result per permission you can add it to a list and then you could know if the user denied / rejected the permissions completely . It can be done in the following way :

    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
                }
            }
        }
Karunesh Palekar
  • 2,190
  • 1
  • 9
  • 18