Android M (6.0)でのActivity#shouldShowRequestPermissionRationaleの使いどころを探る

注意:本記事については、弊社でもどうするのがベストプラクティスなのか掴みかねております。その点を留意してお読みください。

Andorid M (6.0)のPreview 2から、ActivityクラスにshouldShowRequestPermissionRationaleというメソッドが追加されています。rationaleとは「理論的根拠」とかそんな感じの意味があるので、このメソッドは「パーミッション要求の根拠を表示すべきかどうか」を判定するためのものであることが名前からわかります。

実際、Previewのドキュメントでもそういう風に使うように記載されています。

しかし、このメソッドの挙動が少し不思議です。

  1. まだ一度も要求していないパーミッションを渡した場合、falseが返る
  2. 要求したパーミッションが拒絶されたことがあり、かつ今後表示しないチェックがつけられていない場合、trueが返る
  3. 要求したパーミッションが、今後表示しないというチェックを入れて拒絶された場合、falseが返る

上記のような挙動になります。

ここで不思議なのは1番目です。初回のパーミッション要求の前にも、そのパーミッションをどういう根拠で求めるのかはユーザに提示した方が良いのではないかと思われますが、このAPIに従った場合、表示しないというパスに流れます。

また、PreviewのAPI Overviewに示されたコードも不思議です。

if (checkSelfPermission(Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {

    // Should we show an explanation?
    if (shouldShowRequestPermissionRationale(
            Manifest.permission.READ_CONTACTS)) {
        // Explain to the user why we need to read the contacts
    }

    requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
            MY_PERMISSIONS_REQUEST_READ_CONTACTS);

    // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
    // app-defined int constant

    return;
}

このコードを参考にして実装すると、shouldShowRequestPermissionRationale()の結果がtrueであったときに説明を表示します。たとえばダイアログで表示するなどが考えられますが、その場合はダイアログ表示している間にrequestPermissions()がすでに呼び出され、外部アプリ(PackageInstallerアプリ)による権限確認ダイアログの表示に遷移してしまうことでしょう。

以上から、このサンプルコードをベースに書くのはベストプラクティスでは無いだろうと考えています。

ということで、現時点ではどうするのが良いのかについてはまだ模索中です。二つの問題点とうまく折り合いをつけたベストプラクティスがGoogleから提示されることを期待しています。

Android M (6.0)の新セキュリティモデルの注意点

TechBooster様の「Androidビルディングデザイン」に、弊社代表中西がAndroid Mの新しいセキュリティモデル(パーミッションモデル)の記事を寄稿しました。2015年8月25日現在、紙の書籍は完売しておりますが電子書籍版はまだ頒布されています。

電子版では、Android M Developer Preview 3、SDKバージョン23、Support Libraryバージョン23についても反映した内容に更新されていますが、その中では触れていない気をつけないといけない項目について、ここに記載します。

targetSdkVersionを23以上に上げたアプリは22以下に戻せない

Android Studioでデバッグ実行で試すとわかるのですが、targetSdkVersionを23にしたアプリをインストールし、それを22以下に変更して再度インストールしようとすると、以下の様な警告が表示されます。

Failure [INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE]

書いてあるとおり、パーミッションモデルのダウングレードを求めるようなアプリのインストールが許可されていません。この時、Android Studioは以下のようなダイアログも表示します。

スクリーンショット 2015-08-25 10.36.08

ここに書いてあるのは、今インストールされているアプリをアンインストールして、それからインストールするかと聞いてきています。つまり、インストール済みのアプリの保存しているデータや設定などを維持して、targetSdkVersionを22以下に落としたアプリのインストール(アップデート)を行うことはできません。

これ、おそらくはGoogle Play Storeでも対策がなされるのではないでしょうか。

一度targetSdkVersionを23以上に上げて新しいセキュリティモデルの対象となったアプリは、targetSdkVersionを上げたことによって発生したバグがあっても、22以下に戻したアプリをアップロードすることはできなくするのではないかと。

既存アプリを運用されている場合、targetSdkVersionを23に変更するのは慎重に行うようにしましょう。

targetSdkVersion 22以下のアプリを23にした場合、パーミッションが許可状態になる

これはユーザにとっての罠ですが、Android M端末にtargetSdkVersionが22以下のアプリをインストールし、それがバージョンアップでtargetSdkVersionが23になったとしても、パーミッションが許可状態になります(Context#checkSelfPermissionがtrueを返します)。

新規にtargetSdkVersionが23のアプリをインストールした場合、最初はContext#checkSelfPermissionはfalseとなりますので、そこからActivity#requestPermissionsによって権限を取得していくという流れになります。

しかし、前述の場合は、targetSdkVersionが22のアプリをインストールした時点で、権限利用を許可したという状態が端末に記録され、それはtargetSdkVersionを23以上に上げた場合にも維持されます。

この挙動は、iOSなどで新しいOSバージョンで権限チェックが強化された場合の挙動とは異なります。iOSでは、たとえばマイク利用にユーザによる権限確認が必要となった場合、アプリの新規インストールとアップデートのいずれであってもダイアログで確認するという挙動になります。

この挙動のまま正式版となるかはわかりませんが、ユーザは気をつけておくとよいでしょう。