【Android 入門開發實戰:口罩地圖】獲取位置權限
【Android 入門開發實戰:口罩地圖】線上免費講義課程目錄
獲取使用者位置權限,除了要在 AndroidManifest.xml 宣告外,因為被列屬為危險權限,從 Android 6 (SDK 23)以上,需要特別額外跟使用詢問獲取,否則會因權限不足,而造成 APP 閃退。詳細權限級別,可以查閱官網文件: Manifest.permission。
獲取 APP 權限方法
獲取 APP 權限,主要分成這四個部分。
checkSelfPermission
檢查我們的APP,是否獲得權限
shouldShowRequestPermissionRationale
是否要顯示更多說明解釋為何此權限對話視窗。收到 true,代表需要跟使用者顯示更多說明解釋為何此權限對話視窗,收到 false,代表不需額外顯示給使用者說明。
使用情境:
- 第一次詢問權限,這個值會收到 false。
- 第一次詢問,用戶選擇「拒絕」,這個值會收到 true。則需要顯示客制對話視窗,在視窗中解釋為何需要此權限。
- 用戶允許權限後或是選擇「拒絕且不在詢問」後,這個值會收到 false。
requestPermissions
要求用戶給我們APP使用權限
onRequestPermissionsResult
覆寫此方法,要求權限後,會收到用戶決定是否給權限的結果 CallBack
AndroidManifest.xml
獲取位置權限,需要先在 AndroidManifest.xml 裡,加入此宣告。位置權限有兩種,一個是概略位置存取權(ACCESS_COARSE_LOCATION)和另一個精確位置存取(ACCESS_FINE_LOCATION),擇一即可,我們選擇精確定位權限。
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
MapActivity.kt
我們先新開一個空白的 Activity 頁面,檔名為 MapActivity,並在 AndroidManifest.xml 裡將啟動載入Activity,更改為此 Activity。
<activity android:name=".MapActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
檢查有無權限
透過 checkSelfPermission 方法,檢查有無精準位置(ACCESS_FINE_LOCATION)權限,若沒有則詢問使用者要求獲取權限,若獲得 locationPermissionGranted 設定為 true。
private var locationPermissionGranted = false
...
...
...
private fun getLocationPermission() {
//檢查權限
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
) {
//已獲取到權限
Toast.makeText(this, "已獲取到位置權限,可以準備開始獲取經緯度", Toast.LENGTH_SHORT).show()
locationPermissionGranted = true
//todo checkGPSState()
} else {
//詢問要求獲取權限
requestLocationPermission()
}
}
詢問要求獲取權限
private fun requestLocationPermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(
this, Manifest.permission.ACCESS_FINE_LOCATION
)
) {
AlertDialog.Builder(this)
.setMessage("此應用程式,需要位置權限才能正常使用")
.setPositiveButton("確定") { _, _ ->
ActivityCompat.requestPermissions(
this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_LOCATION_PERMISSION
)
}
.setNegativeButton("取消") { _, _ -> requestLocationPermission() }
.show()
} else {
ActivityCompat.requestPermissions(
this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_LOCATION_PERMISSION
)
}
}
處理權限 CallBack
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<out String>, grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
REQUEST_LOCATION_PERMISSION -> {
if (grantResults.isNotEmpty()) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//已獲取到權限
locationPermissionGranted = true
//todo checkGPSState()
} else if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
if (!ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.ACCESS_FINE_LOCATION
)
) {
//權限被永久拒絕
Toast.makeText(this, "位置權限已被關閉,功能將會無法正常使用", Toast.LENGTH_SHORT).show()
AlertDialog.Builder(this)
.setTitle("開啟位置權限")
.setMessage("此應用程式,位置權限已被關閉,需開啟才能正常使用")
.setPositiveButton("確定") { _, _ ->
val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivityForResult(intent, REQUEST_LOCATION_PERMISSION)
}
.setNegativeButton("取消") { _, _ -> requestLocationPermission() }
.show()
} else {
//權限被拒絕
Toast.makeText(this, "位置權限被拒絕,功能將會無法正常使用", Toast.LENGTH_SHORT).show()
requestLocationPermission()
}
}
}
}
}
}
處理設定回來 CallBack
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQUEST_LOCATION_PERMISSION -> {
getLocationPermission()
}
}
}
輸出結果
第一次呈現詢問畫面
若在第一次詢問,選擇「拒絕」,則會出現,我們自定義的對話視窗,可以在這個視窗跟用戶說明為何需要權限。
若是選擇「拒絕且不在詢問」,將不會在出現詢問視窗
參考資料
Build location-aware apps
https://developer.android.com/training/location
Request App Permissions
https://developer.android.com/training/permissions/requesting
permissions API reference page
https://developer.android.com/reference/android/Manifest.permission#ACCESS_FINE_LOCATION
Location Data
https://developers.google.com/maps/documentation/android-sdk/location
Select Current Place and Show Details on a Map
https://developers.google.com/maps/documentation/android-sdk/current-place-tutorial
程式碼範例
範例名稱:獲取位置權限
開發人員:HKT (侯光燦)
程式語言:Kotlin
開發環境:Android Studio 4.1.2 & Android 11 & Kotlin 1.4.30
授權範圍:使用時必須註明出處且不得為商業目的之使用
範例下載點:點我下載