How to use custom permissions in Android?
Solution 1:
I created a test code you can use it and test your permissions. There are two applications PermissionTestClient which declares permission and protects its activity with this permission. Here is its manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.testpackage.permissiontestclient"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="10" />
<permission android:name="com.testpackage.mypermission" android:label="my_permission" android:protectionLevel="dangerous"></permission>
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:permission="com.testpackage.mypermission"
android:name=".PermissionTestClientActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter >
<action android:name="com.testpackage.permissiontestclient.MyAction" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
There is nothing special in Activity file so I will not show it here.
PermissionTestServer application calls activity from PermissionTestClient. Here is its manifest file:
<?xml version="1.0" encoding="utf-8"?>
<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="com.testpackage.mypermission"/>
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".PermissionTestServerActivity"
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>
And Activity:
package com.testpackage.permissiontestserver;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class PermissionTestServerActivity extends Activity {
private static final String TAG = "PermissionTestServerActivity";
/** Called when the activity is first created. */
Button btnTest;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnTest = (Button) findViewById(R.id.btnTest);
btnTest.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "Button pressed!");
Intent in = new Intent();
in.setAction("com.testpackage.permissiontestclient.MyAction");
in.addCategory("android.intent.category.DEFAULT");
startActivity(in);
}
});
}
}
To test it just remove uses-permission from Server application. You'll get security violation error.
Solution 2:
You need to create a permission in your base app's manifest by declaring it exclusively. For example:
<permission android:name="your.namespace.permission.TEST"
android:protectionLevel="normal" android:label="This is my custom permission" />
And later make use of it in your desired app as:
<uses-permission android:name="your.namespace.permission.TEST" />
Note: It is vital to maintain the order in which you install your applications with custom permissions. i.e You must need to install that app first which declares the permission and later install the one which makes use of it. Any disruption in this order may break the usage of custom. permissions.
Solution 3:
As mentioned in the answers, you should also take into account the order you install the apps.
this is important because:
if the App that requests the permission (App B) is installed before the App that defines the permission (App A), then there will be no such defined permission in the specific device so the OS won't ask for the permission at all.
later on, when you install the App A and try to run App B, the latter will fail to access the secure component.
One workaround would be to define the same custom permission in both Apps, A and B in order to make sure that the permission exists in the device regardless of which App is installed first, so when the App A is installed, the permission will be already granted to App B.
In that case though, you should make sure that the protection level is the same in both declarations because this can lead to security risk.
(note here that from android 5.0 and on you cannot define the same permission in more than one App, except when those Apps are signed with the same signature key).
Solution 4:
The accepted answer shows the correct flow to create custom permissions. I have some note to decide which permission and permission name after my testing
android:protectionLevel="normal" // don't need user confirmation to grant, similar to some low-risk permission like android.permission.INTERNET
android:protectionLevel="dangerous" // need user confirmation to grant // similar to some high-risk permission like android.permission.CAMERA
android:protectionLevel="signature" // both app need to sign with the same signature
On Android < 6, user grant dangerous
permission when install or update app. Android do it for us, we don't need to code
Android >= 6, user grant dangerous
permission when using app (Runtime Permission). We need to code to request runtime permission
Android dangerous permission name need to has 2 parts (test on Android 10, Pixel 4XL), label
, description
, icon
is not required to make permission work
<permission
android:name="my.MyCustomPermission" // work well
android:name="MyCustomPermission" // not work, the runtime permission dialog won't show
android:label="" // don't required
android:description="" // don't required
android:icon="" // don't required