Part VI

Other Android Capabilities

Chapter 38

Requesting and Requiring Permissions

In the late 1990s, a wave of viruses spread through the Internet, delivered via e-mail, using contact information culled from Microsoft Outlook. A virus would simply e-mail copies of itself to each of the Outlook contacts that had an e-mail address. This was possible because, at the time, Outlook did not take any steps to protect data from programs using the Outlook API, since that API was designed for ordinary developers, not virus authors.

Nowadays, many applications that hold onto contact data secure that data by requiring that a user explicitly grant rights for other programs to access the contact information. Those rights could be granted on a case-by-case basis or all at once at install time.

Android is no different, in that it requires permissions for applications to read or write contact data. Android’s permission system is useful well beyond contact data, and for content providers and services beyond those supplied by the Android framework.

You, as an Android developer, will frequently need to ensure that your applications have the appropriate permissions to do what you want to do with other applications’ data. You may also elect to require permissions for other applications to use your data or services, if you make those available to other Android components. This chapter covers how to accomplish both these ends.

Mother, May I?

Requesting the use of other applications’ data or services requires the uses-permission element to be added to your AndroidManifest.xml file. Your manifest may have zero or more uses-permission elements, all as direct children of the root manifest element.

The uses-permission element takes a single attribute, android:name, which is the name of the permission your application requires:

<uses-permission
  android:name="android.permission.ACCESS_LOCATION" />

All of the stock system permissions begin with android.permission and are listed in the Android SDK documentation for Manifest.permission. Third-party applications may have their own permissions, which, hopefully, they have documented for you. Here are some of the more useful permissions:

  • INTERNET, if your application wishes to access the Internet through any means, from raw Java sockets through the WebView widget
  • WRITE_EXTERNAL_STORAGE, for writing data to the SD card (or whatever the device has designated as external storage)
  • NFC, for performing I/O with the near-field communication (NFC) radio on newer devices
  • ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION, for determining where the device is located
  • CALL_PHONE, to allow the application to place phone calls directly, without user intervention

Permissions are confirmed at the time the application is installed. The user will be prompted to confirm that it is acceptable for your application to do what the permission calls for. Hence, it is important that you ask for as few permissions as possible and justify those you seek, so users do not elect to skip installing your application because you ask for too many unnecessary permissions. This prompt will not appear when loading an application via USB, such as during development.

If you do not have the desired permission and try to do something that needs it, you should get a SecurityException informing you of the missing permission. Note that you will fail on a permission check only if you forgot to ask for the permission—it is impossible for your application to be running and not have been granted your requested permissions.

Halt! Who Goes There?

The other side of the coin 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: whether you can read or modify contacts, send SMS messages, and so forth. If your application does not store information that might be considered private, security is less of 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. You need to supply three pieces of information:

  • The symbolic name of the permission: To keep your permissions from colliding with those from other applications, you should use your application’s Java namespace as a prefix.
  • A label for the permission: Choose something short that would be understandable by users.
  • A description for the permission: Choose something a wee bit longer that is understandable by your users.

Following is an example:

<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.

There are two ways for your application to enforce permissions, dictating where and under what circumstances they are required. The easier option is to indicate in the manifest where permissions are required. The more difficult option is to enforce permissions in your code. Both options are discussed next.

Enforcing Permissions via the Manifest

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 the following:

  • Activities cannot be started without the permission.
  • Services cannot be started, stopped, or bound to an activity without the permission.
  • 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.

First, 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 and write permissions in code by checking those methods for the permissions you need from Java.

Second, 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.

May I See Your Documents?

There is no automatic discovery of permissions at compile time; all permission failures occur at runtime. Hence, it is important that youdocument the permissions required for your public APIs, including content providers, services, and activities intended for launching from other activities. Otherwise, programmers who are attempting to interface with your application will have to find out the permission rules by trial and error.

Furthermore, you should expect that users of your application will be prompted to confirm any permissions your application says it needs. Hence, you need to document for your users what they should expect, lest they get confused by the question posed by the device and elect to not install or use your application. You may wish to use string resources for this, so you can internationalize your permission details the way you internationalize all the other messages and prompts in your application. You should also be mindful that your users will be reading your permission details on a phone or tablet screen, so keep your justifications short and to the point.

New Permissions in Old Applications

Sometimes, Android introduces new permissions that govern behavior that formerly did not require permissions. WRITE_EXTERNAL_STORAGE is one example. Originally, applications could write to external storage without any permission at all. Android 1.6 introduced WRITE_EXTERNAL_STORAGE, which is required before you can write to external storage. However, applications that were written before Android 1.6 could not possibly request that permission, since it did not exist at the time. Breaking those applications would seem to be a harsh price for progress.

What Android does is grandfather in certain permissions for applications supporting earlier SDK versions. In particular, if you have <uses-sdkandroid:minSdkVersion="3"> in your manifest, saying that you support Android 1.5, your application will automatically request WRITE_EXTERNAL_STORAGE and READ_PHONE_STATE, even if you do not explicitly request those permissions. People installing your application on an Android 1.5 device will see these requests.

The number of new permissions introduced grows as the handsets take on new capabilities and users’ attitudes toward underlying features mature, requiring more fine-grained approaches to managing access. New permissions in Android 4.0 include the following:

  • ADD_VOICEMAIL: Allows an application to inject voicemail into the system
  • BIND_TEXT_SERVICE: Required for any service you write that derives from TextService
  • BIND_VPN_SERVICE: Required for any service you write that derives from VpnService
  • READ_PROFILE: Provides access to read a user’s personal profile data
  • WRITE_PROFILE: Allows an application to update or change a user’s personal profile data

Eventually, when you drop support for the older version of permissions (e.g., switch to <uses-sdkandroid:minSdkVersion="4">), Android will no longer automatically request those permissions. Hence, if your code really does need those permissions, you will need to ask for them yourself.

Permissions: Up Front or Not at All

The permission system in Android is not especially flexible. Notably, you have to ask for all permissions you might ever need up front, and the user has to agree to all of them or abandon the installation of your app.

This means you cannot do the following:

  • Create optional permissions, ones the user could say “no, thanks” to, that your application could react to dynamically
  • Request new permissions after installation, which means that even if a permission is needed only for some lightly used feature, you have to ask for it anyway

Hence, as you determine the feature list for your app, it is important that you keep permissions in mind. Every additional permission that you request is a filter that will cost you some portion of your prospective audience. Certain combinations—such as INTERNET and READ_CONTACTS—will have a stronger effect, as users may fear what the combination can do. You will need to decide for yourself whether attracting additional users by offering the feature is worth the cost of requiring the permissions the feature needs to operate.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.52.96