Select Page

People have trust issues when it comes to mobile apps, thanks to all the recent leaks and hacks. Permissions on Android have always been an important area to consider when developing applications.

System Permissions, as such, is of two types:

– The ones that read your personal data [dangerous]

– And the ones that don’t [normal]

Normal permissions cover areas where your app needs to access data or resources outside the app’s sandbox, but where there’s very little risk to the user’s privacy or the operation of other apps.For example, permission to turn on the flashlight is a normal permission.

Dangerous permissions cover areas where the app wants data or resources that involve the user’s private information, or could potentially affect the user’s stored data or the operation of other apps.For example, the ability to read the user’s contacts is a dangerous permission.

Until Android 5.1(API level 22), users must grant your app a variety of permissions while installing.

Thanks to Android 6.0 (API level 23), now users can grant permissions on runtime.This approach streamlines the app install / update process. It also gives the user more control over the app’s functionality.

Enter the hack

As a developer, you must check whether you have that permission every time you perform an operation that requires that permission. The user is always free to revoke the permission, so even if the app used the camera yesterday, it can’t assume it still has that permission today.

Here comes the fancy flow-chart to explain how you can handle this,

droid-updated

Step [1]: Check if the build version is greater than or equal to 23. Make use of the following code to do so:


if(Build.VERSION.SDK_INT >= 23) 
    if (checkAndRequestPermissions(permissions, request_code))
        permissionResultCallback.PermissionGranted(request_code);
else
    permissionResultCallback.PermissionGranted(request_code);

Step [2]: Check if the needed permissions have already been granted or not.


int hasPermission = ContextCompat.checkSelfPermission(current_activity,permissions.get(i));

if (hasPermission != PackageManager.PERMISSION_GRANTED) 
{
    listPermissionsNeeded.add(permissions.get(i));
}

Step [3]: If the permissions are not granted in step 2, check if the user has already been asked for permissions earlier. If yes, check whether the user has enabled “Don’t ask again”. Else, show the rationale dialog to the user with an explanation of why the app needs the permission.


// Request Permissions

if (!listPermissionsNeeded.isEmpty())
{
    ActivityCompat.requestPermissions(current_activity,listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),request_code);
    return false;
}

// Check to show the rationale dialog 

if(ActivityCompat.shouldShowRequestPermissionRationale(current_activity,listPermissionsNeeded.get(i)))
        pending_permissions.add(listPermissionsNeeded.get(i));
else
{
    Log.i("Go to settings","and enable permissions");
    permissionResultCallback.NeverAskAgain(req_code);
    Toast.makeText(current_activity, "Go to settings and enable permissions", Toast.LENGTH_LONG).show();
    return;
}

Step [4]: If the user has selected “Ok” in the rationale dialog box, then the respective permission must be shown. But if the user has gone with “cancel” then you should go ahead and handle the permission.


new AlertDialog.Builder(current_activity)
 .setMessage(" Explain here why the app needs permissions ")
 .setPositiveButton("Ok", okListener)
 .setNegativeButton("Cancel", okListener)
 .create()
 .show();

Step [5]: When the user accepts all the permissions needed by the app, exit the above loop and continue with the app’s workflow. But when the app is granted with only a few and not all of the permissions (like permission A is granted and not B), your app must be able to work with limited features.

How to use

  • PermissionUtils: Used to check and request the needed permission from the user.
  • PermissionsResultCallback: This is a callback that you use to execute code when the permissions you have requested are either granted or denied.
interface PermissionResultCallback
{
 void PermissionGranted(int request_code);
 void PartialPermissionGranted(int request_code, ArrayList<String> granted_permissions);
 void PermissionDenied(int request_code);
 void NeverAskAgain(int request_code);
}

Getting permissions from the user is simple. First, add all the needed permissions in a list.

 ArrayList&lt;String&gt;permissions=new ArrayList<>();


 permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
 permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);

Create an instance for the class “PermissionUtils”, and call the function check_permission by passing the list of permissions, the purpose of those permission and the request code.

 permissionUtils=new PermissionUtils(getApplicationContext());
 permissionUtils.check_permission(permissions,"Explain here why the app needs permissions",1);

Then redirect the onRequestPermissionsResult to permissionUtils.onRequestPermissionsResult

 @Override
 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
 @NonNull int[] grantResults) {

 // redirects to utils

 permissionUtils.onRequestPermissionsResult(requestCode,permissions,grantResults);

 }

For getting the callbacks you need to include PermissionResultCallback interface into your activity,
and also implement the needed methods.


public class PermissionActivity extends AppCompatActivity implements
 OnRequestPermissionsResultCallback,PermissionResultCallback

 // Callback functions

 @Override
 public void PermissionGranted(int request_code) {
 Log.i("PERMISSION","GRANTED");
 }

 @Override
 public void PartialPermissionGranted(int request_code, ArrayList&amp;lt;String&amp;gt; granted_permissions) {
 Log.i("PERMISSION PARTIALLY","GRANTED");
 }

 @Override
 public void PermissionDenied(int request_code) {
 Log.i("PERMISSION","DENIED");
 }

 @Override
 public void NeverAskAgain(int request_code) {
 Log.i("PERMISSION","NEVER ASK AGAIN");
 }

In AndroidManifest.xml

Specify all the needed permissions. If you don’t, permission requests fail silently. That’s an Android thing.

I created a sample project on GitHub to demonstrate the things covered in this article.

View on GithubDownload .zip

Feel free to comment and share, keep watching this space get more updates on Android Stuff!

 

Elsewhere

Jaison Fernando

Android Developer at NFN Labs
Elsewhere