45
47

More than 5 years have passed since last update.

【Android M】アプリ内からPermission設定画面に遷移する(失敗編)

Last updated at Posted at 2015-09-14

Android Mの厄介な機能としてRuntime Permissionsが入りますよね。

詳しくは公式のドキュメントを見れば、だいたいどんな機能なのかわかります。

Permissions

開発者的には、これに対応させるのってすげー大変なのですよ。。。

Permissionの許可・非許可ってアプリの設定画面からユーザが自由に操作できるんですよね。

例えば、標準のカメラアプリのPermission設定画面がこれ。

Screenshot_20150914-102734.png

んで今回、このPermission設定画面にアプリ内からIntentを作って遷移することができるのか?という検証をしてみた。

Permission設定画面にアプリ内からIntentを作って遷移することができるのか?

Permission設定画面に遷移するために、調べて見たことをまとめてみた。

  • 遷移するIntentのActionは、android.intent.action.MANAGE_APP_PERMISSIONS
  • 起動するActivityは、com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.ManagePermissionsActivity
  • ManagePermissionsActivityにAppPermissionsFragmentというFragmentがAttachされている
  • IntentのデータにKeyがandroid.intent.extra.PACKAGE_NAMEで、値にアプリのパッケージ名が入ってるっぽい

adb shell amでPermission設定画面を開けるか試してみた

以下のadb shell amでPermission設定画面を開けるか試してみた。

adb shell am start -a android.intent.action.MANAGE_APP_PERMISSIONS -e android.intent.extra.PACKAGE_NAME <Package Name>

e.g.)
adb shell am start -a android.intent.action.MANAGE_APP_PERMISSIONS -e android.intent.extra.PACKAGE_NAME com.kouzoh.mercari

結果(Permission設定画面 開いた)

android.intent.extra.PACKAGE_NAMEに指定したパッケージ名のアプリのPermission設定画面が開いた。

うん、開いた!

Screenshot_20150914-184455.png

どうやらadb shell amからなら開けるっぽい。

では、お次は目的のアプリ内から開けるかどうか。

アプリ内からIntentでPermission設定画面に遷移することができるのか試してみた

adb shell amの結果から、以下のようなコードでアプリ内からPermission設定画面に遷移できるのではないかと考えた。

Intent i = new Intent();
i.setAction("android.intent.action.MANAGE_APP_PERMISSIONS");
i.putExtra("android.intent.extra.PACKAGE_NAME", getPackageName());
startActivity(i);

結果 (SecurityExceptionが起きて遷移できない)

startActivityを実行したところ、SecurityExceptionが起きてPermission設定画面に遷移できなかった

Process: com.mercariapp.mercari, PID: 23142
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mercariapp.mercari/com.kouzoh.mercari.activity.TestActivity}: java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.MANAGE_APP_PERMISSIONS cmp=com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.ManagePermissionsActivity (has extras) } from ProcessRecord{1573c3 23142:com.mercariapp.mercari/u0a102} (pid=23142, uid=10102) requires android.permission.GRANT_RUNTIME_PERMISSIONS
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
    at android.app.ActivityThread.-wrap11(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5417)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.MANAGE_APP_PERMISSIONS cmp=com.google.android.packageinstaller/com.android.packageinstaller.permission.ui.ManagePermissionsActivity (has extras) } from ProcessRecord{1573c3 23142:com.mercariapp.mercari/u0a102} (pid=23142, uid=10102) requires android.permission.GRANT_RUNTIME_PERMISSIONS
    at android.os.Parcel.readException(Parcel.java:1599)
    at android.os.Parcel.readException(Parcel.java:1552)
    at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2658)
    at android.app.Instrumentation.execStartActivity(Instrumentation.java:1507)
    at android.app.Activity.startActivityForResult(Activity.java:3917)
    at android.app.Activity.startActivityForResult(Activity.java:3877)
    at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:820)
    at android.app.Activity.startActivity(Activity.java:4200)
    at android.app.Activity.startActivity(Activity.java:4168)
    at com.kouzoh.mercari.activity.TestActivity.onCreate(TestActivity.java:60)
    at android.app.Activity.performCreate(Activity.java:6237)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)

メッセージを見る感じandroid.permission.GRANT_RUNTIME_PERMISSIONSのPermissionが必要そう。

GRANT_RUNTIME_PERMISSIONSを詳しく調べてないのでわからないですが、System Process関連しか使えないPermission系かもしれない。

とりあえずアプリ内から直接特定アプリのPermission設定画面には遷移できなさそう。(今のところは)

結論

  • adb shell amコマンドからなら特定アプリのPermission設定画面に遷移できる
  • アプリ内で作ったIntentで遷移しようとするとSecurityExceptionが起きて遷移できない
    • 遷移するには何かしたら権限が必要みたい
    • android.permission.GRANT_RUNTIME_PERMISSIONS?

おまけ

今回、アプリ内からPermission設定画面に遷移させるために使ったコードのActionとかKeyがベタ書きで書かれているけど、SDK 23のIntentクラスにこれらは定義されています。

Intent i = new Intent();
i.setAction("android.intent.action.MANAGE_APP_PERMISSIONS");
i.putExtra("android.intent.extra.PACKAGE_NAME", getPackageName());
startActivity(i);

こんな感じで定義されている。けど、hideなので直接使えないんだよね。リフレクションしたくないし・・・。

Intent.java(SDK 23から一部抜粋)

/**
 * Intent extra: An app package name.
 * <p>
 * Type: String
 * </p>
 *
 * @hide
 */
@SystemApi
public static final String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";


**
 * Activity action: Launch UI to manage the permissions of an app.
 * <p>
 * Input: {@link #EXTRA_PACKAGE_NAME} specifies the package whose permissions
 * will be managed by the launched UI.
 * </p>
 * <p>
 * Output: Nothing.
 * </p>
 *
 * @see #EXTRA_PACKAGE_NAME
 *
 * @hide
 */
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_MANAGE_APP_PERMISSIONS =
        "android.intent.action.MANAGE_APP_PERMISSIONS";

まとめ

何かいい情報や「こうやれば遷移できた!」って情報あればフィードバックもらえると嬉しいです!

引き続きPermission周りの調査続けてみる。

45
47
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
45
47