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 a 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 other than 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. 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.
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 important built-in permissions:
INTERNET
, if your application wishes to access the Internet through any means, from raw Java sockets through the WebView
widgetREAD_CALENDAR
, READ_CONTACTS
, and the like for reading data from the built-in content providersWRITE_CALENDAR
, WRITE_CONTACTS
, and the like for modifying data in the built-in content providersPermissions are confirmed at the time the application is installed. The user will be prompted to confirm it is acceptable for your application to do what the permission calls for. Hence, it is important for you to ask for as few permissions as possible and to justify those you request, so users do not elect to skip installing your application because you ask for too many unnecessary permissions. This prompt is not available in the current emulator, however.
If you do not have the desired permission and try to do something that needs it, you may get a SecurityException
informing you of the missing permission, but this is not a guarantee. Failures may come in other forms, depending on if something else is catching and trying to handle that exception. 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.
The other side of the coin is to secure your own application. If your application is merely activities and intent receivers, 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 messages, and so on. 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:
<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 which circumstances they are required. You can enforce permissions in your code, but the easier option is to indicate in the manifest where permissions are required.
Activities, services, and intent receivers can 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:
sendBroadcast()
unless the sender has the permission.Content providers offer two distinct attributes: readPermission
and writePermission
.
<provider
android:name=".SekritProvider"
android:authorities="vnd.tla.sekrits.SekritProvider"
android:readPermission="vnd.tla.sekrits.SEE_SEKRITS"
android:writePermission="vnd.tla.sekrits.MOD_SEKRITS" />
In this case, readPermission
controls access to querying the content provider, and writePermission
controls access to insert, update, or delete data in the content provider.
In your code, you have two additional ways to enforce permissions:
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 get the effect of readPermission
and writePermission
in code by checking those methods for the permissions you need from Java.sendBroadcast()
. This means that eligible receivers must hold that permission; those without the permission are ineligible to receive it. For example, the Android subsystem presumably includes the RECEIVE_SMS
permission when it broadcasts that an SMS message has arrived. This will restrict the receivers of that intent to be only those authorized to receive SMS messages.There is no automatic discovery of permissions at compile time; all permission failures occur at runtime. Hence, it is important that you document the permissions required for your public APIs, including content providers, services, and activities intended for launching from other activities. Otherwise, the programmers attempting to interface with your application will need 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 phone and elect to not install or use your application.