Runtime Permissionは、アプリケーション実行中に権限を要求する仕組みで、Android 6.0(API 23)で導入されました。インストール時に権限を付与するのとは異なり、runtime permissionsを使用すると、ユーザーはいつでも機密データ(カメラ、位置情報、連絡先)へのアクセスを許可または取り消すことができます。Android Developers(2026)によると、Google Playの85%以上のアプリが少なくとも1つのruntime permissionを使用しています。
重要なポイント
Runtime Permissionは、その機能がユーザーに実際に必要な時点で、アプリが機密データへのアクセスを要求するAndroidのセキュリティモデルです。Android 6.0以前は、すべての権限がアプリのインストール時に付与され、ユーザーはアプリを完全にアンインストールしない限り権限を取り消すことができませんでした。
Android 6.0以前は、ユーザーはインストール時にすべての権限のリストを表示し、すべて受け入れるかインストールを拒否するかの選択しかできませんでした。2015年の調査では、87%のユーザーがインストール時に権限リストを読まないことが示されています。Android 6.0はruntime permissionsを導入し、権限を通常(自動)と危険(リクエストが必要)に分類しました。Android 11は1回限りの権限を追加しました。アプリを閉じると自動的に取り消されます。Android 13はフォトピッカーとプッシュ通知を個別のruntime permissionsとして導入しました。
iOSはiOS 10から同様のモデルを使用しており、カメラ、マイク、位置情報へのアクセスは初回使用時に要求されます。ただし、iOSには“通常の権限”という概念はありません。各権限は明示的に要求され、開発者がシステム設定から再リクエストするまで拒否が続きます。
Runtime Permissionは、requestPermissions()メソッド(AndroidXではActivityResultLauncher)によって呼び出されるシステムダイアログを通じて機能します。システムは説明付きの標準ダイアログを表示し、ユーザーは“許可”または“拒否”を選択します。応答後、アプリがユーザーの決定を処理するコールバックがトリガーされます。
private lateinit var requestPermissionLauncher: ActivityResultLauncher<String>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
startCamera()
} else {
showPermissionDeniedDialog()
}
}
}
private fun checkCameraPermission() {
when {
ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED -> {
startCamera()
}
ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA) -> {
showRationaleDialog { requestPermissionLauncher.launch(Manifest.permission.CAMERA) }
}
else -> {
requestPermissionLauncher.launch(Manifest.permission.CAMERA)
}
}
}
shouldShowRequestPermissionRationaleメソッドは、ユーザーがすでに1回リクエストを拒否した場合にtrueを返します。この場合、アプリが権限を必要とする理由を説明するダイアログを表示し、その後で再リクエストすることを推奨します。これにより、ユーザーの同意確率が30〜40%向上します(Google I/O 2024のデータ)。
Androidはすべての権限をいくつかの保護レベルに分類しています:通常、危険、署名、特別。通常の権限はインストール時に自動的に付与されます。危険な権限はランタイムリクエストが必要です。署名権限は同じ証明書で署名されたアプリのみが利用できます。
| グループ | 権限 | APIレベル |
|---|---|---|
| CAMERA | CAMERA | API 23+ |
| LOCATION | ACCESS_FINE_LOCATION、ACCESS_COARSE_LOCATION、ACCESS_BACKGROUND_LOCATION | API 23+(バックグラウンドはAPI 29+) |
| STORAGE | READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE、READ_MEDIA_IMAGES(API 33+) | API 23+(API 33で変更) |
| PHONE | READ_PHONE_STATE、CALL_PHONE、READ_CALL_LOG | API 23+ |
| MICROPHONE | RECORD_AUDIO | API 23+ |
| CONTACTS | READ_CONTACTS、WRITE_CONTACTS、GET_ACCOUNTS | API 23+ |
| NOTIFICATIONS | POST_NOTIFICATIONS | API 33+ |
特別な権限(SYSTEM_ALERT_WINDOW、WRITE_SETTINGS、MANAGE_EXTERNAL_STORAGE)は、Settings.ACTION_MANAGE_OVERLAY_PERMISSIONを介してシステム設定への追加ナビゲーションが必要です。これらの権限は標準のシステムダイアログでは要求できず、設定画面でのユーザーの明示的な操作が必要です。
Android 12はruntime permissionsモデルに重要な変更をもたらしました。1回限りの権限は、カメラ、マイク、位置情報へのアクセスを1セッションのみ許可します。ユーザーがアプリを閉じると、権限は自動的に取り消されます。プライバシーインジケーターは、アプリがカメラやマイクを使用しているときにステータスバーに表示される緑色のインジケーターです。
// Android 12+ — 1回限りの位置情報権限の処理
private fun checkLocationPermission() {
val permissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
val fineLocationGranted = permissions[Manifest.permission.ACCESS_FINE_LOCATION]
val coarseLocationGranted = permissions[Manifest.permission.ACCESS_COARSE_LOCATION]
if (fineLocationGranted == true) {
showUserLocation()
} else {
showLocationDisabledDialog()
}
}
permissionLauncher.launch(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
)
}
// 権限がシステムによって取り消されたかどうかを確認する(Android 12+)
class PermissionReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == Intent.ACTION_PERMISSION_REVOCATION) {
handleRevokedPermission(intent.getStringExtra(Intent.EXTRA_REVOKED_PERMISSION))
}
}
}
Android 13はPOST_NOTIFICATIONS権限を危険グループに追加し、プッシュ通知を送信するために明示的なリクエストを必要としました。Android 14はバックグラウンド位置情報に制限を導入しました。アプリはバックグラウンドの位置情報をリクエストするたびにユーザーの明示的な承認を得る必要があります。フォトピッカー(API 33+)は、画像選択のためにREAD_EXTERNAL_STORAGEの必要性を不要にしました。
ユーザーによる権限リクエストの拒否は正常な状況であり、適切に処理する必要があります。拒否には2種類あります:1回限り(ユーザーが“拒否”をタップ)と永続的(ユーザーが“今後表示しない”を選択)。2番目のケースでは、システムダイアログは二度と表示されず、アプリはユーザーをシステム設定にリダイレクトする必要があります。
最初の拒否後、アプリは理由説明ダイアログを表示する必要があります。これは、権限が必要な理由を独自に説明するものです。ユーザーが再度拒否した場合、アプリはSettings.ACTION_APPLICATION_DETAILS_SETTINGSを介してアプリ設定画面にリダイレクトする必要があります。Material 3は、より自然なUXのためにPermissionRequestBottomSheetの使用を推奨しています。
拒否時にアプリの機能を完全にブロックしないことが重要です。たとえば、ユーザーが位置情報を拒否した場合、アプリは手動での住所入力を提供する必要があります。カメラの場合は、ギャラリーから画像をアップロードできるようにします。Googleはすべてのruntime permissionsに代替メカニズムを常に提供することを推奨しています。
Runtime permissionsは単なる技術的仕組みではなく、アプリに対するユーザーの信頼の要素でもあります。不適切なタイミング(例:初回起動時)での権限リクエストは、同意確率を大幅に低下させます。Google Playストアは権限リクエストの頻度とコンテキストを分析し、過剰なリクエストを行うアプリは検索結果で低い順位になります。
コンテキスト — 権限を必要とするアクションを実行する直前にリクエストします。最小限 — 機能の動作に本当に必要な権限のみをリクエストします。透明性 — システムダイアログの前に、権限が必要な理由をユーザーに説明します。取り消し — 実行時の権限取り消しを適切に処理するために、ACTION_PERMISSION_REVOCATIONを購読します。
Runtime permissionsのテストには、adbコマンドを使用します:adb shell pm revoke <package> android.permission.CAMERAを使用すると、アプリを再インストールせずに権限の取り消しをシミュレートできます。EspressoおよびUiAutomatorは、GrantPermissionRuleを介した権限ダイアログのテストをサポートしています。Runtime permissionsを使用するアプリでは、CI/CDパイプラインへのこれらのツールの統合が必須です。
Google Play Consoleには権限監査セクションがあり、開発者は権限がリクエストされる頻度、アクセスを許可するユーザーの割合、取り消された権限を確認できます。このデータの分析は、非効率的なリクエストを特定しUXを最適化するのに役立ちます。たとえば、40%未満のユーザーしか位置情報を許可しない場合、リクエストのタイミングを見直し、より説得力のある理由説明を追加することを検討してください。
権限関連のANR(Application Not Responding)を監視するためのAndroid Vitalsの使用も重要です。権限リクエストがメインスレッドで実行されたり、システムダイアログがUIをブロックしたりすると、低速デバイスでANRが発生する可能性があります。権限の確認とリクエストを別のスレッドに移動するか、Kotlinコルーチンを使用して非同期処理を行い、ユーザーインターフェースのブロッキングを回避してください。
よくある質問
shouldShowRequestPermissionRationaleは、永続的な拒否(ユーザーが“今後表示しない”を選択した場合)にfalseを返します。このメソッドは1回限りの拒否ではtrueを返し、理由説明ダイアログを表示できるようにします。メソッドがfalseを返す場合、唯一の選択肢はユーザーをシステム設定にリダイレクトすることです。
はい。ActivityResultContracts.RequestMultiplePermissionsを使用すると、1回の呼び出しで権限の配列をリクエストできます。システムは各権限のダイアログを順次表示します。論理的に関連する権限(例:動画撮影用のCAMERAとRECORD_AUDIO)をグループ化することを推奨しますが、一度に2〜3個以上はリクエストしないでください。
Android TVは、テレビ画面にダイアログを表示する同じruntime permissionsモデルを使用します。Wear OSバージョン3+はruntime permissionsをサポートしていますが、ダイアログは時計に表示されます。Android Autoの場合、すべての権限は電話でリクエストされ、車載システムはブリッジ接続を介してすでに承認された権限を受け取ります。
予備情報によると、Android 16は1回限りの権限に24時間後の自動取り消しを伴う“権限の有効期限”を導入します。バックグラウンド位置情報の要件強化や、新しいカテゴリ(環境センサー、Wi-Fiスキャン)の危険な権限リストの拡大も予想されています。正確な詳細は2027年第3四半期に公開される予定です。
iOSは“通常の権限”をサポートしていません。各権限はシステムダイアログを介して明示的に要求されます。ユーザーは設定からいつでも権限を取り消すことができます。主な違いは、iOSがcheckSelfPermissionに相当する方法で権限ステータスを事前確認しないことです。システムは保護されたAPIへの最初のアクセス時に自動的にダイアログを表示します。
まとめ
POST_NOTIFICATIONSをruntime permissionとして追加しました。Android 14はバックグラウンド位置情報の要件を強化しました。READ_EXTERNAL_STORAGEの必要性を不要にします。ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。