home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

技術/Android/PermissionExamples (v1)

技術/Android/PermissionExamples (v1)

技術 / Android / PermissionExamples (v1)
id: 997 所有者: msakamoto-sf    作成日: 2011-07-10 18:19:33
カテゴリ: Android 

AndroidManifest.xmlでの"<permission>"と"android:permission"属性の使用例+メモ。


実験

  • "PermissionTest1" : Activity, BroadcastReceiver, Serviceを用意しているアプリ。全てのコンポーネントでIntentFilterを設定せず、パッケージ名とクラス名で直接呼び出すものとする。それぞれ次の5パターンを用意。
    • android:exported=false : 外部非公開。IntentFilterが無いので、特に指定しない場合のデフォルト設定。
    • android:exported=true : 外部公開。
    • android:permission="test.perms1.TESTPERM_NORMAL" : "normal"レベルのpermissionを要求(+外部公開)。
    • android:permission="test.perms1.TESTPERM_DANGEROUS" : "dangerous"レベルのpermissionを要求(+外部公開)。
    • android:permission="test.perms1.TESTPERM_SIGNATURE" : "signature"レベルのpermissionを要求(+外部公開)。
  • "PermissionTest2" : PermissionTest1の各コンポーネントを呼び出すアプリ。AndroidManifest.xmlで必要な"<uses-permission>"を定義済み。PermissionTest1と同じ証明書で署名する。
  • "PermissionTest3" : PermissionTest2と内容は同じだが、PermissionTest1,2と異なる証明書で署名する。

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

PermissionTest1のAndroidManifest.xml

<?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>

PermissionTest2で使っている呼び出しコード

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>

結果

予想通り

  1. android:exported="false"の非公開は呼べない。
  2. PermissionTest3でのみ、"signature"レベルのpermissionが署名違いで呼べない。

という結果になった。

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

参考資料



プレーンテキスト形式でダウンロード
表示中のバージョン : 1
現在のバージョン : 6
更新者: msakamoto-sf
更新日: 2011-11-25 19:21:36
md5:f74c9c2b3d30f192d4b8db94d2ec3ca1
sha1:7ee3af0fefd8dc459e22b57af9b2bff1e0057d41
コメント
コメントを投稿するにはログインして下さい。