Understanding and Using Custom Permissions

Android allows you to define custom permissions with your application. For example, if you wanted to prevent certain users from starting one of the activities in your application, you could do that by defining a custom permission. To use custom permissions, you first declare them in your AndroidManifest.xml file. Once you've defined a permission, you can then refer to it as part of your component definition. We'll show you how this works.

Let's create an application containing an activity that not everyone is allowed to start. Instead, to start the activity, a user must have a specific permission. Once you have the application with a privileged activity, you can then write a client that knows how to call the activity.

First create the project with the custom permission and activity. Open the Eclipse IDE and select New > New Project > Android Project. This will open the "New Android Project" dialog box. Enter CustomPermission as the project name, select the "Create new project in workspace" radio button, and mark the "Use default location" check box. Enter com.cust.perm as the package name, CustPermMainActivity as the activity name, and Custom Permission as the application name. Click the Finish button to create the project. The generated project will have the activity you just created, which will serve as the default (main) activity. Let's also create a so-called privileged activity—an activity that requires a special permission. In the Eclipse IDE, go to the com.cust.perm package, create a class named PrivActivity, and copy the code shown in Listing 7-4.

Listing 7-4. The PrivActivity Class package com.cust.perm;

import android.app.Activity; import android.os.Bundle; import android.view.ViewGroup.LayoutParams; import android.widget.LinearLayout; import android.widget.TextView;

public class PrivActivity extends Activity {

^Override public void onCreate(Bundle savedlnstanceState) { super.onCreate(savedlnstanceState); LinearLayout view = new LinearLayout(this);

view.setLayoutParams(new LayoutParams(

LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); view.setOrientation(LinearLayout.HORIZONTAL);

CHAPTER 7 ■ EXPLORING SECURITY AND LOCATION-BASED SERVICES

TextView nameLbl = new TextView(this);

nameLbl.setText("Hello from PrivActivity");

view.addView(nameLbl);

setContentView(view);

As you can see, PrivActivity does not do anything miraculous. This is obviously intentional because we want to protect this activity with a permission and then call it from a client. If the client succeeds, then you'll see the text "Hello from PrivActivity" on the screen. Now that you have an activity you want to protect, you can create the permission for it.

To create a custom permission, you have to define it in the AndroidManifest.xml file. The easiest way to do this is to use the manifest editor. Double-click the AndroidManifest.xml file and then select the Permissions tab. In the Permissions window, click the Add button, choose Permission, and then click the OK button. The manifest editor will create an empty new permission for you. Populate the new permission by setting its attributes as shown in Figure 7-3.

Figure 7-3. Declaring a custom permission using the manifest editor

As shown in Figure 7-3, a permission has a name, a label, an icon, a permission group, a description, and a protection level. Table 7-3 defines these properties.

Table 7-3. Attributes of a Permission

Attribute

Required? Description android:name

Yes android:protectionLevel Yes android:permissionGroup No android:label No android:description No android:icon No

Name of the permission. You should generally follow the Android naming scheme (*.permission.*).

Defines the "potential for risk" associated with the permission. Must be one of the following values:

normal dangerous signature signatureOrSystem

Depending on the protection level, the system might take a different action when determining whether to grant the permission or not. normal signals that the permission is low-risk and will not harm the system, the user, or other applications. dangerous signals that the permission is high-risk, and that the system will likely require input from the user before granting this permission. signature tells Android that the permission should be granted only to applications that have been signed with the same digital signature as the application that declared the permission. signatureOrSystem tells Android to grant the permission to applications with the same signature or to the Android package classes. This protection level is not to be used at this time.

You can place permissions into a group, but for custom permissions you should avoid setting this property. If you really want to set this property, use this instead: android.permission-group.SYSTEM_TOOLS.

Although it's not required, use this property to provide a short description of the permission.

Although it's not required, you should use this property to provide a more useful description of what the permission is for and what it protects.

Permissions can be associated with an icon out of your resources (such as @drawable/myicon).

After you add the permission in Figure 7-3, the manifest editor will modify your manifest file by adding a permission entry, as shown in Listing 7-5.

Listing 7-5. A Custom Permission Definition <permission android:protectionLevel="normal" android:name="syh.permission.STARTMYACTIVITY " android:label="Start My Activity"

android:description="@string/startMyActivityDesc"></permission>

Now you have a custom permission. Next, you want to tell the system that the PrivActivity activity should be launched only by applications that have the syh.permission.STARTMYACTIVITY permission. You can set a required permission on an activity by adding the android:permission attribute to the activity definition in the AndroidManifest.xml file. For you to be able to launch the activity, you'll also need an intent-filter to the activity. Update your AndroidManifest.xml file with the content from Listing 7-6.

Listing 7-6. The AndroidManifest.xml File for the Custom-Permission Project <?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.cust.perm" android:versionCode="1" android:versionName="1.0.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".CustPermMainActivity" android:label="@string/app_name"> <intent-filter>

<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="PrivActivity" android:permission="syh.permission.STARTMYACTIVITY"> <intent-filter>

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

<permission android:protectionLevel="normal" android:label="Start My Activity" android:description="@string/startMyActivityDesc" android:name="syh.permission.STARTMYACTIVITY"></permission>

</manifest>

Now run the project in the emulator. Although the main activity does not do anything, you just want the application installed on the emulator before you write a client for the privileged activity. Also, Listing 7-6 assumes that you have added a string constant named startMyActivityDesc to your string resources. To ensure compilation of Listing 7-6, add the following string resource to the res/values/strings.xml file:

<string name="startMyActivityDesc">Allows starting my activity</string>

Let's write a client for the activity. In the Eclipse IDE, click New > Project > Android Project. Enter ClientOfCustomPermission as the project name, select the "Create new project in workspace" radio button, and mark the "Use default location" check box. Set the package name to com.client.cust.perm, the activity name to ClientCustPermMainActivity, and the application name to Client Of Custom Permission. Click the Finish button to create the project.

Next, you want to write an activity that displays a button you can click to call the privileged activity. Copy the layout shown in Listing 7-7 to the main.xml file in the project you just created.

Listing 7-7. Main.xml File for the Client Project <?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent"

android:layout_height="fill_parent" >

<Button android:id="@+id/btn" android:text="Launch PrivActivity" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>

As you can see, the XML layout file defines a single button whose text reads "Launch PrivActivity." Now let's write an activity that will handle the button-click event and launch the privileged activity. Copy the code from Listing 7-8 to your ClientCustPermMainActivity class.

Listing 7-8. The Modified ClientCustPermMainActivity Activity package com.client.cust.perm;

import android.app.Activity;

import android.content.Intent;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

public class ClientCustPermMainActivity extends Activity { ^Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedlnstanceState); setContentView(R.layout.main);

Button btn = (Button)findViewByld(R.id.btn); btn.setOnClickListener(new OnClickListener(){

^Override public void onClick(View arg0) {

Intent intent = new Intent();

intent.setQassName("com.cust.perm","com.cust.perm.PrivActivity"); startActivity(intent);

As shown in Listing 7-8, you obtain a reference to the button defined in the main.xml file and then wire up the on-click listener. When the button is invoked, you create a new intent, and then set the class name of the activity you want to launch. In this case, you want to launch the com.cust.perm.PrivActivity in the com.cust.perm package.

The only thing missing at this point is to add a uses-permission entry into the manifest file to tell the Android runtime that you need the syh.permission.STARTMYACTIVITY to run. Replace your client project's manifest file with that shown in Listing 7-9.

Listing 7-9. The Client Manifest File <?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.client.cust.perm" android:versionCode="1" android:versionName="1.0.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".QientCustPermMainActivity" 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>

<uses-permission android:name="syh.permission.STARTMYACTIVITY"></uses-permission> </manifest>

As shown in Listing 7-9, we added a uses-permission entry to request the custom permission required to start the PrivActivity we implemented in the custom-permission project.

With that, you should be able to deploy the client project to the emulator and then select the "Launch PrivActivity" button. When the button is invoked, you should see the text "Hello from PrivActivity."

After you successfully call the privileged activity, remove the uses-permission entry from your client project's manifest file and redeploy the project to the emulator. Once it's deployed, confirm that you get a permission denial when you invoke the button to launch the privileged activity. Note that LogCat will display a permission-denial exception.

Now you know how custom permissions work in Android. Obviously, custom permissions are not limited to activities. In fact, you can apply both predefined and custom permissions to Android's other types of components as well.

0 0

Post a comment