Book Image

Android 6 Essentials

By : Yossi Elkrief
Book Image

Android 6 Essentials

By: Yossi Elkrief

Overview of this book

Android 6 is the latest and greatest version of the Android operating system, and comes packed with cutting edge new features for you to harness for the benefit of building better applications. This step-by-step guide will take you through the basics of the Android Marshmallow permissions model and beyond into other crucial areas such as the Audio,Video,Camera API and Android’s at work features. Learn how to create, deploy, and manage Android applications with Marshmallow’s API and the latest functionalities. The combination of instructions and real-world examples will make your application deployment and testing a breeze.
Table of Contents (16 chapters)
Android 6 Essentials
Credits
About the Author
Acknowledgments
About the Reviewer
www.PacktPub.com
Preface
Index

Taking coding permissions into account


Well, after all the explanations, we've reached the coding part, and this is where we will get our coding hands dirty. The following are key methods used for handling permissions:

  • Context.checkSelfPermission(): This checks whether your app has been granted a permission

  • Activity.requestPermission(): This requests a permission at runtime

Even if your app is not yet targeting Android Marshmallow, you should test your app and prepare to support it.

Testing permissions

In the Android Marshmallow permissions model, your app must ask the user for individual permissions at runtime. There is limited compatibility support for legacy apps, and you should test your app and also test a version to make sure it's supported.

You can use the following test guide and conduct app testing with the new behavior:

  • Map your app's permissions

  • Test flows with permissions granted and revoked

The adb command shell can be quite helpful to check for permissions:

  • Listing application permissions and status by group can be done using the following adb command:

    adb shell pm list permissions -g
    
  • You can grant or revoke permissions using the following adb syntax:

    adb shell pm [grant|revoke] <permission.name>
    
  • You can grant permissions and install apk using the following adb command:

    adb install -g <path_to_apk>
    

Coding for runtime permissions

When we want to adjust our application to the new model, we need to make sure that we organize our steps and leave no permission stranded:

  • Check what platform the app is running on: When running a piece of code that is sensitive at the API level, we start by checking the version/API level that we are running on.

    By now, you should be familiar with Build.VERSION.SDK_INT.

  • Check whether the app has the required permission: Here, we get ourselves a brand new API call:

    Context.checkSelfPermission(String permission_name).

    With this, we silently check whether permissions are granted or not.

    This method returns immediately, so any permission-related controls/flows should be dealt with by checking this first.

  • Prompting for permissions: We have a new API call, Activity.requestPermissions (String[] permissions, int requestCode). This call triggers the system to show the dialog requesting a permission. This method functions asynchronously.

    You can request more than one permission at once. The second argument is a simple request code returned in the callback so that you can recognize the calls. This is just like how we've been dealing with startActivityForResult() and onActivityResult() for years.

    Another new API is Activity.shouldShowRequestPermissionRationale(String permission).

    This method returns true when you have requested a permission and the user denied the request. It's considered a good practice after verifying that you explain to the user why you need that exact permission. The user can decide to turn down the permission request and select the Don't ask again option; then, this method will return false.

The following sample code checks whether the app has permission to read the user's contacts. It requests the permission if required, and the result callback returns to onRequestPermissionsResult:

if (checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
  requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, SAMPLE_MATRIXY_READ_CONTACTS);
}
//Now this is our callback
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
  switch (requestCode) {
  case SAMPLE_MATRIXY_READ_CONTACTS:
    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
      // permission granted - we can continue the feature flow.
    } else {
      // permission denied! - we should disable the functionality that depends on this permission.
    }
  }
}

Just to make sure we all know the constants used, here's the explanation:

  • public static final int PERMISSION_DENIED=-1:

    Since it's API level 1, permission has not been granted to the given package

  • public static final int PERMISSION_GRANTED=0:

    Since it's API level 1, permission has been granted to the given package.

If the user denies your permission request, your app should take the appropriate action, such as notifying the user why this permission is required or explaining that the feature can't work without it.

Note

Your app cannot assume user interaction has taken place because the user can choose to reject granting a permission along with the do not show again option; your permission request is automatically rejected and onRequestPermissionsResult gets the result back.

Best practices and usage notes

The new permissions model has brought to life a smoother experience for users and a bit more code-handling for developers. It makes it easier to install and update apps and feel comfortable with what the apps are doing.

Minimalism is a great option

Don't be a permission hog! In our application life cycle, we should try to minimize our permission requests. Asking for a lot of permissions and maintaining them can seem hazardous for some, and we should try and make the feature smooth and ask for the smallest number of permissions as far as possible in order to allow relaxed, undisturbed usage. Consider using intents whenever possible—rely on other applications doing some of the work for us (fewer permissions means less friction, turning a good app into a great one).

Asking for too many permissions at once

Users can get distracted by too many dialogs popping up, asking them for more and more permissions. Instead, you should ask for permissions as and when you need them.

However, we have some exceptions to every rule. Your app may require a few permissions to begin with, such as a camera application showing the camera permissions right at the beginning. However, setting the photo to your contact can be done and requested only when the user triggers that specific action. Try to map your flow and make it easier for users to understand what is going on. Users will understand that you've requested permissions for contacts if they have asked to set information to a contact via your app.

One more suggestion: apps with a tutorial can integrate the essential permissions' request in the tutorial, allowing the users to better understand the flow and why each permission is used.

Honesty can be a great policy

When asking for a permission, the system shows a dialog stating which permission your app wants, but it doesn't say why. Consider users who hate being left in the dark thinking why this permission is needed now or users who deny the permissions due to speculation. Things can be even worse: sometimes, a user's cursor may be 2 cm away from the 1-star rating or the uninstall button.

This is why it's a good idea to explain why your app wants the permissions before calling requestPermissions().

Keep in mind that most developers will choose a tutorial but a lot of users may choose to skip tutorials whenever possible, so you must make sure that you can provide information about permissions, apart from the ones in the tutorial.