android permission handling on marshmallow and preM
Dec 21, 2015
Before android marshmallow, permission prompt, e.g. making a call, reading contacts, retrieving user location, happens in Google Play when you press install button.
On marshmallow, story is little bit different - it kinda looks like what iOS does. Official android developer website has a dedicated section for permission handling: Working with System Permissions.
When I try to get this new stuff work in practice, two things worth some elaborations: Never ask again and pre marshmallow handling.
Never ask again checked
The new permission workflow works like following. Suppose, there is a button that you could press to make call.
And when you press the call btn first time, it would prompt:
If you choose ALLOW, it would just go and call like pre marshmallow; If you choose DENY, it means you have denied permission for user to access, then better we’d show an alert to guide user what’s going like following screenshot:
The idea here is, so user has denied permission, we need provide some explanation(i.e. rationale) to tell user why we need it. Also we provide two actions: Retry and I’m Sure. Click Retry, it would prompt permission asking alert again; Click I’m sure, then it just dismiss silently because user has explicitly known what he is doing.
So if you clicked Retry or you press call button second time, the permission requesting window will have an option: Never ask again.
The tricky part here what happens if user has denied with Never ask again checked?
It turns out in onRequestPermissionsResult, you could query shouldShowRequestPermissionRationale to tell whether user has denied with Never ask again option.
The code in onRequestPermissionsResult:
So if shouldShowRequestPermissionRationale returns false, we will display an alert for go to app settings to allow user manually toggle permissions.
Last point, when request permission, we need a way to distinguish two case when shouldShowRequestPermissionRationale returns false. According to android documentation:shouldShowRequestPermissionRationale
To help find the situations where you need to provide extra explanation, the system provides the Activity.shouldShowRequestPermissionRationale(String) method. This method returns true if the app has requested this permission previously and the user denied the request. That indicates that you should probably explain to the user why you need the permission.
If the user turned down the permission request in the past and chose the Don't ask again option in the permission request system dialog, this method returns false. The method also returns false if the device policy prohibits the app from having that permission.
when shouldShowRequestPermissionRationale return false, it could be either user request permission first time or user has denied with Never ask again before. Hence we need modify request code a little bit:
That’s all.
Pre marshmallow and code reuse
To make it work with pre marshmallow, we could encapsulate those logic in a helper.
So in helper, we could specify a general callback for affirmative actions. On pre marshmallow, you could just call that callback; on marshmallow, do permission flow: