1. 歡迎
簡介
應用程式權限可用於提供對應用程式沙箱以外的資料和功能的存取權。還能夠讓應用程式存取網際網路、裝置位置及相機等內容,增強應用程式功能。
若要使用這些功能,您必須要求使用者提供權限。本程式碼研究室會逐步引導您新增執行階段權限,以及檢查是否授予權限。
軟硬體需求
- 最新版本的 Android Studio。
須知事項
- 如 Kotlin 新手上路課程 所述
- 基本 Android 開發技能,如同 使用 Kotlin 開發 Android 應用程式 所述
課程內容
- 如何在 Android 資訊清單中新增權限。
- 如何要求權限。
- 如何處理權限遭接受及遭拒的情況。
- 如何確認是否已授予權限。
建構內容
您可以製作會要求相機權限的應用程式。您將導入應用程式的權限部分,而非相機部分。
2. 建立 Android Studio 專案
- 開始新的 Android Studio 專案。
- 選擇「Empty Activity」。
- 將專案命名為「Permissions Codelab」,並將語言設為 Kotlin。
3. 設定代碼
- 將下列依附元件的最新版本加入應用程式層級
build.gradle
檔案中。這些方法可讓您按程式碼研究室的後續說明來使用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
}
}
- 再按綠色鐵鎚按鈕即可開始建構。這項操作會產生名為
ActivityMainBinding
的繫結類別,供您稍後使用ViewBinding
。
- 請前往
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
類別底下,新增擴充功能函式,以便在程式碼研究室中顯示 Snackbars。
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. 在資訊清單中新增權限
首先,您必須使用 <uses-permission>
標記在 Android manifest
中宣告您的權限。
您所要求的權限有時還需要其他要求。在此情況下,除非裝置設有相機,否則無法使用相機應用程式。因此您必須將 <uses-feature>
標記加入資訊清單。
- 在
AndroidManifest.xml
檔案中,將相機權限新增至<application>
標記上方。
<uses-permission android:name="android.permission.CAMERA" />
5. 建立權限啟動器
於 MainActivity.kt
,請建立 val
呼叫 requestPermissionLauncher
並複製這段程式碼。在接下來的幾個重點中,我們會在這裡細分。
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
)
}
}
}
- 設定
when
陳述式來涵蓋以下三種情況:已獲得權限、應用程式是否應顯示要求權限原因,以及是否提出過要求。
when {
ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
}
ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.CAMERA
) -> {
}
else -> {
}
}
- 如果應用程式授予權限,請顯示 Snackbar,並公告。
ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
layout.showSnackbar(
view,
getString(R.string.permission_granted),
Snackbar.LENGTH_INDEFINITE,
null
) {}
}
- 如果
shouldShowRequestPermissionRationale()
傳回 true,則顯示使用者介面,進一步說明該功能需要特定權限的原因,並讓使用者得以透過使用者介面接受/拒絕權限。
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. 摘要
這樣就可以了!本程式碼研究室會說明如何新增執行階段權限,並可用於位置、網路、媒體等權限!