AndroidManifest.xmlでの"<permission>"と"android:permission"属性の使用例+メモ。
Activityは表示されたか否か、BroadcastReceiver/ServiceはLogを出力するようにしてそれで判定する。PermissionTest2,3でもstartActivity()/sendBroadcast()/startService()それぞれtry-catchで囲み、ThrowableをLogに出力するようにしている。
予想としては、外部非公開は全て呼べない、それ以外はPermissionTest3だけ、"signature"レベルのpermissionが署名違いで呼べない結果になると思われる。
https://www.glamenv-septzen.net/medias/android/PermissionTestEx01.zip
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="test.perms1" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="3" /> <permission android:protectionLevel="normal" android:name="test.perms1.TESTPERM_NORMAL" android:label="TestPermNormal" android:description="@string/perm_desc_normal"> </permission> <permission android:protectionLevel="dangerous" android:name="test.perms1.TESTPERM_DANGEROUS" android:label="TestPermDangerous" android:description="@string/perm_desc_dangerous"> </permission> <permission android:protectionLevel="signature" android:name="test.perms1.TESTPERM_SIGNATURE" android:label="TestPermSignature" android:description="@string/perm_desc_signature"> </permission> <uses-permission android:name="test.perms1.TESTPERM_NORMAL"></uses-permission> <uses-permission android:name="test.perms1.TESTPERM_DANGEROUS"></uses-permission> <uses-permission android:name="test.perms1.TESTPERM_SIGNATURE"></uses-permission> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".Main" 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=".activities.NoPermHidden"></activity> <activity android:name=".activities.NoPermPublic" android:exported="true"></activity> <activity android:name=".activities.NormalPerm" android:exported="true" android:permission="test.perms1.TESTPERM_NORMAL"></activity> <activity android:name=".activities.SignaturePerm" android:exported="true" android:permission="test.perms1.TESTPERM_SIGNATURE"></activity> <activity android:name=".activities.DangerousPerm" android:exported="true" android:permission="test.perms1.TESTPERM_DANGEROUS" ></activity> <receiver android:name=".receivers.NoPermHidden"></receiver> <receiver android:name=".receivers.NoPermPublic" android:exported="true"></receiver> <receiver android:name=".receivers.NormalPerm" android:permission="test.perms1.TESTPERM_NORMAL" android:exported="true"></receiver> <receiver android:name=".receivers.DangerousPerm" android:permission="test.perms1.TESTPERM_DANGEROUS" android:exported="true"></receiver> <receiver android:name=".receivers.SignaturePerm" android:permission="test.perms1.TESTPERM_SIGNATURE" android:exported="true"></receiver> <service android:name=".services.NoPermHidden"></service> <service android:exported="true" android:name=".services.NoPermPublic"></service> <service android:exported="true" android:name=".services.NormalPerm" android:permission="test.perms1.TESTPERM_NORMAL"></service> <service android:name=".services.DangerousPerm" android:permission="test.perms1.TESTPERM_DANGEROUS" android:exported="true"></service> <service android:name=".services.SignaturePerm" android:permission="test.perms1.TESTPERM_SIGNATURE" android:exported="true"></service> </application> </manifest>
PermissionTest3も同様。
test.perms2.Main.java:
package test.perms2; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Spinner; public class Main extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ArrayAdapter<CharSequence> classnameArrayAdapter = ArrayAdapter.createFromResource( this, R.array.classname_array, android.R.layout.simple_spinner_item); Spinner spinner = (Spinner) findViewById(R.id.main_spn_activities); classnameArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(classnameArrayAdapter); spinner.setOnItemSelectedListener(new ActivitiesSelectedListener()); spinner = (Spinner) findViewById(R.id.main_spn_receivers); classnameArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(classnameArrayAdapter); spinner.setOnItemSelectedListener(new ReceiversSelectedListener()); spinner = (Spinner) findViewById(R.id.main_spn_services); classnameArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(classnameArrayAdapter); spinner.setOnItemSelectedListener(new ServicesSelectedListener()); } public class ActivitiesSelectedListener implements OnItemSelectedListener { @Override public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { if (0 == pos) { return; } String classname = "test.perms1.activities." + parent.getItemAtPosition(pos).toString(); Intent i = new Intent(); i.setClassName("test.perms1", classname); view.getContext().startActivity(i); } @Override public void onNothingSelected(AdapterView<?> parent) { } } public class ReceiversSelectedListener implements OnItemSelectedListener { @Override public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { if (0 == pos) { return; } String classname = "test.perms1.receivers." + parent.getItemAtPosition(pos).toString(); Intent i = new Intent(); i.setClassName("test.perms1", classname); i.setData(Uri.parse("test://" + classname)); view.getContext().sendBroadcast(i); } @Override public void onNothingSelected(AdapterView<?> parent) { } } public class ServicesSelectedListener implements OnItemSelectedListener { @Override public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { if (0 == pos) { return; } String classname = "test.perms1.services." + parent.getItemAtPosition(pos).toString(); Intent i = new Intent(); i.setClassName("test.perms1", classname); i.setData(Uri.parse("test://" + classname)); view.getContext().startService(i); } @Override public void onNothingSelected(AdapterView<?> parent) { } } }
res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, Main!</string> <string name="app_name">PermissionTest2</string> <string name="spinner_prompt_for_activities">Choose Activity</string> <string name="spinner_prompt_for_receivers">Choose Receiver</string> <string name="spinner_prompt_for_services">Choose Service</string> <string-array name="classname_array"> <item>-</item> <item>NoPermHidden</item> <item>NoPermPublic</item> <item>NormalPerm</item> <item>DangerousPerm</item> <item>SignaturePerm</item> </string-array> </resources>
予想通り
という結果になった。
Activity:
PermissionTest2 | PermissionTest3 | |
android:exported=false | SecurityException: Permission Denial | 同左 |
android:exported=true | o | o |
"normal" level | o | o |
"dangerous" level | o | o |
"signature" level | o | SecurityException: Permission Denial |
BroadcastReceiver:
PermissionTest2 | PermissionTest3 | |
android:exported=false | (Log-WARN): Permission Denial | 同左 |
android:exported=true | o | o |
"normal" level | o | o |
"dangerous" level | o | o |
"signature" level | o | (Log-WARN): Permission Denial |
Service:
PermissionTest2 | PermissionTest3 | |
android:exported=false | SecurityException: Not allowed to start service Intent | 同左 |
android:exported=true | o | o |
"normal" level | o | o |
"dangerous" level | o | o |
"signature" level | o | SecurityException: Not allowed to start service Intent |