1. はじめに
学習内容
- ユーザーにとってプライバシーがますます重要になっている理由。
- これまでのリリースにおける Android のプライバシーに関するベスト プラクティス。
- プライバシーに関するベスト プラクティスを既存のアプリに統合して、プライバシー保護を強化する方法。
作成するアプリの概要
この Codelab では、ユーザーが思い出を保存することができるサンプルアプリに取り組みます。
最初に、次の画面から開始します。
- 権限画面 - ホーム画面に進む前にすべての権限を付与するようユーザーに求める画面。
- ホーム画面 - ユーザーの既存の写真ログをすべて表示する画面。新しい写真ログをここから追加することもできます。
- [ログを追加] 画面 - ユーザーが新しい写真ログを作成できる画面。ここでは、ライブラリにある既存の写真を閲覧したり、カメラを使って新しい写真を撮ったり、現在地の都市を写真ログに追加したりすることができます。
- カメラ画面 - 写真を撮影して写真ログに保存するための画面。
アプリは機能していますが、プライバシーに関する問題が数多くあるため、一緒に改善していきましょう。
この Codelab を通じて、以下を学習します。
- ...アプリでプライバシーが重要な理由
- ...Android のプライバシー機能と主なベスト プラクティス
- ...以下を行い、これらのベスト プラクティスを既存のアプリに実装する方法
- 状況に応じた権限のリクエストを行う
- アプリでの位置情報へのアクセスを減らす
- 写真選択ツールなどのストレージ改善機能を使用する
- データアクセス監査 API を使用する
完了すると、アプリは次のようになります。
- ...上記のプライバシーに関するベスト プラクティスを実装したアプリ。
- ...プライバシー保護を強化して、個人データを慎重に処理することでユーザーを保護して、ユーザー エクスペリエンスを強化するアプリ。
必要なもの
推奨
- 次のアーキテクチャ コンポーネントに精通していること: ViewModel、およびアプリ アーキテクチャ ガイドで提案されているアーキテクチャ。
- Jetpack Compose に精通していること。Compose の概要については、Jetpack Compose チュートリアルをご覧ください。
2. プライバシーが重要な理由
調査により、ユーザーがプライバシーに関して懸念を抱いていることが判明しています。ピュー研究所が実施した調査によると、アメリカ人の 84% は、企業やアプリが収集するデータをほとんど、またはまったく管理できないと感じています。データが直接使用されることに加え、どのようにデータが使用されているかわからないというのが、ユーザーの主な不満です。ターゲティング広告用のプロファイルの作成、第三者へのデータの販売など、他の目的でデータが使用されることをユーザーは懸念しています。一度データが世に出てしまうと、そのデータを削除することはほとんど不可能です。
このようなプライバシーに関する懸念は、使用するサービスやアプリに関するユーザーの意思決定にすでに大きな影響を与えています。実際、ピュー研究所の同じ調査によると、米国の成人の半数以上(52%)が、収集されるデータの量を心配するなどのプライバシーに関する懸念を理由として、製品やサービスの使用を止めたことがあると報告されています。
そのため、アプリユーザーのエクスペリエンスを向上させるには、アプリのプライバシーを強化してこれを示すことが不可欠です。調査では、これがユーザーベースの拡大にも役立つ可能性が高いことが示されています。
この Codelab で説明する機能やベスト プラクティスの多くは、アプリがアクセスするデータの量を減らすことや、個人データに対するユーザーの制御機能を強化することに直接関連しています。どちらの改善も、前述の調査でユーザーが共有した懸念事項に直接対応するものです。
3. 環境をセットアップする
できるだけすぐに開始できるように、たたき台として利用できるスターター プロジェクトを用意しています。このステップでは、スターター プロジェクトを含む Codelab 全体のコードをダウンロードし、エミュレータまたはデバイスでスターター アプリを実行します。
git がインストールされている場合は、以下のコマンドをそのまま実行できます。git がインストールされているかどうかを確認するには、ターミナルまたはコマンドラインで「git –version
」と入力し、正しく実行されることを確認します。
git clone https://github.com/android/privacy-codelab
git がない場合は、ダウンロード リンクをクリックして、この Codelab のすべてのコードをダウンロードできます。
Codelab を設定するには:
- Android Studio で
PhotoLog_Start
ディレクトリのプロジェクトを開きます。 - Android 12(S)以降を搭載したデバイスまたはエミュレータで
PhotoLog_Start
実行構成を実行します。
アプリを実行する権限を付与するよう求める画面が表示されます。これは、環境が正常にセットアップされたことを意味しています。
4. ベスト プラクティス: 状況に応じて権限をリクエストする
重要な多くの機能をロック解除して優れたユーザー エクスペリエンスを実現するためには、実行時の権限付与が不可欠であることはおわかりでしょう。ただ、アプリが権限をリクエストするタイミングと方法もユーザー エクスペリエンスに大きな影響を与えることはご存知でしょうか。
では、PhotoLog_Start
アプリが権限をリクエストする方法を確認して、権限モデルが最適ではない理由を確認してみましょう。
- リリース後すぐに、複数の権限を付与するよう要求する権限プロンプトがユーザーに送信されます。これはユーザーを混乱させる可能性が高く、アプリの信用を落とす場合や、最悪の場合はアンインストールにつながる場合もあります。
- このアプリでは、すべての権限を付与しなければ続行することができません。ユーザーは、これらすべての機密情報へのアクセス権限をリリース時に付与するほどには、アプリを信頼していない場合もあります。
ご想像できるかと思いますが、上記の項目は、アプリの権限リクエスト プロセスを改善するためにこれから行う改善の項目を表しています。それでは始めましょう。
Android のベスト プラクティスの推奨事項には、ユーザーが初めて機能を使用するときに、状況に応じて権限を要求すべきとあります。その理由は、ユーザーがすでに使用している機能を有効化するための権限をアプリがリクエストしても、ユーザーが驚くことはないからです。これは、ユーザー エクスペリエンスの改善に貢献します。PhotoLog アプリでは、ユーザーが初めてカメラまたは位置情報のボタンをクリックするまで、権限のリクエストを待つようにします。
まず、ホーム画面に移動する前にすべての権限の承認をユーザーに強制する権限画面を削除しましょう。このロジックは現在 MainActivity.kt
で定義されているため、そこに移動します。
val startNavigation = if (permissionManager.hasAllPermissions) { Screens.Home.route } else { Screens.Permissions.route }
ユーザーのホーム画面への移動を許可する前に、ユーザーがすべての権限を付与しているかどうかを確認しています。すでに説明したように、これはユーザー エクスペリエンスに関するベスト プラクティスに従っていません。次のコードに変更して、ユーザーがすべての権限を付与しなくてもアプリを操作できるようにします。
val startNavigation = Screens.Home.route
権限画面が不要になったため、NavHost から次の行を削除することもできます。
composable(Screens.Permissions.route) { PermissionScreen(navController) }
続いて、Screens クラスから次の行を削除します。
object Permissions : Screens("permissions")
最後に、PermissionsScreen.kt ファイルも削除できます。
今度は、アプリを削除して再インストールします。これは、すでに付与されている権限をリセットする方法のひとつです。これで、すぐにホーム画面に移動できるはずです。ただ、[ログを追加] 画面でカメラまたは位置情報のボタンを押しても、ユーザーから権限をリクエストするロジックがないため、何も起こりません。これを修正しましょう。
カメラへのアクセス権限をリクエストするロジックを追加する
まず、カメラへのアクセス権限から開始します。権限のリクエストに関するドキュメントにあるコードサンプルに基づいて、RequestPermission()
コントラクトを使用するために権限コールバックを先に登録します。
必要なロジックを評価してみましょう。
- ユーザーが権限を承認した場合は、権限を viewModel に登録します。また、追加済みの写真数の上限にまだ達していない場合は、カメラ画面に移動します。
- ユーザーが権限を拒否した場合、拒否されたためその機能が使用できないことを通知します。
このロジックを実行するには、このコードブロックを次に追加します: // TODO: Step 1. Register ActivityResult to request Camera permission
val requestCameraPermission = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> if (isGranted) { viewModel.onPermissionChange(CAMERA, isGranted) canAddPhoto { navController.navigate(Screens.Camera.route) } } else { coroutineScope.launch { snackbarHostState.showSnackbar("Camera currently disabled due to denied permission.") } } }
次に、カメラ画面に移動する前にアプリにカメラの権限が付与されていることを確認して、ユーザーがまだ権限を許可していない場合はリクエストします。このロジックを実装するには、以下のコードブロックを次に追加します: // TODO: Step 2. Check & request for Camera permission before navigating to the camera screen
canAddPhoto { when { state.hasCameraAccess -> navController.navigate(Screens.Camera.route) // TODO: Step 4. Trigger rationale screen for Camera if needed else -> requestCameraPermission.launch(CAMERA) } }
続いて、アプリを再度実行して、[ログを追加] 画面でカメラアイコンをクリックします。カメラへのアクセス権限を求めるダイアログが表示されます。これで、アプリを開始する前からすべての権限を承認するようユーザーに要求する場合よりも、はるかに改善されました。
ですが、さらに改善する余地はあるでしょうか。あります。アプリでカメラへのアクセスを必要とする理由を説明する根拠の提示を、システムが推奨しているかどうかを確認できます。これにより、権限のオプトインの割合が向上する可能性があります。また、適切なタイミングでアクセス権限を再度リクエストすることも引き続き可能です。
これを行うために、ユーザーのカメラへのアクセス権限をアプリで必要とする理由を説明する画面を作成しましょう。これを行うために、以下のコードブロックを次に追加します: // TODO: Step 3. Add explanation dialog for Camera permission
var showExplanationDialogForCameraPermission by remember { mutableStateOf(false) } if (showExplanationDialogForCameraPermission) { CameraExplanationDialog( onConfirm = { requestCameraPermission.launch(CAMERA) showExplanationDialogForCameraPermission = false }, onDismiss = { showExplanationDialogForCameraPermission = false }, ) }
これでダイアログ自体の用意ができたので、あとは、カメラの権限をリクエストする前に根拠を示す必要があるかどうかを確認するだけです。これを行うには、ActivityCompat の shouldShowRequestPermissionRationale()
API を呼び出します。true が返された場合は、showExplanationDialogForCameraPermission
も true に設定して説明ダイアログを表示します。
state.hasCameraAccess
ケースと else
ケースの間に、または、以前に手順で次の TODO を追加した場所に、次のコードブロックを追加します: // TODO: Step 4. Add explanation dialog for Camera permission
ActivityCompat.shouldShowRequestPermissionRationale(context.getActivity(), CAMERA) -> showExplanationDialogForCameraPermission = true
カメラボタン用の完全なロジックは次のようになります。
canAddPhoto { when { state.hasCameraAccess -> navController.navigate(Screens.Camera.route) ActivityCompat.shouldShowRequestPermissionRationale(context.getActivity(), CAMERA) -> showExplanationDialogForCameraPermission = true else -> requestCameraPermission.launch(CAMERA) } }
お疲れさまでした。Android のベスト プラクティスをすべて遵守しながら、カメラへのアクセス権限を処理できるようになりました。アプリを再度削除して再インストールし、[ログを追加] ページでカメラボタンを押してみます。権限を拒否したとしても、フォト アルバムを開くなどの機能はブロックされません。
一方で、権限を拒否してからカメラアイコンをクリックすると、先ほど追加した説明プロンプトが表示されます。*ユーザーが説明プロンプトで [続行] をクリックした場合にのみ、システム権限プロンプトが表示されます。ユーザーが [後で] をクリックした場合、それ以上ユーザーに干渉することなくアプリが使用できる状態になります。これにより、ユーザーから再度権限が拒否されることがなくなり、権限付与の準備ができたときに別のタイミングで再度リクエストできるようになります。
- 注:
shouldShowRequestPermissionRationale()
API の正確な動作は内部実装の詳細であり、変更される可能性があります。
位置情報の利用許可をリクエストするロジックを追加する
次に、位置情報について同じことをしてみましょう。まず、位置情報の利用許可に対する ActivityResult を登録するために、以下のコードブロックを次に追加します: // TODO: Step 5. Register ActivityResult to request Location permissions
val requestLocationPermissions = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> if (isGranted) { viewModel.onPermissionChange(ACCESS_COARSE_LOCATION, isGranted) viewModel.onPermissionChange(ACCESS_FINE_LOCATION, isGranted) viewModel.fetchLocation() } else { coroutineScope.launch { snackbarHostState.showSnackbar("Location currently disabled due to denied permission.") } } }
続いて、以下のコードブロックを次に追加することで、位置情報の利用許可の説明ダイアログを追加します: // TODO: Step 6. Add explanation dialog for Location permissions
var showExplanationDialogForLocationPermission by remember { mutableStateOf(false) } if (showExplanationDialogForLocationPermission) { LocationExplanationDialog( onConfirm = { // TODO: Step 10. Change location request to only request COARSE location. requestLocationPermissions.launch(arrayOf(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION)) showExplanationDialogForLocationPermission = false }, onDismiss = { showExplanationDialogForLocationPermission = false }, ) }
次に、位置情報の利用許可の確認、説明(必要な場合)、リクエストを行います。権限が付与されている場合は、位置情報を取得して、写真ログにデータを入力できます。以下のコード ブロックを次に追加します: // TODO: Step 7. Check, request, and explain Location permissions
when { state.hasLocationAccess -> viewModel.fetchLocation() ActivityCompat.shouldShowRequestPermissionRationale(context.getActivity(), ACCESS_COARSE_LOCATION) || ActivityCompat.shouldShowRequestPermissionRationale( context.getActivity(), ACCESS_FINE_LOCATION) -> showExplanationDialogForLocationPermission = true else -> requestLocationPermissions.launch(arrayOf(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION)) }
これで、この Codelab の権限のセクションが完了しました。アプリをリセットして結果を確認してみてください。
ユーザー エクスペリエンスとアプリの利点をどのように改善したかに関する概要:
- アプリの起動の直後ではなく、状況に応じて(ユーザーが機能を操作するタイミングで)権限をリクエストする→混乱やユーザーの離脱を減らす。
- 説明画面を用意して、アプリが権限を必要とする理由をユーザーに説明する→ユーザーに対する透明性を高める
- shouldShowRequestPermissionRationale() API で、システムがアプリでの説明画面の表示を推奨しているかを判断する→権限承認率を高め、永続的に権限が拒否される可能性を減らす。
5. ベスト プラクティス: アプリの位置情報へのアクセスを減らす
位置情報は機密情報に関わる権限として代表的なものであるため、Android のプライバシー ダッシュボードには位置情報に関する機能が備わっています。
簡単に言うと、Android 12 では、位置情報に関する追加の管理機能がユーザーに提供されています。正確な位置情報ではなくおおよその位置情報を選択できるため、アプリが位置情報へのアクセスをリクエストしたときに精度の低い位置情報をアプリと共有することを明示的に選択できるようになりました。
おおよその位置情報では、3 平方キロメートル以内のユーザーの位置情報の推定値が提供されます。この精度は、アプリの機能の多くで十分な精度です。アプリで位置情報へのアクセスを必要とするすべてのデベロッパーが、ユースケースを確認することをおすすめします。正確な位置情報を必要とする機能をユーザーが積極的に使用している場合にのみ、ACCESS_FINE_LOCATION
をリクエストするようにします。
カリフォルニア州ロサンゼルスの繁華街を中心とした、おおよその位置情報の推定値の範囲を視覚化したグラフィック。
PhotoLog アプリの場合、ユーザーの都市を使用して「思い出」の場所をユーザーに思い出してもらうことだけを行うので、おおよその位置情報へのアクセスだけで間違いなく十分です。しかし、このアプリは現在、ユーザーに ACCESS_COARSE_LOCATION
と ACCESS_FINE_LOCATION
の両方を要求しています。これを変更しましょう。
まず、位置情報のアクティビティの結果を編集し、ActivityResultContracts.RequestMultiplePermissions()
ではなく ActivityResultContracts.RequestPermission()
関数をパラメータとして提供して、ACCESS_COARSE_LOCATION
のみをリクエストすることを反映させる必要があります。
代わりに、現在の requestLocationsPermissions オブジェクト(// TODO: Step 8. Change activity result to only request Coarse Location
で表示)を次のコードブロックに置き換えます。
val requestLocationPermissions = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> if (isGranted) { viewModel.onPermissionChange(ACCESS_COARSE_LOCATION, isGranted) } }
次に、両方の位置情報の利用許可ではなく ACCESS_COARSE_LOCATION
のみを要求するように launch()
メソッドを変更します。
次のように置き換えます。
requestLocationPermissions.launch(arrayOf(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION))
...を以下で置き換えます。
requestLocationPermissions.launch(ACCESS_COARSE_LOCATION)
変更する必要のある PhotoLog の launch()
メソッドのインスタンスは 2 つあります。1 つは // TODO: Step 9. Change location request to only request COARSE location
で示される LocationExplanationDialog
の onConfirm()
ロジックにあります。もう 1 つは、// TODO: Step 10. Change location request to only request COARSE location
で示される [Location] リストアイテムにあります。
最後に、PhotoLog の ACCESS_FINE_LOCATION
権限をリクエストしなくなったので、このセクションを AddLogViewModel.kt の onPermissionChange() メソッドから削除します。
Manifest.permission.ACCESS_FINE_LOCATION -> { uiState = uiState.copy(hasLocationAccess = isGranted) }
アプリのマニフェストから ACCESS_FINE_LOCATION
を削除することも忘れないでください。
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
これで、Codelab の位置情報のセクションが完了しました。アプリをアンインストール後に再インストールして、結果を確認してみてください。
6. ベスト プラクティス: ストレージ権限の使用を最小限に抑える
デバイス上に保存された写真をアプリが操作することはよくあることです。ユーザーが目的の写真や動画を選択できるように、そのようなアプリで独自のファイル選択ツールが実装されていることはよくありますが、そのような場合、ストレージへの幅広いアクセス権限が要求されます。ユーザーは、自身のすべての写真へのアクセスを許可することを望んでいません。また、デベロッパーは独立したファイル選択ツールを管理したくないと考えています。
Android 13 では写真選択ツールが導入されています。これは、メディア ライブラリ全体へのアクセス権を付与せずにアプリのメディア ファイルを選択できるようにするためのツールです。また、Google Play システム アップデートにより、Android 11 および 12 にバックポートされています。
PhotoLog アプリの機能として、PickMultipleVisualMedia
ActivityResultContract を使用します。デバイスで利用できる場合は Android 写真選択ツールを使用して、古いデバイスでは ACTION_OPEN_DOCUMENT
インテントを使用します。
まず、ActivityResultContract を AddLogScreen
ファイルに登録します。これを行うには、この行の後に次のコードブロックを追加します: // TODO: Step 11. Register ActivityResult to launch the Photo Picker
val pickImage = rememberLauncherForActivityResult( PickMultipleVisualMedia(MAX_LOG_PHOTOS_LIMIT), viewModel::onPhotoPickerSelect )
注: ここでの MAX_LOG_PHOTOS_LIMIT
は、ログに追加するときに設定することを選択した写真の上限を表します(この場合は 3 枚)。
次に、アプリの内部選択ツールを Android 写真選択ツールに置き換える必要があります。ブロックの後に次のコードを追加します: // TODO: Step 12. Replace the below line showing our internal UI by launching the Android Photo Picker instead
pickImage.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly))
この 2 行のコードを追加することにより、権限のない方法でデバイスの写真にアクセスできるようになりました。これにより UX が大幅に改善し、コードの保守が不要になります。
PhotoLog での写真へのアクセスで、従来型の写真グリッドとストレージの権限を必要としなくなったため、マニフェストのストレージ権限エントリからその背後にあるロジックまで、従来型の写真グリッドを含むコードをすべて削除できます(このアプリで必要なくなったためです)。
7. 推奨: デバッグビルドでデータアクセス監査 API を使用する
アプリがアクセスしているユーザーデータの種類を追跡することが困難な、さまざまな機能や関係者が関与する(または、そうなることが予想される)大規模なアプリはありますか?ある時点で使用されていた API や SDK からのデータアクセスでも、現時点でアプリに留まっている場合、そのデータアクセスの責任を負うことをご存知でしょうか?
Google は、含まれるすべての SDK やその他の依存関係を含め、アプリが個人データにアクセスしている場所をすべて追跡することは困難であると理解しています。そのため、アプリとその依存関係がユーザーの個人データにどのようにアクセスしているかに関する透明性を高めるために、Android 11 ではデータアクセスの監査が導入されています。この API を使用すると、デベロッパーは次のいずれかのイベントが発生するたびに、ログファイルへの出力などの特定のアクションを実行できます。
- アプリのコードがプライベート データにアクセスした。
- 依存ライブラリまたは SDK のコードがプライベート データにアクセスした。
まず、Android でのデータアクセス監査 API の動作の基本について説明します。データアクセス監査を導入するため、AppOpsManager.OnOpNotedCallback
のインスタンスを登録します(Android 11 以降をターゲットとする必要があります)。
また、コールバックの 3 つのメソッドをオーバーライドする必要もあります。これらのメソッドは、さまざまな方法でユーザーデータにアプリがアクセスするときにシステムによって呼び出されます。以下がそのメソッドです。
onNoted()
- アプリがユーザーデータにアクセスする同期(双方向バインディング)API を呼び出したときに呼び出されます。これらは通常、コールバックを必要としない API 呼び出しです。onAsyncNoted()
- アプリがユーザーデータにアクセスする非同期(一方向バインディング)API を呼び出したときに呼び出されます。これらは通常、コールバックを必要とする API 呼び出しであり、コールバックが呼び出されるとデータアクセスが発生します。onSelfNoted()
- 呼び出されるのはごくまれな場合で、アプリが自身の UID を noteOp() などに渡すときに呼び出されます。
次に、PhotoLog アプリでのデータアクセスにどのメソッドが適用されるかを判断しましょう。PhotoLog は主に 2 つのタイミングでユーザーデータにアクセスします。1 つはカメラの有効化時、もう 1 つはユーザーの位置情報へのアクセス時です。どちらも比較的リソースを大量に消費するため、これらは両方とも非同期 API 呼び出しになります。それぞれのユーザー データにアクセスするときには、システムが onAsyncNoted()
を呼び出すことが想定されます。
PhotoLog でデータアクセス監査 API をどのように導入するか見てみましょう。
まず、AppOpsManager.OnOpNotedCallback()
のインスタンスを作成し、上記の 3 つのメソッドをオーバーライドする必要があります。
オブジェクト内の 3 つのメソッドすべてについて、個人ユーザーデータにアクセスしたオペレーションをログに記録しましょう。このオペレーションで、アクセスされたユーザーデータの種類に関する詳細情報を確認できます。また、カメラと位置情報にアプリがアクセスするときに onAsyncNoted()
が呼び出されることが想定されています。そこで、特別な操作を行い、位置情報アクセス用の地図の絵文字とカメラアクセス用のカメラの絵文字をログに記録してみましょう。これを行うために、以下のコード ブロックを次に追加します: // TODO: Step 1. Create Data Access Audit Listener Object
@RequiresApi(Build.VERSION_CODES.R) object DataAccessAuditListener : AppOpsManager.OnOpNotedCallback() { // For the purposes of this codelab, we are just logging to console, // but you can also integrate other logging and reporting systems here to track // your app's private data access. override fun onNoted(op: SyncNotedAppOp) { Log.d("DataAccessAuditListener","Sync Private Data Accessed: ${op.op}") } override fun onSelfNoted(op: SyncNotedAppOp) { Log.d("DataAccessAuditListener","Self Private Data accessed: ${op.op}") } override fun onAsyncNoted(asyncNotedAppOp: AsyncNotedAppOp) { var emoji = when (asyncNotedAppOp.op) { OPSTR_COARSE_LOCATION -> "\uD83D\uDDFA" OPSTR_CAMERA -> "\uD83D\uDCF8" else -> "?" } Log.d("DataAccessAuditListener", "Async Private Data ($emoji) Accessed: ${asyncNotedAppOp.op}") } }
次に、先ほど作成したコールバック ロジックを実装する必要があります。システムでデータアクセスの計測が開始されるのは、コールバックの登録後であるため、最良の結果を得るために、できる限り早くこれを行います。コールバックを登録するには、以下のコードブロックを次に追加します: // TODO: Step 2. Register Data Access Audit Callback
.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val appOpsManager = getSystemService(AppOpsManager::class.java) as AppOpsManager appOpsManager.setOnOpNotedCallback(mainExecutor, DataAccessAuditListener) }
8. まとめ
今回の内容を振り返りましょう...
- ...アプリでプライバシーが重要な理由を学習しました。
- ...Android のプライバシー機能を学習しました。
- ...以下を行い、アプリのプライバシーに関する重要なベスト プラクティスを数多く実装しました。
- 状況に応じた権限のリクエストを行う
- アプリでの位置情報へのアクセスを減らす
- 写真選択ツールなどのストレージ改善機能を使用する
- データアクセス監査 API を使用する
- ...既存のアプリにこれらのベスト プラクティスを実装して、アプリのプライバシーを強化しました。
PhotoLog のプライバシーとユーザー エクスペリエンスを向上させ、その過程でさまざまなコンセプトを学習しましたが、いかがでしたでしょうか。
参照コードを確認するには(省略可):
この Codelab の解答コードをまだ確認していない場合は、PhotoLog_End
フォルダで確認できます。この Codelab の手順に厳密に従うと、PhotoLog_Start
フォルダ内のコードは PhotoLog_End
フォルダ内のコードと同じになるはずです。
詳細
これで完了です。上記で説明したベスト プラクティスについて詳しくは、Android のプライバシーに関するランディング ページをご覧ください。