Mais conteúdo relacionado Semelhante a パーミッションモデルの過渡期への対応 (20) パーミッションモデルの過渡期への対応11. 複数のパーミッションをチェックする場合は、
文字列の配列を受け取り、for文等でチェックするクラスを作ってもよい
Step.1 チェックの処理
public void showContacts(View v){
if (checkSelfPermission(Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
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);
}else{
showContactsDetails();//すでに許可されていた場合の処理
}
}
パーミッションのチェックは次のAPIを用いる
context#checkSelfPermission(String permission_name)
許可:PERMISSION_GRANTED(=0)
不許可:PERMISSION_DENIED(=-1)
12. Step.2 リクエストの処理
パーミッションが許可されていなければ、次のAPIで要求する
Activity#requestPermissions(String[] permissions, int requestCode)
パーミッションを複数指定した場合、グループ数分の要求ダイアログが表示される
requestCodeを設定し、ハンドリング時のケース分けに使う
shouldShowRequestPermissionRationale(String permission)は、
パーミッションが過去にリクエストを拒否していて、
かつ「今後は確認しない」を設定していないか確認できる。
public void showContacts(View v){
if (checkSelfPermission(Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)) {
// パーミッションの必要性を説明するための処理を書く
}
//ポップアップなどで要求に対する説明を書く
requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
}else{
showContactsDetails();//すでに許可されていた場合の処理
}
}
13. Step.3 ハンドリングの処理
次のメソッドでリクエストの結果を受け取る
onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults)
リクエスト時のパーミッション毎に対する結果が配列grantResultsに格納されている
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
showContactsDetails();//リクエストが許可されたときの処理
} else {
if(shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)) {
// パーミッションが許可されなかった場合の処理を書く
}else{
//「今後は確認しない」を設定していると、この部分の処理に飛ぶ
//アプリの詳細設定画面へのインテントを行うボタン表示などを作ると良い
}
}
return;
}
// その他のリクエストコードの時の動作
}
}
リクエストに対して許可されていたら、
PERMISSION_GRANTED(=0)が格納されている
14. いつリクエストしたらよいか
最初にリクエスト(チュートリアル)
絶対必要な機能(これだけでも使える)
カメラアプリでCAMERA権限
カレンダーアプリでCALENDER権限
実行前に再チェックは必要!
実行中にリクエスト
アプリの出来ることを広げる機能
メッセージアプリで現在地投稿
→現在地ボタン押下時にLOCATION権限
関係ないところで要求すると不信感を持たれる
それとわかるようにデザインする
そもそもリクエストしないという選択肢
カメラで撮った画像が必要なら、カメラを呼び出して撮影する
message
15. 説明はどこまでやるか
最初の説明(チュートリアル)
アプリから権限が必要と連想しにくいもの
実行中にリクエストすることの予告
SNSアプリ:メッセージの他に、画像投稿する場合は許可が必要
実行中の説明
リクエストしている権限についての説明。
ここで許可することによる、アプリ全体への影響を説明する。
一度拒否している場合はより詳細に
Activity#shouldShowRequestPermissionRationale
拒否された後の説明
許可しないと機能が使えない旨の説明。
「今後表示しない」のチェックを入れられた場合、アプリの詳細設
定からしか設定できなくなる。誘導ボタン等を設置
16. 対応の効率化
パーミッションの許可が必要なAPI全てに、
ミス無しにこの処理を書くのは大変
ライブラリ(PermissionsDispatcher)の利用
Annotation Processingを使ってハンドリングするクラスを作成
条件分岐を書かなくていい!
各条件で処理を行いたいメソッドにアノテーションを付与すればいい
@RuntimePermissions:Activityやフラグメントに付与
@NeedPermission:パーミッションが必要なAPIを使うメソッドに付与
@OnShowRational:一度拒否されている場合に説明などを行うメソッドに付与
@OnPermissionDenied:拒否された場合の処理を行うメソッドに付与
@OnNeverAskAgain:「今後は表示しない」の場合の処理を行うメソッドに付与
独自のパーミッションは不可
https://github.com/hotchemi/PermissionsDispatcher
22. Android6.0.x Devices(NTTドコモ)
•Nexus5X
•AQUOS ZETA SH-03G
•AQUOS ZETA SH-01H
•AQUOS Compact SH-02H
•ARROWS NX F-04G
•arrows Fit F-01H
•arrows NX F-02H
•GALAXY S5 SC-04F
•GALAXY Note Edge SC-01G
•GALAXY S5 ACTIVE SC-02G
•GALAXY Tab S 8.4 SC-03G
•Galaxy S6 edge SC-04G
•Galaxy S6 SC-05G
•Xperia Z3 SO-01G
•Xperia Z3 Compact SO-02G
•Xperia Z4 SO-03G
•Xperia A4 SO-04G
•Xperia Z4 Tablet SO-05G
•Xperia Z5 SO-01H
•Xperia Z5 Compact SO-02H
•Xperia Z5 Premium SO-03H
docomo
3月上旬から順次アップデート予定
https://www.nttdocomo.co.jp/info/notice/page/160210_00_m.html
24. • Activity#requestPermissions
• Fragment#requestPermissions
• context#checkSelfPermission
Android5.1以前の端末への対応
チェック
リクエスト
• ContextCompat#checkSelfPermission
• PermissionChecker#checkSelfPermission
少し動作が異なる(後ほど説明します)
Android6.0未満だと、コールバックAPIに、許可済(宣言している
もの)であればGranted、それ以外はDeniedとして渡す。
• ActivityCompat#requestPermissions
• FragmentCompat#requestPermissions
• Activity#shouldShowRequestPermissionRationale
• Fragment#shouldShowRequestPermissionRationale
その他
Android6.0未満で動作すると常にfalse
• ActivityCompat#shouldShowRequestPermissionRationale
• FragmentCompat#shouldShowRequestPermissionRationale
対応するSupport Libraryの利用
Support Library v4
Support Library v13
29. 制限≠取消
取消
パーミッションの許可自体の剥奪
制限
パーミッションの許可は残したまま、機能を
使えないようにする。
ファイル:/data/system/users/{user_id}/runtime-permissions.xml
上記に書き込まれるのはruntime-permissionの対象となるPermissionのみ
その他のPermissionは/data/system/packages.xmlに書き込まれる。
許可:granted=“true”でflags=“0”、拒否:granted=“false”でflags=“1”
ダイアログを表示しない場合:granted=“false”でflags=“2”
ファイル:/data/system/packages.xml
許可:granted=“true”でflags=“0”、制限:granted=“true”でflags=“8”
制限はAndroid4.3以降に隠し機能として存在したAppOps(の変化版?)によって行われる
パッケージまたはsharedUserIdごとに以下の形式で書き込まれる。
<item name=“パーミッション名” granted=“true” flags=“0”>
32. 制限状態での実行を許容した改修
レスポンスへの細かな対応が必要
情報取得時にNullや0が返ってきたときの処理
値を用いた処理、Nullの場合のエラー処理の見直し
制限状態のレスポンス時に、解除要求の実施
PermissionChecker#checkSelfPermissionを使って判断
Snack Bar、Toastなどでやんわりと要求・説明
最初に許可されているので、自分の意思で制限してる?
・ContextCompat#checkSelfPermission(Context context, String permission)
許可の場合は「PERMISSION_GRANTED」を返す。
許可なしの場合は「PERMISSION_DENIED」を返す。
(context#checkPermissionを呼び出してるだけ。context#checkSelfPermissionも同じ)
・PermissionChecker#checkSelfPermission(Context context, String permission)
許可の場合は「PERMISSION_GRANTED」を返す。
許可なしの場合は「PERMISSION_DENIED」を返す。
許可はあるが制限されている場合は「PERMISSION_DENIED_APP_OP」を返す。