Android “M” Permission System Explained

4 minute read

At this year’s I/O, Google unveiled the next version of Android, codename “M”. This release focuses on incremental improvements, new APIs and refining the user interface.

Having experience with both Android and iOS SDKs, I can draw some parallels between them, to the benefit of my friends and colleagues working on Apple platforms.

One of the aspects that was covered is the new permission system, which is clearly inspired by iOS. Gone is the “permission wall” shown when users tap “Install” in the Play Store. The system will ask users to either grant or deny access to privileged functionality on the spot.

Each application gets, as soon as it is installed, network access and is allowed to read and write files in its own container. Additional permissions are requested and, eventually, granted as soon as the application needs them, with the operating system in charge to present a confirmation prompt to the user. This is quite similar to how iOS application have been working since the dawn of the AppStore.

What’s interesting is that the underlying mechanism is still the old, broad, and granular set of permissions we’ve been accustomed to since the first version of Android. What’s changed is just the user experience and a couple of new APIs.

Developers, in fact, still have to declare all permissions they need in AndroidManifest.xml but these permissions are now clustered into “logical groups” to make them easier to understand for end users. For example the old READ_CALENDAR and WRITE_CALENDAR permissions are presented to the user as a single prompt to access the whole calendar. From an API perspective, you are still requesting access to READ_CALENDAR, WRITE_CALENDAR (or both) but, once the user grants or denies a permission coming from a logical group, all permissions in that group are either granted or denied at the same time.

This is, again, strikingly similar to iOS. When I request access to the address book, I’m given both read and write access simultaneously. I don’t have to request them separately.

Power users will be disappointed to know that the settings screen will only allow to toggle groups, not individual permissions. As a first iteration, though, this is good enough and still a vast improvement over the “wall of permissions” users have endured until now.

Developers must opt-in to the new scheme by telling the system that they target “M” by changing a couple of lines in their build.gradle file in a manner quite similar to how the “Deployment Target” configuration parameter works in iOS.

Opting in to the new scheme comes with a price: applications now must degrade gracefully in case the permission is being denied and they don’t have to crash when the permission is toggled from the settings screen at a later date. Developers also should ponder whether it’s better to ask for all permissions when the app is first launched 1 or wait until the permission is effectively needed.

Old applications that target a pre-M version of Android will get the old “wall of permissions” at install time but users will still be able to toggle each permission group after the application has been installed. The settings screen will, in this case, show a warning telling users that legacy applications might misbehave when something is turned off, since old applications assume that all permissions were granted them by the virtue they are installed and running on a device. Once a permission group is disabled, the system supplies fake data to the application in the form of e.g. an empty address book, unavailable location fixes, and so on. The system won’t raise security exceptions.

Also, whenever a permission is toggled from the settings page, the application process is killed. This frees developers from having to think about permissions changing while an application is performing a long-running operation.

From a developer standpoint the API is really simple: you check if you have a permission with Context.checkSelfPermission() and prompt the user with Activity.requestPermissions() and then handle the response in the onRequestPermissionsResult() method in your activities.

One difference with iOS is that developers can’t provide an explanation to be injected in the system UI. Developers either have to “double-prompt” 2 or show a justification prompt after the user has denied a particular permission, then ask again. This last method seems to be the preferred one. Beware though, after the first prompt users are shown a checkbox to hush all future requests. It is unclear whether all dialogs or only those coming from a specific permission group will be hidden.

Unlike iOS it is also possible to cluster multiple permission requests together. The system UI will include a progress indicator in the lower left corner displaying how many more dialogs will be shown.

In some cases permission alerts can be skipped altogether by firing a system intent, delegating the action to a component for which the user might already have granted all permissions, and this is really what most developers should attempt to do before taking matter to themselves and use privileged APIs.

The new permission model goes definitely in the right direction and I can’t wait to see devices with Android M hitting the market, bringing users a refined user experience alongside all other new features and improvements Android has to offer such as Doze and Android Pay.

Additional Resources

Footnotes

  1. Hangouts requests access to the microphone, contacts and SMS at launch because these are needed to provide essential functions in the application. Google Keep instead requests access to the microphone when you first tap the button to record a voice memo. 

  2. Double-prompting is the practice of showing an application-managed prompt before the one handled by the system.