特別な権限をリクエストする

特別な権限は、特に機密性の高い、またはユーザーのプライバシーに直接関係しないシステム リソースへのアクセスを保護します。これらの権限は、インストール時の権限実行時の権限とは異なります。

図 1: システム設定の [特別なアプリアクセス] 画面。

特別な権限の例を次に示します。

  • 正確なアラームをスケジュールする。
  • 他のアプリの上に重ねて表示、描画する。
  • すべてのストレージ データにアクセスする。

特別な権限を宣言するアプリは、システム設定の [特別なアプリアクセス] ページに表示されます(図 1)。アプリに特別な権限を付与するには、ユーザーは [設定] > [アプリ] > [特別なアプリアクセス] に移動する必要があります。

ワークフロー

特別な権限をリクエストする手順は次のとおりです。

  1. アプリのマニフェスト ファイル内で、アプリがリクエストする必要がある特別な権限を宣言します。
  2. アプリの特定のアクションが特定の特別な権限に関連付けられるようアプリの UX を設計します。アプリが非公開のユーザーデータにアクセスするための権限の付与がどのアクションで必要となるかをユーザーが認識できるようにします。
  3. 特定の非公開のユーザーデータへのアクセスを必要とするアプリ内のタスクやアクションをユーザーが起動するまで待ちます。ユーザーが起動した時点で、アプリはそのデータへのアクセスに必要となる特別な権限をリクエストできます。
  4. アプリが必要とする特別な権限をユーザーがすでに付与しているかどうかを確認します。そのためには、各権限のカスタム チェック関数を使用します。すでに付与されている場合、アプリは非公開のユーザーデータにアクセスできます。付与されていない場合は、次のステップに進みます。注: 権限を必要とする操作を実行するたびに、その権限の有無を確認する必要があります。
  5. UI 要素で、アプリがアクセスしようとしているデータ、特別な権限を付与した場合にアプリからユーザーにもたらされるメリットについて、明確な根拠を示します。また、アプリはユーザーが権限を付与できるようシステム設定にリダイレクトするため、ユーザーが権限を付与する方法を示す簡単な手順も含めます。根拠を示す UI では、ユーザーが権限の付与を無効にできる明確なオプションを提供する必要があります。ユーザーが根拠を確認したら、次のステップに進みます。
  6. アプリが非公開のユーザーデータにアクセスするために必要な特別な権限をリクエストします。これには多くの場合、ユーザーが権限を付与できるシステム設定の対応するページへのインテントが含まれます。実行時の権限とは異なり、ポップアップの権限ダイアログはありません。
  7. onResume() メソッドにおけるユーザーの応答で、ユーザーが特別な権限を付与するか、拒否するかを確認します。
  8. ユーザーがアプリに権限を付与した場合は、非公開のユーザーデータにアクセスできます。ユーザーが権限を拒否した場合は、アプリ エクスペリエンスのグレースフル デグラデーションを行って、その権限で保護される情報がなくてもユーザーに機能が提供されるようにします。
図 2: Android で特別な権限を宣言してリクエストする場合のワークフロー。

特別な権限をリクエストする

実行時の権限とは異なり、ユーザーはシステム設定の [特別なアプリアクセス] ページから特別な権限を付与する必要があります。アプリは、インテントを使用してユーザーをこのページにリダイレクトできます。インテントはアプリを一時停止し、特定の特別な権限に対応する設定ページを起動します。 ユーザーがアプリに戻った後、アプリは onResume() 関数で権限が付与されたかどうかを確認できます。

次のサンプルコードは、ユーザーに SCHEDULE_EXACT_ALARMS の特別な権限をリクエストする方法を示しています。

val alarmManager = getSystemService<AlarmManager>()!!
when {
   // if permission is granted, proceed with scheduling exact alarms…
   alarmManager.canScheduleExactAlarms() -> {
       alarmManager.setExact(...)
   }
   else -> {
       // ask users to grant the permission in the corresponding settings page
       startActivity(Intent(ACTION_REQUEST_SCHEDULE_EXACT_ALARM))
   }
}

onResume() で権限を確認し、ユーザーの決定を処理するためのサンプルコードを以下に示します。

override fun onResume() {
   // ...

   if (alarmManager.canScheduleExactAlarms()) {
       // proceed with the action (setting exact alarms)
       alarmManager.setExact(...)
   }
   else {
       // permission not yet approved. Display user notice and gracefully degrade
       your app experience.
       alarmManager.setWindow(...)
   }
}

おすすめの方法とヒント

以降のセクションでは、特別な権限をリクエストする際のおすすめの方法と考慮事項について説明します。

権限ごとに固有のチェック方法がある

特別な権限は、実行時の権限とは動作が異なります。代わりに、権限 API リファレンス ページを参照し、特別な権限ごとにカスタム アクセス チェック関数を使用してください。これには、SCHEDULE_EXACT_ALARMS 権限の AlarmManager#canScheduleExactAlarms()MANAGE_EXTERNAL_STORAGE 権限の Environment#isExternalStorageManager() などがあります。

状況に応じてリクエストする

実行時の権限と同様に、権限を必要とする特定のアクションをユーザーがリクエストした場合、アプリは状況に応じて特別な権限をリクエストする必要があります。たとえば、特定の時間にメールを送信するようにユーザーがスケジュールを設定するまで待ってから、SCHEDULE_EXACT_ALARMS 権限をリクエストします。

リクエストについて説明する

システム設定にリダイレクトする前に、その根拠を示します。ユーザーは、特別な権限を付与するため一時的にアプリから離れるため、システム設定の [特別なアプリアクセス] ページへのインテントを起動する前に、アプリ内 UI を表示します。この UI では、アプリが権限を必要とする理由と、ユーザーが設定ページで権限を付与する方法を明確に説明する必要があります。