Upon installing the app I request access to the mic (I'm aware of the recommendations, this is a quick-and-dirty version.) Here's the pertinent code:
override fun onResume() {
super.onResume()
checkPermissions()
// once the user selects an option in the permissions activity, this onResume fires again
}
private fun checkPermissions() {
if (ContextCompat.checkSelfPermission(
this, Manifest.permission.RECORD_AUDIO
)
== PackageManager.PERMISSION_GRANTED
) {
// we're good, proceed
checkSignIn()
} else {
if (ActivityCompat.shouldShowRequestPermissionRationale(
this, Manifest.permission.RECORD_AUDIO
)
) {
// branch A
explainRecordingRequest()
} else {
// branch B
ActivityCompat.requestPermissions(
this@MainActivity, arrayOf(Manifest.permission.RECORD_AUDIO), 1000
)
}
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
Timber.d("FLOW: received req=$requestCode, len(grants)=${grantResults.size}")
when (requestCode) {
1000 -> {
if (grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
Timber.d("FLOW: ...granted")
} else {
Timber.d("FLOW: ...not granted")
}
}
else -> {
Timber.e("FLOW: unhandled permission request for $requestCode")
}
}
}
private fun explainRecordingRequest() {
val builder: AlertDialog.Builder = AlertDialog.Builder(this)
builder
.setTitle("Why we're requesting this")
.setMessage(getString(R.string.record_audio_permission_explanation))
.setPositiveButton("Got it!") { it, _ ->
it.dismiss()
ActivityCompat.requestPermissions(
this@MainActivity, arrayOf(Manifest.permission.RECORD_AUDIO), 1000
)
}
val dialog: AlertDialog = builder.create()
dialog.show()
}
The mic permission req looks like this:
The "rosy path" -- user authorizes -- works fine; The semi-rosy path -- user first refuses, reads the explanation, and then authorizes -- works fine too.
But I want to support a "corner case", whereby the user continues to refuse until they give up and delete the app (I know, I know, bear with me here...)
If you tap "Don't allow" twice, this code runs into an infinite loop. From what I can tell:
It looks like you only get one shot at the shouldShowRequestPermissionRationale and, past that, "a No is a No"?
Many thanks
Sounds like the dismissal of the permission dialog retriggers the onResume of your Activity/Fragment.
In that case, it would make sense that checkPermissions()
gets called and you are stuck in the B branch of your code as the shouldShow...Rationale
will only fire once as @Edric confirmed.
You can override onPause()
to verify this.
"But I want to support a "corner case", whereby the user continues to refuse until they give up and delete the app (I know, I know, bear with me here...)"
This sounds like you would want the infinite loop that you are getting?
What is exactly the problem with the behaviour you are seeing and what is the behaviour you are looking for? Do you want to show the explainDialog on a loop instead of the requestPermissions dialog?