【Kotlin/Android Studio】パーミッション(権限)許可のリクエスト方法!requestPermissions
この記事からわかること
- Android Studio/Kotlinでパーミッション(権限)のリクエスト方法
- requestPermissionsメソッド・checkSelfPermissionメソッドの使い方
- 許可が必要になる機能
- RequestPermission/RequestMultiplePermissionsを使用したパーミッションダイアログの結果取得
index
[open]
\ アプリをリリースしました /
環境
- Android Studio:Narwhal Feature Drop
- Kotlin:2.1.10
- Material3
- AGP:8.9.2
- Gradle:8.11.1
- Mac M1:Sequoia 15.6.1
Androidで機能を使用する権限
Androidアプリからデバイスに組み込まれている機能(カメラや連絡先、Bluetooth機能など)を使用するためには使用する権限を明確に付与しておく必要があります。権限の宣言をしなくても一部機能を利用することもできたりしますが、使う機能によって権限が細分化されているので適切に権限を把握しておく必要があります。
必要となる権限の宣言方法は2種類あります。
- インストール時:Install time
- 実行時:Runtime
これは機能ごとに振られているレベル(Protection level)によって異なります。以下の公式ページにて機能ごとにレベルが載っており、normalならインストール時、dangerousなら実行時に必要になります。
インストール時のパーミッション宣言
normalレベルの機能に関してはインストール時のみの宣言になります。これはプロジェクト内の「AndroidManifest.xml」ファイル内にuses-permissionタグを使用した形式で使用したい機能を記述するだけです。これでユーザーがアプリをインストールした際に自動的にアプリに権限が付与されます。
<uses-permission android:name="android.permission.BLUETOOTH" />
またアプリでインストール時の権限を宣言することで、アプリストアでユーザーがアプリの詳細ページを開いたときに、インストール時の権限に関するお知らせが表示されます。
実行時のパーミッション宣言
dangerousレベルの機能に関してはインストール時と実行時の2箇所での宣言が必要になります。先ほど同様に「AndroidManifest.xml」ファイル内にuses-permissionタグを使用した形式で使用したい機能を記述するのとユーザーが機能を利用しようとした際などにアラートなどを表示し権限の許可を求めるリクエストを送信します。
またこのリクエストの送信についてはAndroid 6.0(API レベル 23)以上から必要になったものなのでそれ以前であればマニフェストファイルへの記載のみで問題ないようです。
権限の許可を求めるリクエストの送信方法
カメラ機能をリクエストするのを例に一度実装方法をまとめていきます。
流れ
- マニフェストファイルへの記述
- コードからパーミッションをチェック
- リクエストを送信
マニフェストファイルへの記述
まずはマニフェストファイル「AndroidManifest.xml」の中に権限を追加しておきます。
<uses-permission android:name="android.permission.CAMERA" />
追加するパーミッションのname部分はManifest.permissionクラスに定義されている定数値を記述すればOKです。
コードからパーミッションをチェック:checkSelfPermission
コードからパーミッションが付与されているか(許可されているか)をチェックします。コードからもManifest.permissionオブジェクトから定数として参照することができます。
ここではcheckSelfPermissionメソッドを使用してパーミッションをチェックします。付与されていればPERMISSION_GRANTEDになります。
- 付与済:PackageManager.PERMISSION_GRANTED
- 未付与:PackageManager.PERMISSION_DENIED
if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "カメラ権限が許可されてないよ", Toast.LENGTH_SHORT).show()
// TODO: - リクエストを送信する処理
} else {
Toast.makeText(this, "カメラ権限の許可OK", Toast.LENGTH_SHORT).show()
}
アプリ初回起動時にはまだ許可されていないのでPERMISSION_DENIEDになります。なので許可されていない場合にリクエストを送信していきます。
Manifestは手打ちしてもimport文が自動で入らないことがあるので上部に以下を追加してください。
import android.Manifest
リクエストを送信:requestPermissions
リクエストを送信する方法は2つあります。registerForActivityResultの方が最新で推奨されているのでそちらを使用すれば良いと思いますが、requestPermissions側の使い方も紹介しておきます。
- requestPermissions
- registerForActivityResult
requestPermissionsメソッドを使用する場合は引数にリクエストを送信したい権限を配列形式で渡します。今回は1つだけですが複数渡すことも可能です。2つ目の引数にはリクエストコードを渡します。これはこのリクエスト処理を識別するためのコードなので適当な数値を渡しておきます。
val permissions = arrayOf(Manifest.permission.CAMERA)
val REQUEST_CODE = 100
requestPermissions(permissions,REQUEST_CODE)
このコードが実行されるとアプリ側で以下のようにアラートが表示されます。
リクエストの結果を受け取る
リクエストの結果はonRequestPermissionsResultメソッドから受け取ることが可能です。引数requestCodeから対象のリクエストコード、grantResultsから許可または拒否された定数を受け取ることが可能です。先ほどのREQUEST_CODEをクラスのプロパティとして定義し直してonRequestPermissionsResultメソッド内からも参照できるようにしておきました。
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == REQUEST_CODE) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 許可された場合
Toast.makeText(this, "許可されました", Toast.LENGTH_SHORT).show()
} else {
// 拒否された場合
Toast.makeText(this, "拒否されました", Toast.LENGTH_SHORT).show()
}
}
}
リクエストを送信:registerForActivityResult
ここからはregisterForActivityResultを使用したリクエスト送信方法を紹介していきます。
RequestPermission:単体
registerForActivityResultの引数にRequestPermissionを渡すことで簡単にパーミッション許可申請ダイアログを表示することができます。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 許可ダイアログを表示
launcher.launch(Manifest.permission.CAMERA)
}
private val launcher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { result ->
// ダイアログの結果で処理を分岐
if (result) {
Toast.makeText(this, "許可されました", Toast.LENGTH_SHORT)
.show()
} else {
Toast.makeText(this, "否認されました", Toast.LENGTH_SHORT)
.show()
}
}
}
RequestMultiplePermissions:複数
複数のパーミッション許可申請ダイアログを表示するにはRequestMultiplePermissionsを指定します。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
launcher.launch(
arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_COARSE_LOCATION
)
)
}
private val launcher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {
it
val camera = it[Manifest.permission.CAMERA] ?: false
val location = it[Manifest.permission.ACCESS_COARSE_LOCATION] ?: false
if (camera && location) {
Toast.makeText(this, "許可されました", Toast.LENGTH_SHORT)
.show()
} else {
Toast.makeText(this, "否認されました", Toast.LENGTH_SHORT)
.show()
}
}
}
Jetpack Composeの場合:rememberLauncherForActivityResult
Jetpack ComposeでUIを実装している場合はrememberLauncherForActivityResultを使用します。画面表示時などに発火させたい場合はLaunchedEffectなどに仕込んでおくと良いです。
val context = LocalContext.current
val launcher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
val fineLocation = permissions[Manifest.permission.ACCESS_FINE_LOCATION] ?: false
val coarseLocation = permissions[Manifest.permission.ACCESS_COARSE_LOCATION] ?: false
if (fineLocation && coarseLocation) {
Toast.makeText(context, "許可されました", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(context, "否認されました", Toast.LENGTH_SHORT).show()
}
}
LaunchedEffect(Unit) {
launcher.launch(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
)
)
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。






