権限の目的は、Android ユーザーのプライバシーを保護することです。Android アプリは、ユーザーの機密データ(連絡先や SMS)と特定のシステム機能(カメラやインターネット)にアクセスする権限をリクエストする必要があります。機能に応じて、システムは権限を自動的に付与するか、またはユーザーにリクエストの承認を求めます。
Android セキュリティ アーキテクチャの設計においては、他のアプリ、オペレーティング システム、またはユーザーに悪影響を及ぼしかねないオペレーションの実行権限を、いかなるアプリにもデフォルトで付与しないよう徹底されています。そうしたオペレーションとしては、ユーザーの個人情報(連絡先やメールアドレス)の読み取りまたは書き込み、他のアプリのファイルの読み取りまたは書き込み、ネットワークへのアクセス、デバイスのスリープモードへの移行の抑止などがあります。
このページでは、Android の権限の仕組み(権限の種類と権限グループ、権限が適用される仕組みなど)の概要について説明します。アプリの権限を使用するための入門ガイドのみを参照したい場合は、アプリの権限を宣言するおよびアプリの権限をリクエストするをご覧ください。
保護レベル
権限はいくつかの保護レベルに分類されます。保護レベルは、実行時の権限リクエストが必要かどうかに影響します。
サードパーティのアプリに影響する保護レベルは、標準、署名、危険の 3 つです。特定の権限の保護レベルを確認するには、権限 API リファレンスのページをご覧ください。
標準の権限
標準の権限に該当するのは、アプリがアプリのサンドボックス外のデータやリソースにアクセスする必要があるが、ユーザーのプライバシーまたは他のアプリのオペレーションに影響する危険がほとんどないケースです。たとえば、タイムゾーンを設定する権限は、標準の権限です。
アプリがマニフェストで標準の権限が必要であると宣言している場合、システムはインストール時にその権限を自動的にアプリに付与します。ユーザーは標準の権限を付与するかどうかを尋ねられることはなく、標準の権限を取り消すこともできません。
署名権限
このタイプの権限については、権限の使用を要求するアプリが権限を定義しているアプリと同じ証明書で署名されている場合に限り、システムはインストール時に権限をアプリに付与します。
危険な権限
危険な権限に該当するのは、アプリがユーザーの個人情報を含むデータやリソースを要求するケースや、ユーザーが保存したデータや他のアプリのオペレーションに影響を及ぼす可能性があるケースです。たとえば、ユーザーの連絡先を読み取る機能には、危険な権限が必要です。危険な権限が必要であるとアプリが宣言した場合、ユーザーは明示的にアプリに権限を付与することを求められます。ユーザーが権限を承認しない限り、アプリはその権限に依存する機能を提供できません。
アプリが危険な権限を使用するには、実行時に権限の付与をユーザーにリクエストする必要があります。ユーザーにプロンプトを表示する方法の詳細については、危険な権限をリクエストするプロンプトをご覧ください。
特別な権限
標準の権限とも危険な権限とも異なる効果を持つ権限がいくつかあります。SYSTEM_ALERT_WINDOW
と WRITE_SETTINGS
は特に取扱いに注意を要するため、ほとんどのアプリでは使用を避けるべきです。
ほとんどの場合、アプリはマニフェスト内で SYSTEM_ALERT_WINDOW
権限を宣言し、かつ、ユーザーの承認をリクエストするインテントを送信する必要があります。システムはインテントに対応するために、ユーザーに対して詳細な管理画面を表示します。
Android 11(API レベル 30)以降、ACTION_MANAGE_OVERLAY_PERMISSION
インテント アクションを呼び出すアプリではパッケージを指定できません。このインテント アクションを含むインテントをアプリが呼び出したとき、ユーザーはまず権限を付与するアプリまたは権限を取り消すアプリを選択することを求められます。この動作は、権限を付与する際の意識を高めることで、ユーザーの保護を強化することを目的としています。
これらの権限をリクエストする方法の詳細については、SYSTEM_ALERT_WINDOW
および WRITE_SETTINGS
のリファレンスの説明をご覧ください。
Android システムが提供するすべての権限は、Manifest.permission
で確認できます。
権限グループ
権限は、デバイスの機能に応じて、いくつかのグループに分類されています。このシステムの下で、権限リクエストはグループレベルで処理されます。1 つの権限グループがアプリ マニフェスト内の複数の権限の宣言に対応します。たとえば、SMS グループには READ_SMS
宣言と RECEIVE_SMS
宣言の両方が含まれています。権限をこのようにグループ化することにより、ユーザーは、複雑で専門的な権限リクエストに煩わされずに、十分な情報に基づいて適切な判断を下すことができます。
Android システムのすべての危険な権限は、なんらかの権限グループに属しています。権限は、保護レベルと無関係に同じ権限グループに属する場合があります。ただし、ある権限が属するグループがユーザー エクスペリエンスに影響するのは、その権限が危険な権限である場合だけです。
アプリが Android 6.0(API レベル 23)以上を搭載したデバイスにインストールされている場合や、Android 6.0 以上をターゲットとしている場合、システムは特定の動作を実行します。アプリが Android 5.1(API レベル 22)以下を搭載したデバイスにインストールされている場合や、Android 5.1 以下をターゲットとしている場合、システムは別の動作を実行します。
デバイスで Android 6.0 以上を実行していて、アプリの targetSdkVersion
が 23 以上である場合、アプリが危険な権限をリクエストしたときにシステムは次のように動作します。
-
現在、該当する権限グループ内の権限がいずれもアプリにない場合は、アプリがアクセスしようとしている権限グループを示す権限リクエスト ダイアログがユーザーに表示されます。そのグループ内の具体的な権限はダイアログに表示されません。たとえば、アプリが
READ_CONTACTS
権限をリクエストした場合、ダイアログには、アプリがデバイスの連絡先にアクセスする必要があることだけが示されます。ユーザーが承認した場合は、リクエストされた権限だけがアプリに付与されます。 -
同じ権限グループ内の別の危険な権限がすでにアプリに付与されている場合は、ユーザーへのプロンプトなしで、リクエストされた権限が直ちにアプリに付与されます。たとえば、以前
READ_CONTACTS
権限をリクエストして付与されたアプリがWRITE_CONTACTS
をリクエストした場合、ユーザーに権限リクエスト ダイアログは表示されず、直ちにその権限がアプリに付与されます。
注意: Android SDK の将来のバージョンで、特定の権限が別のグループに移動される可能性があります。そのため、現行の権限グループの編成に基づいてアプリのロジックを作成することは避けてください。
たとえば、Android 8.1(API レベル 27)では、READ_CONTACTS
は WRITE_CONTACTS
と同じ権限グループに属しています。アプリが READ_CONTACTS
権限をリクエストした後で WRITE_CONTACTS
権限をリクエストした場合、システムが WRITE_CONTACTS
権限を自動的に付与すると想定しないようにしてください。
デバイスで Android 5.1(API レベル 22)以下を実行しているか、アプリの targetSdkVersion
が 22 以下である場合、ユーザーはインストール時に権限を付与するかどうかを尋ねられます。この場合も、システムは、個別の権限ではなく、どの権限グループがアプリに必要かをユーザーに知らせます。たとえば、アプリが READ_CONTACTS
をリクエストした場合、連絡先グループがインストール ダイアログに示されます。ユーザーが承認すると、READ_CONTACTS
権限だけがアプリに付与されます。
注: ユーザーが同じ権限グループ内の別の権限をすでに付与している場合も、アプリはすべての必要な権限を明示的にリクエストする必要があります。また、権限グループの編成は、将来の Android リリースで変更される可能性があります。アプリのコードでは、同じグループに属する特定の権限のセットに依存するロジックを使用しないようにしてください。
アプリの権限を表示する
システムで現在定義されているすべての権限を表示するには、設定アプリまたはシェルコマンド adb shell pm list permissions
を使用します。設定アプリにアクセスするには、[設定] > [アプリ] に移動します。アプリを選択して下にスクロールすると、アプリが使用する権限を確認できます。デベロッパーの場合は、adb
コマンドの -s
オプションを使用して、ユーザーが目にするのと同様の形式で権限を表示できます。
$ adb shell pm list permissions -s All Permissions: Network communication: view Wi-Fi state, create Bluetooth connections, full internet access, view network state Your location: access extra location provider commands, fine (GPS) location, mock location sources for testing, coarse (network-based) location Services that cost you money: send SMS messages, directly call phone numbers ...
また、adb の -g
オプションを使用すると、エミュレータまたはテストデバイスにアプリをインストールする際に、すべての権限を自動的に付与できます。
$ adb shell install -g MyApp.apk
権限の適用
権限の目的はシステム機能を要求することだけではありません。アプリが提供するサービスは、カスタム権限を適用して、サービスを使用できる主体を制限できます。カスタム権限の宣言の詳細については、カスタムアプリ権限を定義するをご覧ください。
アクティビティ権限の適用
android:permission
属性を使用してマニフェストの <activity>
タグに適用される権限により、その Activity
を開始できる主体が制限されます。権限は、Context.startActivity()
と Activity.startActivityForResult()
でチェックされます。呼び出し元に必要な権限がない場合は、呼び出しで SecurityException
がスローされます。
サービス権限の適用
android:permission
属性を使用してマニフェストの <service>
タグに適用される権限により、関連する Service
を開始またはバインドできる主体が制限されます。権限は、Context.startService()
、Context.stopService()
、Context.bindService()
でチェックされます。呼び出し元に必要な権限がない場合は、呼び出しで SecurityException
がスローされます。
ブロードキャスト権限の適用
android:permission
属性を使用して <receiver>
タグに適用される権限により、関連する BroadcastReceiver
にブロードキャストを送信できる主体が制限されます。権限は、Context.sendBroadcast()
が返された後、送信されたブロードキャストを指定されたレシーバにシステムが配信しようとしたときにチェックされます。したがって、権限エラーが発生しても呼び出し元に例外はスローされません。単に Intent
が配信されないだけです。
同様に、Context.registerReceiver()
に権限を与えることにより、プログラムで登録されたレシーバにブロードキャストを送信できる主体を制限できます。逆に、Context.sendBroadcast()
を呼び出す際に権限を与えて、ブロードキャストを受信できるブロードキャスト レシーバを制限することもできます。
ブロードキャストの受信側と送信側の両方で権限が必要とされる場合があります。その場合、関連するターゲットにインテントが配信されるためには、両方の権限チェックに合格する必要があります。詳細については、権限の設定によるブロードキャストの制限をご覧ください。
コンテンツ プロバイダ権限の適用
android:permission
属性を使用して <provider>
タグに適用される権限により、ContentProvider
内のデータにアクセスできる主体が制限されます(コンテンツ プロバイダでは、後述の URI 権限と呼ばれる追加の重要なセキュリティ機能を使用できます)。他のコンポーネントと異なり、2 つの権限属性を個別に設定できます。android:readPermission
はプロバイダから読み取りを行う主体を制限し、android:writePermission
は書き込みを行う主体を制限します。プロバイダが読み取りと書き込みの両方の権限で保護されている場合、書き込み権限だけを持っていても、プロバイダの情報を読み取ることはできません。
権限がチェックされるのは、最初にプロバイダを取得するとき(いずれかの権限を持っていないと SecurityException
がスローされます)と、プロバイダでオペレーションを実行するときです。ContentResolver.query()
を使用するには読み取り権限が必要です。ContentResolver.insert()
、ContentResolver.update()
、ContentResolver.delete()
を使用するには書き込み権限が必要です。いずれの場合も、必要な権限を持っていなければ、呼び出しで SecurityException
がスローされます。
URI 権限
これまでに説明した標準的な権限システムは、コンテンツ プロバイダで使用するには不十分であることがままあります。コンテンツ プロバイダは読み取りおよび書き込み権限で自身を保護する必要がありますが、一方、コンテンツ プロバイダの直接クライアントは、特定の URI を他のアプリに渡して、それらのアプリが URI を処理できるようにしなくてはなりません。
その典型的な例は、メールアプリの添付ファイルです。メールはユーザーの機密データであるため、メールへのアクセスは権限で保護する必要があります。しかし、画像添付ファイルの URI がイメージ ビューアに渡されても、イメージ ビューアにはすべてのメールにアクセスする権限を保持する理由がないため、添付ファイルを開く権限がありません。
この問題の解決策は、URI ごとの権限です。アクティビティを開始するときまたは結果をアクティビティに返すときに、呼び出し元は Intent.FLAG_GRANT_READ_URI_PERMISSION
と Intent.FLAG_GRANT_WRITE_URI_PERMISSION
の両方またはいずれかを設定できます。これにより、インテントに対応するコンテンツ プロバイダ内のデータにアクセスする権限の有無にかかわらず、インテント内の特定のデータの URI にアクセスする権限が受信側アクティビティに付与されます。
この仕組みによって、ユーザー操作(添付ファイルの開封や連絡先リストからの選択など)に対し臨機応変にきめ細かい権限を付与できる一般的な機能スタイルモデルが利用可能になります。この仕組みは、アプリが要求する権限を、アプリの動作に直接関連するものだけに制限するうえで非常に重要です。
アプリ内で他のアプリが実行を請け負う最も安全な実装を構築するには、この方法できめ細かい権限を使用し、android:grantUriPermissions
属性または <grant-uri-permissions>
タグでアプリが権限をサポートすることを宣言する必要があります。
詳細については、Context.grantUriPermission()
、Context.revokeUriPermission()
、Context.checkUriPermission()
メソッドを参照してください。
その他の権限の適用
サービスを呼び出すとき、任意のきめ細かい権限を適用できます。これは Context.checkCallingPermission()
メソッドで行います。目的の権限文字列を指定して呼び出しを行うと、実行された呼び出しプロセスに権限が付与されたかどうかを示す整数値が返されます。この方法は、別のプロセスからの呼び出しを実行する場合にのみ使用できることに注意してください。このような呼び出しは、一般的にはサービスから発行された IDL インターフェースを介して行いますが、別のプロセスに固有の他の方法で行うこともあります。
有用な権限のチェック方法は他にもいくつかあります。別のプロセスのプロセス ID(PID)がある場合は、Context.checkPermission()
メソッドを使用して、その PID に対する権限を確認できます。別のアプリのパッケージ名がある場合は、PackageManager.checkPermission()
メソッドを使用して、そのパッケージに特定の権限が付与されているかどうかを確認できます。
新しい権限を自動的に付与する
時間の経過に伴って、プラットフォームに新たな制限が追加されることがあります。たとえば、アプリが特定の API を使用するために、以前は不要だった権限をリクエストすることが必要になる場合などです。既存のアプリはそうした API に自由にアクセスできると想定しているので、Android は、新しいプラットフォーム バージョンでアプリが失敗することを避けるために、アプリのマニフェストに新しい権限のリクエストを適用する(それによってアプリが権限を継承できるようにする)ことがあります。Android は、targetSdkVersion
属性に指定された値に基づいて、アプリに権限が必要かどうかを判断します。権限が追加されたバージョンよりもこの値が小さければ、Android は権限を追加します。
たとえば、共有ストレージ領域へのアクセスを制限するため、最初に API レベル 19 で READ_EXTERNAL_STORAGE
権限が適用されたとします。アプリの
targetSdkVersion
が 18 以下であれば、Android の新しいバージョンで、この権限がアプリに追加されます。
注意: アプリに自動的に権限が追加された場合、実際にはアプリにその権限が不要だったとしても、Google Play のアプリ情報には追加された権限が表示されます。このような状況を避けて不要なデフォルトの権限を削除するには、
targetSdkVersion
を常に最新の(最大の)値に更新します。各リリースで追加された権限は、Build.VERSION_CODES
のドキュメントで確認できます。
参考情報
- アプリの権限をリクエストする: アプリの権限をリクエストするための入門ガイド。
- 機能要件を伴う権限: 一部の権限をリクエストしたとき、対応するハードウェアまたはソフトウェアの機能を持つデバイスにアプリが暗黙的に制限される仕組みに関する情報。
-
<uses-permission>
: アプリに必要な権限を宣言するマニフェスト タグの API リファレンス。 - デバイスの互換性: さまざまなタイプのデバイスでの Android の動作、デバイスごとにアプリを最適化する方法、各種デバイスでアプリの利用を制限する方法に関する情報。
- Android セキュリティの概要: Android プラットフォームのセキュリティ モデルに関する詳細な説明。
- "Mother, May I?" Asking for Permissions: Android Dev Summit 2015 のこの動画は、権限をリクエストする際のおすすめの方法について説明しています。
- Android M Permissions: Google I/O 2015 のこの動画は、Android 6.0 で権限モデルに加えられた変更について説明しています。