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.


Requesting Permissions

In the late 1990’s, a wave of viruses spread through the Internet, delivered via email, using contact information culled from Microsoft Outlook. A virus would simply email copies of itself to each of the Outlook contacts that had an email 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 your applications have the appropriate permissions to do what you want to do with other applications’ data. This chapter covers this topic, both the classic approach used for all permissions prior to Android 6.0 and the new runtime permission system used for certain permissions in Android 6.0+.

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 will be discussed later in this book.

Frequently-Asked Questions About Permissions

Permissions are occasionally a confusing topic in Android app development, more so now that Android 6.0 has arrived and has changed the permission system a fair bit. Here are some common questions about permissions to help get us started.

What Is a Permission?

A permission is a way for Android (or, sometimes, a third-party app) to require an app developer to notify the user about something that the app will do that might raise concerns with the user. Only if an app holds a certain permission can the app do certain things that are defended by that permission.

Mechanically, permissions take the form of elements in the manifest. Right now, we are focusing on requesting and holding permissions, and so we will be working with the <uses-permission> element.

When Will I Need a Permission?

Most permissions that you will deal with come from Android itself. Usually, the documentation will tell you when you need to request and hold one of these permissions.

However, occasionally the documentation has gaps.

If you are trying out some code and you crash with a SecurityException the description of the exception may tell you that you need to hold a certain permission — that means you need to add the corresponding <uses-permission> element to your manifest.

Third-party code, including Google’s own Play Services SDK, may define their own custom permissions. Once again, ideally, you find out that you need to request a permission through documentation, and otherwise you find out through crashing during testing.

What Are Some Common Permissions, and What Do They Defend?

There are dozens upon dozens of permissions in Android. Here are some of the permissions we will see in this book:

In this book and in casual conversation, we refer to the permissions using the unique portion of their name (e.g., INTERNET). Really, the full name of the permission will usually have android.permission. as a prefix (e.g., android.permission.INTERNET), for Android-defined permissions. Custom permissions from third-party apps should use a different prefix. You will need the full permission name, including the prefix, in your manifest entries.

How Do I Request a Permission?

Put a <uses-permission> element in your manifest, as a direct child of the root <manifest> element (i.e., as a peer element of <application>), with an android:name attribute identifying the permission that you are interested in.

For example, here is a sample manifest, with a request to hold the WRITE_EXTERNAL_STORAGE permission:

<?xml version="1.0"?>
<manifest package="com.commonsware.android.fileseditor"
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:versionCode="1"
  android:versionName="1.0">

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

  <supports-screens
    android:anyDensity="true"
    android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="true" />

  <application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/Theme.Apptheme">
    <activity
      android:name=".MainActivity"
      android:label="@string/app_name">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
  </application>

</manifest>

This is sufficient for most permissions and most devices. Permissions considered to be dangerous need special attention on Android 6.0+, and we will cover that in grand detail later in this chapter.

Note that you are welcome to have zero, one, or several such <uses-permission> elements. Also note that some libraries that you elect to use might add their own <uses-permission> elements to your manifest, through a process called “manifest merger”.

When Is the User Informed About These Permissions?

Well, that gets complicated. It depends on the permission, the version of Android the user is using, from where the user is installing the app, and the phase of the moon.

(well, OK, not really that last one)

Installing Through SDK Tools

Anyone who installs an app using Android Studio will not be prompted for permissions. The same holds true for anyone using anything else based on the Android SDK tools — while the app may request permissions, the user is not prompted for them, and the permissions are granted.

(Android 6.0+ and dangerous permissions change this up a bit – more on that later in this chapter)

Installing from the Play Store, Android 5.1 and Older

If the user is running an Android 5.1 or older device, and the user goes to install your app from the Play Store, the user will be presented with a roster of permission groups that contain permissions that you are requesting and that are considered to be dangerous:

Permission Confirmation Screen, on Play Store Web Site
Figure 260: Permission Confirmation Screen, on Play Store Web Site

We will discuss more about permission groups and this dangerous concept later in this chapter.

Installing from the Play Store, Android 6.0+

On Android 6.0 and higher, when the user installs your app from the Play Store, what happens depends upon the value of targetSdkVersion for your app.

If your targetSdkVersion is 22 or lower, you get the same behavior as is described above, where the user sees the list of permission groups which contain permissions that you are requesting and that are considered to be dangerous.

If your targetSdkVersion is 23 or higher, the user is not prompted about permissions at install time. Instead these prompts will occur when the user runs your app and when you ask the user for the permissions, as we will see later in this chapter.

Installing by Other Means, Android 5.1 and Older

If you install an app on Android 5.1 or older, by any means (e.g., downloading from a Web site), you will be prompted with a list of all requested permissions:

Permission Confirmation Screen, on Android 4.4
Figure 261: Permission Confirmation Screen, on Android 4.4

Note that this prompt will not appear until you actually have downloaded the app and have begun the installation process. Before then, the device cannot examine the manifest inside the APK file to find the permissions.

Installing by Other Means, Android 6.0+

If your app’s targetSdkVersion is 23 or higher, and you install the app on an Android 6.0+ device by other means than the Play Store, you will not be prompted about any permissions at install time:

Permission Confirmation Screen, on Android 6.0
Figure 262: Permission Confirmation Screen, on Android 6.0

Characteristics of Permissions

Several bits of information make up a permission, and some of those affect app developers or users.

Name

We have already seen that permissions have names, and you use them in the android:name attribute of the <uses-permission> element to identify a permission that you would like your app to hold.

Android framework-defined permissions will begin with android.permission. Permissions from libraries or third-party apps will have some other prefix. Make sure that when you create your <uses-permission> element that you are using the fully-qualified permission name, including android.permission or any other prefix.

Also note that Android is case-sensitive, so make sure you use the case of the permission as documented (e.g., android.permission.INTERNET). Some versions of Android Studio had a bug where if you let the IDE auto-complete a <uses-permission> element for you, sometimes it would have the android:name value appear IN ALL CAPS. This is a bug that has since been fixed, so hopefully it will not affect you in the future.

Protection Level

The definition of a permission, in the framework or in third-party code, will have a “protection level”. This describes how the permission itself should be validated. The two protection levels that you will encounter most often are normal and dangerous.

Normal

A normal permission is something that the user might care about, but probably not. So, while we need to request the permission in the manifest via <uses-permission>, the user will not be bothered about this permission at install time.

The classic example is the INTERNET permission. Most Android apps wind up requesting this permission, either for functionality written by the developers or functionality pulled in from libraries (e.g., ad banners). INTERNET is considered normal, so while we need to request the INTERNET permission in the manifest, the user is not informed about this permission anymore at install time.

(the “anymore” note is because in the early days of Android, users were informed about all permissions, regardless of protection level)

Users can see normal permissions, though, in other places:

Dangerous

A dangerous permission is one that the definers of the permission (e.g., Google) wants to ensure that the user is aware of and has agreed to.

Classically, this meant that the user would be prompted for this permission at install time. On old versions of Android and the Play Store, dangerous permissions would be listed before normal permissions.

With Android 6.0+, while dangerous permissions are not displayed at install time (for apps with a targetSdkVersion of 23 or higher), they will be displayed to the user while the app is running, before the app tries doing something that requires one of those permissions. This is a significant behavior change, so we will be covering it in depth later in this chapter.

Permission Group

Permissions are collected into permission groups.

In the early days of Android, app developers were oblivious to this, as permission groups had no effect on app development, runtime behavior, or user experience.

In the past few years, the “permission” prompts at install time have really been prompting about permission groups. The user is told that the app is requesting permissions from certain groups. Moreover, the blessing that the user gives — by virtue of continuing to install the app — is by group, not by permission. If some future update to the app would ask for a new permission, but one from a group that the user agreed to previously, the user would not be informed about this new permission request.

With Android 6.0, permission groups also extend to the runtime permission UX, as while we developers will still request individual permissions, the user will be asked to grant rights with respect to permission groups.

Maximum SDK Version

<uses-permission> can have an android:maxSdkVersion attribute. This indicates the highest API level for which we need the permission. If the app is running on newer versions of Android, skip the permission.

This is for cases where Android relaxes restrictions over time. We will see an example of this, in the form of the WRITE_EXTERNAL_STORAGE permission, in an upcoming chapter.

Minimum SDK Version

You might think that <uses-permission> would have an android:minSdkVersion attribute to serve as the counterpart to android:maxSdkVersion. The minSdkVersion would indicate the lowest API level for which to request a permission; older devices would skip the permission.

Alas, this is not available.

However, there is the awkwardly-named <uses-permission-sdk-23> element.

This element functions identically to <uses-permission> on Android 6.0+ devices. On older devices, it is ignored.

This element illustrates a problem with the permission system in Android: you have to put all permissions that you want in the manifest. Prior to the runtime permission system in Android 6.0, this would mean that developers who need some controversial permission (e.g., READ_CONTACTS) for some fringe feature would need to request the permission from everyone, not just those who use the feature. As we will see, the runtime permission system lets us not bother the user until they try using the secured feature. <uses-permission-sdk-23> would allow us to not bother with the permission at all on older devices, where its presence might scare away potential users.

New Permissions in Old Applications

The preview of this section apparently resembled a Pokémon.

Android 6.0+ Runtime Permission System

The preview of this section is presently indisposed.

A Simple Runtime Permission Abstraction

The preview of this section is [REDACTED].