The following is the first few sections of a chapter from The Busy Coder's Guide to Android Development, plus headings for the remaining major sections, to give you an idea about the content of the chapter.


Advanced Permissions

Adding basic permissions to your app to allow it to, say, access the Internet, is fairly easy. However, the full permissions system has many capabilities beyond simply asking the user to let you do something. This chapter explores other uses of permissions, from securing your own components to using signature-level permissions (your own or Android’s).

Prerequisites

Understanding this chapter requires that you have read the core chapters, particularly the chapter on permissions and the chapter on signing your app.

One of the sample apps uses RxJava and RxAndroid, which are introduced elsewhere in the book.

Securing Yourself

Principally, at least initially, permissions are there to allow the user to secure their device. They have to agree to allow you to do certain things, such as reading contacts, that they might not appreciate.

The other side of the coin, of course, is to secure your own application. If your application is mostly activities, security may be just an “outbound” thing, where you request the right to use resources of other applications. If, on the other hand, you put content providers or services in your application, you will want to implement “inbound” security to control which applications can do what with the data.

Note that the issue here is less about whether other applications might “mess up” your data, but rather about privacy of the user’s information or use of services that might incur expense. That is where the stock permissions for built-in Android applications are focused – can you read or modify contacts, can you send SMS, etc. If your application does not store information that might be considered private, security is less an issue. If, on the other hand, your application stores private data, such as medical information, security is much more important.

The first step to securing your own application using permissions is to declare said permissions, once again in the AndroidManifest.xml file. In this case, instead of uses-permission, you add permission elements. Once again, you can have zero or more permission elements, all as direct children of the root manifest element.

Declaring a permission is slightly more complicated than using a permission. There are three pieces of information you need to supply:

<permission
  android:name="vnd.tlagency.sekrits.SEE_SEKRITS"
  android:label="@string/see_sekrits_label"
  android:description="@string/see_sekrits_description" />

This does not enforce the permission. Rather, it indicates that it is a possible permission; your application must still flag security violations as they occur.

Enforcing Permissions via the Manifest

There are two ways for your application to enforce permissions, dictating where and under what circumstances they are required. The easier one is to indicate in the manifest where permissions are required.

Activities, services, and receivers can all declare an attribute named android:permission, whose value is the name of the permission that is required to access those items:

<activity
  android:name=".SekritApp"
  android:label="Top Sekrit"
  android:permission="vnd.tlagency.sekrits.SEE_SEKRITS">
  <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category
      android:name="android.intent.category.LAUNCHER" 
/>
  </intent-filter>
</activity>

Only applications that have requested your indicated permission will be able to access the secured component. In this case, “access” means:

  1. Activities cannot be started without the permission
  2. Services cannot be started, stopped, or bound to an activity without the permission
  3. Intent receivers ignore messages sent via sendBroadcast() unless the sender has the permission

Enforcing Permissions Elsewhere

In your code, you have two additional ways to enforce permissions.

Your services can check permissions on a per-call basis via checkCallingPermission(). This returns PERMISSION_GRANTED or PERMISSION_DENIED depending on whether the caller has the permission you specified. For example, if your service implements separate read and write methods, you could require separate read versus write permissions in code by checking those methods for the permissions you need from Java.

Also, you can include a permission when you call sendBroadcast(). This means that eligible broadcast receivers must hold that permission; those without the permission are ineligible to receive it. We will examine sendBroadcast() in greater detail elsewhere in this book.

Requiring Standard System Permissions

While normally you require your own custom permissions using the techniques described above, there is nothing stopping you from reusing a standard system permission, if it would fit your needs.

For example, suppose that you are writing YATC (Yet Another Twitter Client). You decide that in addition to YATC having its own UI, you will design YATC to be a “Twitter engine” for use by third party apps:

You could, and perhaps should, implement your own custom permission. However, since any app can get to Twitter just by having the INTERNET permission, one could argue that a third-party app should just need that same INTERNET permission to use your API (rather than integrating JTwitter or another third-party JAR).

Signature Permissions

The preview of this section was lost in the sofa cushions.

The Custom Permission Vulnerability

The preview of this section is being chased by zombies.

Custom Dangerous Permissions, and Android 6.0

The preview of this section was traded for a bag of magic beans.

Finding the Available Permissions

The preview of this section is in the process of being translated from its native Klingon.