Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

パーミッションモデルの過渡期への対応

8,815 views

Published on

DroidKaigi2016 2/18 15:50からのRoomDのセッションで説明した資料です。

Published in: Software
  • Be the first to comment

パーミッションモデルの過渡期への対応

  1. 1. パーミッションモデルの 過渡期への対応 DroidKaigi2016 2016/2/18 aki_sh_7
  2. 2. 自己紹介  aki_sh_7(塩田 明弘)  株式会社NTTデータ所属  セキュリティビジネス推進室(2013/4~)  2014/4より社内のAndroidアプリ開発者向けの セキュリティガイドライン作成やサポートに従事
  3. 3. 目次 1. Runtime Permissionについて 2. Android5.1以前の端末に対応した targetSDKversion=23のアプリの作り方 3. targetSDKversion=23に出来ないアプリが Android6.0の端末で問題を起こさない方法 4. まとめ
  4. 4. 1. Runtime Permissionについて
  5. 5. Android6.0の大きな変更点 新しいパーミッションモデル Runtime Permissionの導入
  6. 6. 旧来のパーミッションモデル インストール時に許可の確認  許可したくないパーミッションが あっても使うには許可するしかない インストール後に取消不可  一度許可したらアンインストールし ないと取り消せない
  7. 7. Runtime Permission 実行時に許可の確認  ProtectionLevel=dangerousのみ  パーミッショングループ単位  チェック等の処理は作る必要あり  ユーザーが「今後は表示しない」と することも可能(一度拒否が必要) インストール後に取消可能  うっかり許可しても対応可能 Android6.0でも targetSdkVersion<23だと Runtime Permissionではない
  8. 8. モデルごとの特徴 ~Android5.1 Android6.0~ (targertSdkVersion<23) Android6.0~ (targertSdkVersion>=23) Install 許可 許可 Dangerous以外許可 (確認なし) Runtime - - 要求に応じて許可 Setting - Dangerousは制限可 Dangerousは取消可
  9. 9. Permissionが必要なAPIへの対応  許可されていない状態でAPIを使用  結果はPermission Denial  自動で要求処理はしてくれない  API使用前に3つの処理が必要  Step1. チェック  Step2. リクエスト  Step3. ハンドリング
  10. 10. API使用前の簡易フローチャート 許可 有り? 終了 開始 有 無 パーミッション要求 要求結果受け取り 許可 された? Y API使用 呼び出し不可表示 N Step1 Step2 Step3 過去に 拒否した N 追加説明 Y 今後表示 しない? N 呼出し不可表示2 Y
  11. 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. 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. 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. 14. いつリクエストしたらよいか  最初にリクエスト(チュートリアル)  絶対必要な機能(これだけでも使える)  カメラアプリでCAMERA権限  カレンダーアプリでCALENDER権限  実行前に再チェックは必要!  実行中にリクエスト  アプリの出来ることを広げる機能  メッセージアプリで現在地投稿 →現在地ボタン押下時にLOCATION権限  関係ないところで要求すると不信感を持たれる  それとわかるようにデザインする  そもそもリクエストしないという選択肢  カメラで撮った画像が必要なら、カメラを呼び出して撮影する message
  15. 15. 説明はどこまでやるか  最初の説明(チュートリアル)  アプリから権限が必要と連想しにくいもの  実行中にリクエストすることの予告  SNSアプリ:メッセージの他に、画像投稿する場合は許可が必要  実行中の説明  リクエストしている権限についての説明。 ここで許可することによる、アプリ全体への影響を説明する。  一度拒否している場合はより詳細に  Activity#shouldShowRequestPermissionRationale  拒否された後の説明  許可しないと機能が使えない旨の説明。  「今後表示しない」のチェックを入れられた場合、アプリの詳細設 定からしか設定できなくなる。誘導ボタン等を設置
  16. 16. 対応の効率化  パーミッションの許可が必要なAPI全てに、 ミス無しにこの処理を書くのは大変  ライブラリ(PermissionsDispatcher)の利用  Annotation Processingを使ってハンドリングするクラスを作成  条件分岐を書かなくていい!  各条件で処理を行いたいメソッドにアノテーションを付与すればいい @RuntimePermissions:Activityやフラグメントに付与 @NeedPermission:パーミッションが必要なAPIを使うメソッドに付与 @OnShowRational:一度拒否されている場合に説明などを行うメソッドに付与 @OnPermissionDenied:拒否された場合の処理を行うメソッドに付与 @OnNeverAskAgain:「今後は表示しない」の場合の処理を行うメソッドに付与  独自のパーミッションは不可 https://github.com/hotchemi/PermissionsDispatcher
  17. 17. どれくらいの人が 恩恵を受けられる?
  18. 18. Platform Versions(2016/1) 1.2% 17.1% 17.0% 35.5% 3.4% 11.7% 8.8% 2.5% 2.7% 0.1% Distribution 6.0 5.1 5.0 4.4 4.3 4.2.x 4.1.x 4.0.3-4.0.4 2.3.3-2.3.7 2.2 Dashboards, http://developer.android.com/intl/ja/about/dashboards/index.html
  19. 19. Platform Versions(2016/1) 1.2% 17.1% 17.0% 35.5% 3.4% 11.7% 8.8% 2.5% 2.7% 0.1% Distribution 6.0 Dashboards, http://developer.android.com/intl/ja/about/dashboards/index.html
  20. 20. Android6.0.x Devices(Worldwide) •Pixel C •Nexus6P •Nexus5X •Nexus9 •Nexus6 •Nexus5 •Nexus7 (2013) Google •HTC One A9 •HTC One M9 •HTC One M8 •Butterfly 2 HTC •G4 •G3 •G Flex2 •G Stylo LG •Moto G(3rd gen) •Moto X Play •Moto G Turbo Edition •Droid Turbo 2 Motolora •Mate 8 •Honor 7 EE •Honor 7 Huawei •Galaxy S6 •Galaxy S6 edge Samsung •M4 •Mi Note Xiaomi and more…
  21. 21. Android6.0.x Devices(Japan) •Pixel C •Nexus6P •Nexus5X •Nexus9 •Nexus6 •Nexus5 •Nexus7 (2013) Google •HTC One A9 •HTC One M9 •HTC One M8 •Butterfly 2 HTC •G4 •G3 •G Flex2 •G Stylo LG •Moto G(3rd gen) •Moto X Play •Moto G Turbo Edition •Droid Turbo 2 Motolora •Mate 8 •Honor 7 EE •Honor 7 Huawei •Galaxy S6 •Galaxy S6 edge Samsung •M4 •Mi Note Xiaomi
  22. 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
  23. 23. 2. Android5.1以前の端末に対応した targetSDKversion=23のアプリの作り方
  24. 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
  25. 25. 3. targetSDKversion=23に出来ないアプリが Android6.0の端末で問題を起こさない方法
  26. 26. targetSdkVersion=23に 出来ないケース(一例) targetSdkVersion を上げたら他の部 分でバグが出る… お客様先から 改修予算が下 りない… 人手不足で全て のアプリに手を 回せない… The Android robot is reproduced or modified from work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License.
  27. 27. 【再掲】新パーミッションモデルの特徴 ~Android5.1 Android6.0~ (targertSdkVersion<23) Android6.0~ (targertSdkVersion>=23) Install 許可 許可 Dangerous以外許可 (確認なし) Runtime - - 要求に応じて許可 Setting - Dangerousは制限可 Dangerousは取消可 制限≠取消
  28. 28. 制限≠取消  取消  パーミッションの許可自体の剥奪  制限  パーミッションの許可は残したまま、機能を 使えないようにする。
  29. 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”>
  30. 30. 制限≠取消  取消時と制限時では、APIを使用したと きのレスポンスが異なる。  情報取得系では0やNULLが返ってくる  変更を加えるAPIは実際には行われない 何かしらの代替処理が行われ、 実質的にAPI使用不可。 ただし、Exceptionが発生して落ちることは無い (例外:カメラはExceptionが発生)
  31. 31. 対応例  targetSdkVersion=23に上げられない理由や、 今後の計画によって対応方針を決定する。 実行を許容 別処理の実行 実行を拒否 概要 制限状態のレスポ ンスにあわせたハ ンドリング 制限状態ではAPIを 利用せず、代替処理 を実行 制限状態では動作を 行わない(解除を要求) チェック API使用後 API使用前 Activity開始・再開時 稼働 大 中 小
  32. 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」を返す。
  33. 33. 制限状態では別処理を行う改修 制限状態のレスポンスは受け取らない API使用前にパーミッションのチェック  PERMISSION_GRANTED  正常系  PERMISSION_DENIED_APP_OP  別処理  実際に処理を行わなくてもよい  こちらも説明や変更要求などをやんわりと
  34. 34. 制限状態での実行を拒否した改修  Android6.0未満の端末と同じ動作のみ想定  Android6.0未満を想定して設計したアプリはそのまま  Android6.0以降を想定したアプリを作る方にリソースを割く  Activity開始時に、制限されていたら解除要求  onStart以降かonCreate+onRestartでチェック  パーミッションを設定画面で変更すると、プロセスがキルさ れる。その後アプリを呼び出すと、設定変更前のActivityが再 生成される。 Android6.0以降のRuntime Permissionの考え方と間逆! あくまでどうしようもない場合の一時的な措置であり、 早い段階でtargetSdkVersion=23への対応を
  35. 35. 4. まとめ
  36. 36. まとめ AndroidのパーミッションモデルはAndroid 6.0で新しい モデルにとなり、(一部だけど)ユーザーが決定権を持つよ うになった。 今はまだ使える人は少ないが、もうじき本格対応が必須と なる。その際、古い端末でも動作するように気をつける必 要がある。 一方、新しいパーミッションモデルやtargetSdkVersion を上げることができない場合は、過渡期の間の応急対処を しつつ、本格対応に備える。
  37. 37. おまけ
  38. 38. グループ単位での設定変更の影響  パーミッションの設定変更は、AndroidManifestで宣言さ れているグループ内のパーミッション全てに対して一律に 行われる  設定画面からの変更でも、requestPermissionsによるア プリからの要求でも同じ。要求は引数にパーミッションを 一つ指定すれば、グループ全体に影響が及ぶ  すでに許可されていたり、Never askが設定されてい てダイアログが呼び出されなかったりする。 <use-permission android:name=“android.permission. READ_CONTACTS”> <use-permission android:name=“android.permission. WRITE_CONTACTS”>①AndroidManifestでの宣 言 <pkg name="com.sample.sample"> <item name="android.permission. READ_CONTACTS" granted="true" flags="0" /> <item name="android.permission. WRITE_CONTACTS" granted="true" flags="0" /> </pkg> ③パーミッションの許可状況 /data/system/user/{userId}/runtime-permissions.xml requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_READ_CONTACTS);②アプリ内でのパーミッション要求
  39. 39. sharedUserIdによる設定共有  sharedUserIdを設定したアプリ間では、許可/不許可の設定も 共有される。(これまでもPermissionは共有されている) 連絡帳の読 取アプリA  アプリAで許可を行うと、アプリBでも許可される。  アプリBのManifestファイル中で宣言されていないPermissionで も、アプリAで宣言されていれば許可されるが、アプリBの設定画面 からは変更できない。 位置情報へのアクセス アプリB 宣言したPermission ・位置情報へのアクセ ス ・連絡帳の読取 宣言したPermission ・位置情報へのアクセ ス
  40. 40. アプリバージョンアップ時の注意点  アプリケーションをバージョンアップした際、 それまで与えられていたパーミッションは引き継がれる。 targetSdkVersionを22から23に変更した場合も同様。  そのため、バージョンアップにおいては、runtime- permissionのモデルだが、install-timeの設定が継続される。  バージョンアップ後の初回起動時に、対応したことを知らせ、 確認を促す画面などを作ってもよいかもしれない。

×