Handle Runtime Permissions in Android

SHISHIR
PROGRAMMING LITE
Published in
7 min readJul 4, 2018
  • From beginning with Android 6.0 Marshmallow (API LEVEL 23)(
    Marshmallow was released on October 5, 2015), Google has introduced a new runtime permission model.
  • According to this model users are not prompted for permission at the time of installing the app, rather developers need to check for and request permission at runtime (i.e. The particular permission must required before performing any action)
  • Users can then allow or deny the permission, users can also grant or revoke permission anytime from settings even if the app is already installed.
  • Developers have to handle all the use cases. If not handled properly, it can cause application crashes.

Now here we’ll look into the android runtime permissions and handle them.

Types of Runtime Permissions

Android defines basically three types of permissions:

  1. Normal Permissions
  2. Signature Permissions
  3. Dangerous Permissions

Both Normal and Dangerous permissions must be defined in the Manifest file. But only Dangerous permissions are checked at runtime, Normal permissions are not.

Normal Permissions

Some permissions are automatically granted to the application. Just we need to declare those permissions in AndroidManifest.xml and it will work fine. Those permissions are called Normal Permissions. An example of a normal permission is INTERNET.

Normal Permissions are automatically granted to the application.

Click to see all permissions list

Signature Permissions

A permission that the system grants only if the requesting application is signed with the same certificate as the application that declared the permission. If the certificates match, the system automatically grants the permission without notifying the user or asking for the user’s explicit approval.

Dangerous Permissions

Some permissions may affect the users private information, or could potentially affect his data or the operation of other application are called Dangerous Permissions. For example, the ability to read the user’s contacts is a dangerous permission. Some other examples are CONTACTS , CAMERA ,CALENDAR, LOCATION , PHONE , STORAGE , SENSORS , MICROPHONE, etc.

Dangerous permissions must be granted by the user at runtime to the app.

Dangerous permissions are grouped into categories that make it easier for the user to understand what they are allowing the application to do. If any permission in a Permission Group is granted. Another permission in the same group will be automatically granted as well. For example , once WRITE_CONTACTS is granted, application will also grant READ_CONTACTS and GET_ACCOUNTS as all three permissions in the same group.

Click to see all permissions list

Before Marshmallow (API 23)

Before Marshmallow (API 23) all the requested permissions are presented to the user before installing the application. If the user denies a required permission, the related application cannot be installed. And there was no way to grant or deny any permission after installation.

Workflow of Runtime Permission

Here is the workflow of runtime permission to open camera in android.

Flow diagram of runtime permission to open camera in android.

First of all we check the SDK Version. If SDK version is less than 23(Marshmallow) then we don’t need to ask for permission as Runtime Permission started from Marshmallow. And we can open camera.

If SDK version is equal to or greater than 23, then we check the permission is already granted or not by calling contextCompat.checkSelfPermission(). If permission is granted then we can open camera. If the permission is not granted we must request for the permission to the user. But in this case, we have to handle three cases.

Case 1:

The permission never asked before.

Case 2:

The permission asked before but user denied without checking ‘Never ask again’.

Case 3:

The permission asked before but user denied with checking ‘Never ask again’.

Only a method can handle our three cases . The method is shouldShowRequestPermissionRationale. the method returns a boolean value.

This method returns true if the the permission asked before but the user denied without checking ‘Never ask again’. which matches our Case 2.

But it will return false in two cases.

  • If the permission is requested first time. Which matches our Case 1.
  • If the permission asked before but the user denied with checking ‘Never ask again’. Which matches our Case 3.

So here only shouldShowRequestPermissionRationale method can match our three cases. Now just need to solve them with help of this method.

Solution of Case 2:

Solution of case 2 is very easy. Because the method shouldShowRequestPermissionRationale returns true only when the permission asked before but the user denied without checking ‘Never ask again’. So we can just give an explanation about why the app needs this permission. And if the user agree to our explanation we can request for permission again. That’s it.

Solution of Case 1 and Case 3:

But solution of case 1 and case 2 is little tricky. Because we know the method shouldShowRequestPermissionRationale returns false if the permission never asked before (Case 1) or the permission asked but the user denied with checking ‘Never ask again’ (Case 3). But we have to catch this two cases. How can we do that ?

Yes we can do this with the help of Shared Preferences , We can just put a flag on Shared Preferences for checking weather the permission is being asked first time or not. And the problem is solved. By this following code we can put our flag on Shared Preferences.

Putting flag on Shared Preferences for checking weather permission is being asked first time or not.

In firstTimeAsking, we just put a boolean flag with the permission string as key.

In isFirstTimeAsking, we get the value associated with the permission string and return it.

Notice that we set the default value as true. That’s why if the key is not in the preference file or even if the file itself is not created, the android framework will automatically create a file with the name we gave and will return the default value we set.

We will call this method every time when a permission request is required but after first call, we set the flag as false using firstTimeAsking(permission, false).

Here is the code.

We can put all these logic in a method and use a callback to get which case we should handle now. The code would be like this.

Now all the three cases are solved.

If you still getting confused on how to use it and you want to be more clear then see this full project Runtime Permission in Android in Github.

Handle the permissions request response

When the user responds to your app’s permission request, the system invokes your app’s onRequestPermissionsResult() method. So you have to override that method to find out whether the permission was granted or denied. And the same request code that you passed to requestPermissions() method is also passed to the callback. For deeper understanding, you see the following callback method:

Handle permission request result on onRequestPermissionResult() method.

Asking for Multiple Permissions at a time

Asking Multiple Permissions at a time in Android

Permissions from Fragment

In Fragment, you can ask for permission in two ways

Way 1:

ActivityCompat.requestPermissions(this, permissionsList, REQUEST_CODE);

In this way you will get permission result on onRequestPermissionsResult method of the activity not the fragment. That’s why you have to override the onRequestPermissionsResult method of the activity instead of Fragment.

Way 2:

requestPermissions(permissionsList, REQUEST_CODE);

In this way you will get permission result on onRequestPermissionsResult() method of fragment. But you must call

super.onRequestPermissionsResult(requestCode, permissions, grantResults);

in activity’s onRequestPermissionsResult() method.

So the best way is

1) In fragment, ask permission just using

requestPermissions(permissionList, REQUEST_CODE)

instead of

ActivityCompat.requestPermission(Activity, String[], int)

2) In activity’s onRequestPermissionsResult, call

super.onRequestPermissionsResult(requestCode, permissions, grantResults);

so it will pass the result to fragment. Mind it this is the most important call and you must do it.

3) Now in fragment’s onRequestPermissionsResult, write the code that you want to handle the result.

ContextCompat vs AcitvityCompat

ActivityCompat is a subclass (child) of ContextCompat so you can pass either one whenever object of ContextCompat class is required.

ContextCompat.checkSelfPermission(Context context, String permission)

This method is used simply for checking whether you are having requested permission available for your app or not.

ActivityCompat.requestPermissions(Activity activity, String[] permissions,int reqCode)

This method is used for requesting permissions.

Shorten source code with 3rd Party Library

There are many popular permissions libraries that you can use for shorten your code. Some of them are given below:

--

--

SHISHIR
PROGRAMMING LITE

{ 'designation' : 'Lead Software Engineer' , 'hobby' : [ 'Music', 'Photography', 'Travelling' ] ,’email’: ‘shishirthedev@gmail.com’ }