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.
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.
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.
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
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
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.
There are dozens upon dozens of permissions in Android. Here are some of the permissions we will see in this book:
INTERNET, if your application wishes to access the Internet through any means from your own process, using anything from raw Java sockets through the
WRITE_EXTERNAL_STORAGE, for writing data to external storage
ACCESS_FINE_LOCATION, for determining where the device is
READ_CONTACTS, to get at personally-identifying information of arbitrary contacts that the user has in their Contacts app
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
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
<uses-permission> element in your manifest, as a direct
child of the root
<manifest> element (i.e., as a peer element
<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
<?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
to your manifest, through a process called “manifest merger”.
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)
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)
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
Figure 254: Permission Confirmation Screen, on Play Store Web Site
We will discuss more about permission groups and this
concept later in this chapter.
On Android 6.0 and higher, when the user installs your app from the
Play Store, what happens depends upon the value of
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
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.
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:
Figure 255: 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.
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:
Figure 256: Permission Confirmation Screen, on Android 6.0
The preview of this section was whisked away by a shark-infested tornado.
The preview of this section took that left turn at Albuquerque.
The preview of this section is sleeping in.
The preview of this section was eaten by a grue.