Permission handling should be simple, but not the case in Android. Or at least before you know a lot about it. This article aims to solve that problem. And we will use
Anko here to make it better.
This is where you can find the official solution. It explains well but it depends on you how you shape your interactive model. Let’s see how google designs this model.
Below is the official code.
The code is easy to read:
- Check whether we got the permission or not.
- If yes, we go to the
Permission has already been grantedcase.
- If no, two sub-cases here:
- show permission rationale, then ask permission again
- no need to show permission rationale
The key part here is the usage of
And when a user runs through the flow:
The user will get the ask-for-permission-dialog right away. If he grants it, then all fine. If he denies it, then the next time it will then trigger the
The problem is what about as soon as the user sees the ask-for-permission-dialog, he just denies, close the app and uninstall? Because it seems it’s something like a system notification that we want to just use some feature without permission?
trueif this is the first time the user asks for permission.
And if you use this to show your real rationale, the code seems very clean, something like
if shouldShowRequestPermissionRationale then showReason. Then you will be surprised to see that it won’t work for the first time.
Things will become more interesting when the user denies after the 2nd time. The 3rd time there will be a
Never ask again checkbox. And how to handle that after the user tick that option?
And when this is a very important permission to this app, we want some better model to handle it.
Always asks for permission when the user just trigger the feature, try not to ask for many permissions at the start. Because when the user just needs it, in that context, it will make them feel more comfortable to grant you the permission. And actually, it will be quite easy, and Kotlin will make it easier, which we will see later.
In the app. First, we check the permission, and we execute the tasks if we got the permission. And here is how we handle the case when the permission is not granted.
- We always show a dialog to explain why we need the permission.
- Then we try to request the permission.
- Success case: We get the permission, cool, let’s go on.
- Failure case: We will display some further explanation and try to request again, or just stop because the user can press the button again to trigger the whole procedure again
- NeverAskAgain case: We need to route the user to application settings page and let them enable it there because this is the only way. And besides that, we will show an explanation to tell the user what will happen.
With the above ideas in mind, let’s see how to implement this.
Something needs to know here, you don’t need to handle the API case where Google makes a change to the request model.
import android.support.v4.content.ContextCompat.checkSelfPermission will handle it for you. If the above run under an older device (<= API 23), it will return true. So you can always execute the permission without a problem.
When the permission is not granted, inside the above
else block, add this code
We will show the reason, and after the user press
yes, we will ask for permission and dismiss the
alert if user presses
You will see that we haven’t used that
shouldShowRequestPermissionRationale. When will we use it? Well, we will only use it to check the
never ask again option has been ticked or not.
So after the user responds to your request. It will trigger
onRequestPermissionsResult method, and this is where you can handle that.
And this is how you route the user to the application setting screen.
Then everything should behave as expected.
Although the above code works, can we make it any better? What about inside that
onRequestPermissionsResult(), we can write something like this:
It behaves exactly like the previous one. But in a more declarative and readable way. Even better, you can now reuse it in any
activity. Wait for my next blog, we will see how easily Kotlin will enable us to do something fancy like this. :)