Blog Engineering

Mastering Android Permissions

Darshan Pania Darshan Pania, Associate Director with 12+ years in mobile tech, SDKs, and Gaming. Leads CleverTap's Mobile SDK & LiveOps team, passionate about innovative tech solutions.
Mastering Android Permissions

The official meaning of the word permission means allowing someone to do a particular thing – it is consent or authorization given to perform any kind of action. In the Android world, permissions follow the definition to the letter. Android apps are built to perform a set of actions, some of them requiring permissions from users.
In this blog post, I will help you understand the importance of permissions, how Android has classified its permissions, and how to ask permission from your users.

Before Android Marshmallow (Android 6.0 or API 23)

Unlike iOS, Android arrived to the app permissions party a bit late. Android Marshmallow (Android M) was released on October 5th, 2015. Before its release, all permissions required for the smooth working of the app were specified by the developer in the build submitted to Google Play Store, which would in turn notify a user that the app required a specific set of permissions before installing.
As with any approach, there were pros and cons. The upside was clear: all permissions were approved by the user at once and the app didn’t need to worry about asking and handling permissions while the user used the app.
The downside was pretty obvious as well: developers started adding permissions to collect data, which breached the privacy of the user. Since Google did not check whether the app actually required the mentioned permissions, and there was no option for the user to not provide certain permissions and still use the app, developers had a grand time gaining access to system information or the microphone without any restraint.
Android Permissions 1

Runtime Permissions with Android Marshmallow

With the public release of Android Marshmallow, Google introduced runtime permissions for Android, thereby changing the landscape of permissions for the better.
Now the developer no longer got all permissions at app install. Instead, the developer would now have to request for the permission to perform something specific like use the camera to click a picture or access the user’s storage to save a file. Google also divided the set of permissions in Android into normal and dangerous permissions.
Normal permissions are those which do not pose a risk to the user’s privacy or the device’s operation. The system grants these permissions automatically. These include connecting to the internet, getting network, Bluetooth, wifi, and NFC information, setting alarms & wallpapers, and modifying audio settings on a device.
Dangerous permissions are permissions which could potentially affect the user’s privacy or the device’s operation. The user must explicitly agree to grant those permissions. These include accessing the camera, contacts, location, microphone, sensors, SMS, and storage.
The complete list of normal and dangerous permissions are available in the Android Documentation.

Permission Groups

Permission groups are similar permissions organized together based on features and device capabilities.
For example, the CONTACTS group has both READ_CONTACTS and WRITE_CONTACTS permissions. If your app doesn’t have any permission under the CONTACTS group and you request for READ_CONTACTS, the system shows the permission request dialog to ask the user to allow your app to read the contacts of the user and upon approval, the system grants the app access to your contacts list.
Since you’ve already requested for a dangerous permission under a permission group, the system won’t request for other permissions under that permission group.

Ask for Permission When Needed

Since requesting and granting permissions is now a runtime activity, the whole process not only becomes important for the developer but also for the user experience.
To standardize the process, permission dialogs are generated by Android and are not customizable. Keeping the user’s experience in mind, developers are advised to request for a permission only when required.
So if your app requires the camera to click a picture, the CAMERA permission should be asked for only when the user wishes to take a photo in your app.

Declaring Permissions Needed by Your App

On all Android versions, to declare the permission needed by your app, you need to add the element into your app manifest file like this:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.app">
    <uses-permission android:name="android.permission.CAMERA"/>
    <!-- other permissions go here -->
    <application ...>
        ...
    </application>
</manifest>

Depending on whether the permission is normal or dangerous, the app will ask the user to grant access.

Requesting Permissions for Your App

If your app requires a dangerous permission, check whether your app has been granted access for the operation that requires the permission:

if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.CAMERA)
        != PackageManager.PERMISSION_GRANTED) {
    // Permission is not granted
}

If the app has permission, then the method ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.CAMERA) will return PERMISSION_GRANTED. Or if the permission has been denied, then the method returns PERMISSION_DENIED. If the app receives PERMISSION_DENIED, then the app should prompt the user to grant the permission in the following way:

// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
        Manifest.permission.CAMERA)
        != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.CAMERA},
                MY_PERMISSIONS_REQUEST_CAMERA);
        // MY_PERMISSIONS_REQUEST_CAMERA is an
        // app-defined int constant. The callback method gets the
        // result of the request.
} else {
    // Permission has already been granted
}

Android Permissions 2

Handling Permissions Granted to Your App

When the user responds to the permission request dialog, the system invokes the onRequestPermissionsResult() method passing the response of the user. You can handle the response of the user in the following way:

@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_CAMERA: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission was granted, yay! Do the
                // camera related task you need to do.
            } else {
                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }
        // other 'case' lines to check for other
        // permissions this app might request.
    }
}

Concluding Thoughts

Runtime permissions have now proven to be very important from a user’s perspective. Apps can no longer sneakily access parts or features of the user’s device without the user’s explicit permission. In today’s age where user and data privacy are of utmost importance, runtime permissions in Android are a small but important initiative in that direction.

Last updated on August 13, 2024