Android MからのPermissionについて調べてみた

IMG_0785

2015年5月末に開催された、Google IOの発表の一つに新しいOSAndroid Mがありました。様々な機能の追加や発展がありましたが、その一つにアプリの機能毎にパーミッションを設定できるという物があります。

今回はコベリンの20%ルールを活用して、この機能の振る舞いを試してみました。

この記事はプレビュー版のAndroid Mを利用しています。今後のアップデートで変更がある可能性がありますので、ご注意ください。

使い方

AndroidManifest.xmlに要求をしたいuses-permissionを記入します。この辺りは変わっていません。

    < uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    < uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

ActivityなどからPermissionが必要なAPIを呼ぶ前にユーザに許可要求を行います。そして要求の結果を受け取ります。

public static final int REQUEST_LOCATION = 1; //requesPermissions、onRequestPermissionsResultで利用するリクエストコード

void updateLocation() {
    if (heckSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        locationManager.requestLocationUpdates(); //android.permission.ACCESS_FINE_LOCATION が必要なAPI
    } else {
        // Android Mから追加されたメソッド。第1引数のPermissionの利用許可を求める。第2引数はonRequestPermissionsResultで使うリクエストコード。
        requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION);
    }
}

@Override
// Android Mから追加されたメソッド。リクエストコード、許可要求のあったPermissionと許可の結果が与えられる。
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if (requestCode == REQUEST_LOCATION) {
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            updateLocation();
        } else {
            Toast.makeText(MainActivity.this, "permission does not granted", Toast.LENGTH_SHORT).show();
        }
    } else {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

以上の実装で、ユーザに対し機能利用許可を求めるダイアログが表示されます。

ss1

また、実行時にユーザに許可を求めることのできるPermissionは全てのではなく、一部の様です。詳細は http://developer.android.com/preview/features/runtime-permissions.html#codingTable 1 Permissions and permission groups.を参照してください。

振る舞いの調査

とりあえずの実装ができたので、どう言った点に注意する必要があるのか、その振る舞いを調査してみましょう。

拒否する

1度拒否をすると2回目以降は「今後は確認しない」が表示されるようです。ユーザとしてはこういうのがあると嬉しいですね。

ss2

許可してから拒否する、あるいはその逆

一度許可してから拒否をすることもできます。設定->アプリ->[許可を求めているアプリ]->許可を表示することで、機能毎に許可・拒否の設定が可能です。この場合、どうやらアプリの再起動が行われるようです。

ss3

詳細は完全には追いかけていませんが、Activityの場合は

許可設定変更->Activityの破棄(onDestroyは呼ばれない)

Serviceの場合、onStartCommandSTART_STICKYをreturnしていると、

許可設定変更->Serviceの破棄(onDestroyは呼ばれない)->onStartCommandとなります。

したがって、START_STICKYをreturnするServiceの中で許可が必要な機能を利用する場合、ちゃんとPermissionの確認しなければなりませんね。

また、onDestroyが呼ばれない系のアプリケーションの終了なので終了処理などはちゃんとやっておいた方がいいでしょう。

実装上気をつけるべき事柄

develoerp.android.com/previewに情報は書いてありますが、これからアプリケーションの実装を行う上で気をつけないと行ける必要がると思った点を幾つか。

  • Permissionが必要なAPIを利用する際は、必ず確認を行う。
    • Android Studioが確認をせずにAPIを呼び出しているとエラーを出してくれました。(消せますが)
    • いい感じにインターフェースとか作ってラップするのもありかもしれません?
  • 事前にユーザに説明をする
    • Permissionを求めるダイアログは「どの機能を利用するか」しか表示されません。そのため、「何故利用するのか」を表示、説明した方が良いでしょう。
    • 以前までのPermissionの仕組みでは、ベンダーから利用目的の説明をする余地はほぼ無かったので、この変更は良いと思います。
  • Permissionの許可はダイアログとなる点に気をつける
    • UIによってはダイアログが似つかわしくない場面があると思うので、気をつけてください。
    • ちなみに表示はダイアログですが実態はActivityの様ですね。

ちゃんとした文章はBest Practicesにあるのでそちらを見てください。

まとめ

Android Mに搭載予定の新しいPermissionの仕組みを試してみました。機能毎に許可を求める仕組みのため、ユーザとしては自分の知らない振る舞いをアプリがする可能性が減るため、より便利になると言えると思います。

その分実装者としては気を使う必要がある点が増えたとも言えます。APIと振る舞いを把握して、ユーザに良い体験を与えたいですね。

以上です。