私用の個人端末がまだLolipop(EXPERIA Z3)なので、あぐらをかいていたRuntime Permissionsの対応ですが、Nも出たことで、そろそろ本腰を入れないとということで実装してみました。
その中でつまづいたところとその対処を残しておきたいと思います。
基本的なところについては以下が参考になると思います。
booleanのメソッドなのに3つの状態がある
shouldShowRequestPermissionRationale()
パーミッションを許可するかの確認ダイアログを表示するかどうかを確認するためのメソッドです。
(この時点で若干ややこしい)
自分は、ダイアログを表示しないにチェックを入れたかを知るときに使っていました。
こちら、チェックの有無で値を返してくれたらいいのですが、なぜかダイアログを1度も表示していない場合でもfalseが返ってくるので、チェックをしたからfalseなのか1度も表示していないからfalseなのかがわかりません。
しかたがないので、各パーミッションごとにpreferenceでbooleanの値を確保し、1度でも表示したかの確認をするようにしています。
現在地は端末の設定もある
現在地のパーミッションの場合は、端末でも制御ができるので注意が必要です。
自分は、端末→アプリの順でONになっているか確認し、なっていなければその都度ユーザーに設定を促すようにしました。なお、先に端末から確認したのは、ユーザーがわざとOFFにしている可能性があり、手間を少なくするためです。
また、以下のように端末、パーミッション、その両方の設定を確認して、適宜使い分けていました。
// 端末
boolean isDeviceLocation() {
LocationManager locationManager =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
// パーミッション
boolean isPermissionLocation() {
// M未満は関係なし
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION};
ActivityCompat.requestPermissions(this, permissions, PERMISSION_LOCATION_REQUEST_CODE);
return false;
}
return true;
}
// 両方
boolean isLocation() {
return isDeviceLocation() && isPermissionLocation();
}
各画面で確認しなければならない
当たり前なのですが、その許可が必要な画面すべてで、パーミッションの有無、確認ダイアログ、そして、許可/拒否された場合の処理を書かなければなりません。
こちらについては特に対処できませんでした。大元となるメソッドなどはBaseActivityといった継承元をつくってそこに書いたりしましたが、いまいちな感じでした。どんどん肥大化していきますね。
テストの分岐が増える
現在地のパーミッションだけになるかもしれませんが、M未満は今まで通りでM以上は今回のランタイムパーミッションが適用されるため、
・M未満で端末の現在地の設定による分岐
・M以上で端末の現在地の設定をOFFにしていて、パーミッションの設定による分岐
・M以上で端末の現在地の設定をONにしていて、パーミッションの設定による分岐
と、一気に増えた感が。こちらも特に対処できずに、頑張るしかないと言ったところでしょうか。
おわりに
Runtime Permissionsについての詳しい説明は、結構落ちているのですが、こういった各個人の対処法みたいなのってなかなか無いように思えます。(自分もあまり対処法は書いていませんが)
見逃してるだけで、ベストプラクティスってことでどっかに載ってたりするのかしら?