1. ようこそ
はじめに
アプリの権限は、アプリのサンドボックスによって提供される以外のデータと機能へのアクセスを提供するために使用されます。インターネット、デバイスの位置情報、カメラなどへのアクセスを許可することで、アプリの機能を強化できます。
こうした機能を使用するには、ユーザーに権限をリクエストする必要があります。この Codelab では、実行時の権限の追加と権限の有無の確認に必要な手順について説明します。
必要なもの
- Android Studio の最新バージョン。
前提となる知識
- Kotlin(Kotlin ブートキャンプで説明されているレベル)
- Android 開発の基本的なスキル(Kotlin による Android アプリの開発で説明されているレベル)
学習内容
- Android マニフェストに権限を追加する方法
- 権限をリクエストする方法
- 権限が許可された場合と拒否された場合の対応方法
- 権限が付与されたかどうかを確認する方法
作成するアプリの概要
カメラへのアクセス権限をリクエストするアプリを作成します。アプリの権限に関する処理は実装しますが、カメラに関する処理は実装しません。
2. Android Studio プロジェクトを作成する
- 新しい Android Studio プロジェクトを開始します。
- [Empty Activity] を選択します。
- プロジェクトの名前を「Permissions Codelab」とし、言語を「Kotlin」に設定します。
3. コードをセットアップする
- 以下の最新バージョンの依存関係をアプリレベルの
build.gradle
ファイルに追加します。追加すると、この Codelab で後述するActivity
ライブラリを使用できます。
implementation "androidx.activity:activity-ktx:1.2.2"
implementation "androidx.fragment:fragment-ktx:1.3.2"
- android ブロックで
viewBinding
ビルド オプションを true に設定して、ViewBinding を有効にします。
android {
...
buildFeatures {
viewBinding true
}
}
- 緑色のハンマーボタンをクリックしてビルドします。これにより、後で
ViewBinding
に使用するActivityMainBinding
というバインディング クラスが生成されます。
activity_main.xml
ファイルに移動し、コードを次のコードに置き換えます。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Request Permissions"
android:onClick="onClickRequestPermission"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
- 次の文字列を
strings.xml
ファイルに追加します。
<string name="app_name">Permissions Codelab</string>
<string name="permission_required">Camera access is required to display the camera preview.</string>
<string name="ok">OK</string>
<string name="permission_granted">Permission is granted. You can use the camera now.</string>
MainActivity.kt
のonCreate()
メソッドの上に、レイアウトとViewBinding
の変数を定義します。
private lateinit var layout: View
private lateinit var binding: ActivityMainBinding
onCreate()
メソッドのコードを次のコードで置き換えます。このコードは、バインディングを初期化し、ビューを表すval
を作成してバインディングのルートに設定し、レイアウトをバインディングのmainLayout
に設定します。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
layout = binding.mainLayout
setContentView(view)
}
- ファイルの下部にある
MainActivity
クラスの下に、Codelab 全体を通してスナックバーを表示する拡張関数を追加します。
fun View.showSnackbar(
view: View,
msg: String,
length: Int,
actionMessage: CharSequence?,
action: (View) -> Unit
) {
val snackbar = Snackbar.make(view, msg, length)
if (actionMessage != null) {
snackbar.setAction(actionMessage) {
action(this)
}.show()
} else {
snackbar.show()
}
}
4. マニフェストに権限を追加する
まず必要なのは、Android manifest
で <uses-permission>
タグを使って権限の使用を宣言することです。
リクエストする権限によっては、その他の要件がある場合もあります。この場合、デバイスにカメラが搭載されていない限り、カメラアプリを使用できません。このため、マニフェストに <uses-feature>
タグも追加します。
AndroidManifest.xml
ファイルの<application>
タグの上にカメラの権限を追加します。
<uses-permission android:name="android.permission.CAMERA" />
5. 権限ランチャーを作成する
MainActivity.kt
で、requestPermissionLauncher
という val
を作成し、次のコードをコピーします。このコードの内容を以下の箇条書きに分けて説明します。
private val requestPermissionLauncher =
registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
Log.i("Permission: ", "Granted")
} else {
Log.i("Permission: ", "Denied")
}
}
requestPermissionLauncher
にregisterForActivityResult
を設定し、ActivityResultContracts.RequestPermission()
を渡します。
private val requestPermissionLauncher =
registerForActivityResult(
ActivityResultContracts.RequestPermission())
- 権限が許可されたケース、許可されなかったケースを処理するコールバックを追加します。この例では、結果をログに記録しています。
{ isGranted: Boolean ->
if (isGranted) {
Log.i("Permission: ", "Granted")
} else {
Log.i("Permission: ", "Denied")
}
}
6. 権限をリクエストする
onClickRequestPermission(view: View)
という関数を作成し、このコードをコピーします。このコードの内容を以下の箇条書きに分けて説明します。
fun onClickRequestPermission(view: View) {
when {
ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
layout.showSnackbar(
view,
getString(R.string.permission_granted),
Snackbar.LENGTH_INDEFINITE,
null
) {}
}
ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.CAMERA
) -> {
layout.showSnackbar(
view,
getString(R.string.permission_required),
Snackbar.LENGTH_INDEFINITE,
getString(R.string.ok)
) {
requestPermissionLauncher.launch(
Manifest.permission.CAMERA
)
}
}
else -> {
requestPermissionLauncher.launch(
Manifest.permission.CAMERA
)
}
}
}
- すでに権限が付与されている場合、アプリがリクエスト権限の根拠を示すべきと判断した場合、まだ権限がリクエストされていない場合、以上 3 つのケースを扱う
when
ステートメントを設定します。
when {
ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
}
ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.CAMERA
) -> {
}
else -> {
}
}
- 権限が付与されている場合は、その旨を知らせるスナックバーを表示します。
ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
layout.showSnackbar(
view,
getString(R.string.permission_granted),
Snackbar.LENGTH_INDEFINITE,
null
) {}
}
shouldShowRequestPermissionRationale()
が true を返す場合は、その機能が特定の権限を必要とする理由を詳しく説明する UI を表示し、ユーザーが UI から権限を承認または拒否できるようにします。
ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.CAMERA
) -> {
layout.showSnackbar(
view,
getString(R.string.permission_required),
Snackbar.LENGTH_INDEFINITE,
getString(R.string.ok)
) {
requestPermissionLauncher.launch(
Manifest.permission.CAMERA
)
}
}
- 上記以外の場合は、権限をリクエストします。
else -> {
requestPermissionLauncher.launch(
Manifest.permission.CAMERA
)
}
7. まとめ
これで完了です。この Codelab では、実行時の権限を追加する方法について説明しています。この方法は、位置情報、ネットワーク、メディアなどに関する権限に使用できます。