1. 簡介
在 Android 12 (API 級別 31) 以上版本中,使用者可以控制要授予應用程式的位置精確度。在舊版 Android 中,系統會根據應用程式要求 ACCESS_FINE_LOCATION
權限或 ACCESS_COARSE_LOCATION
權限,間接控制位置精確度。
本程式碼研究室將針對目標 SDK 31 以上版本的應用程式,提供指引與最佳做法,以要求位置存取權。
必要條件
- Android 開發經驗
- 熟悉活動和權限。
- 具備如何要求應用程式權限的先備知識
- 具備如何要求位置存取權的先備知識
學習目標
- 如何在 Android S 中要求位置存取權
- 如何實作最佳位置要求流程,以利使用者授予應用程式精確位置存取權
用語
精確位置:ACCESS_FINE_LOCATION
權限的位置精細程度。
概略位置:ACCESS_COARSE_LOCATION
權限的位置精細程度。
涵蓋的 API
2. 要求 ACCESS_FINE_LOCATION 權限
新版 UI 流程
我們先來看看新版 UI,瞭解位置精確度的變化。
下圖 1a 和圖 1b 顯示了應用程式未獲得 ACCESS_FINE_LOCATION
或 ACCESS_COARSE_LOCATION
權限時,顯示的權限對話方塊。
圖 1a:已選取「精確位置」 圖 1b:已選取「概略位置」
下圖 2a 顯示應用程式在使用期間獲得 ACCESS_COARSE_LOCATION
權限時顯示的權限升級對話方塊。如果使用者在上一個畫面中為概略位置選取「使用應用程式時」,將會顯示此對話方塊 (如圖 1b 所示)。
圖 2a
下圖 2b 顯示了應用程式獲得目前工作階段的 ACCESS_COARSE_LOCATION
權限時,隨即顯示的權限升級對話方塊。如果使用者在上一個畫面中選取「僅允許這一次」,就會顯示此對話方塊 (如圖 1b 所示)。
圖 2b
3. 程式碼執行
在應用程式資訊清單中宣告位置存取權
如要要求 ACCESS_FINE_LOCATION
,系統將要求應用程式宣告應用程式資訊清單中的 ACCESS_FINE_LOCATION
和 ACCESS_COARSE_LOCATION
。否則,系統會忽略要求,也不會授予應用程式任何權限。
<manifest ... >
<!-- Required when requesting precise location access on Android 12 (API level 31) and higher. -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>
要求 ACCESS_FINE_LOCATION 權限
MyActivity.kt (Kotlin)
when {
ContextCompat.checkSelfPermission(
CONTEXT,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED -> {
// You can use the API that requires the permission.
performAction(...)
}
shouldShowRequestPermissionRationale(...) -> {
// In an educational UI, explain to the user why your app requires this
// permission for a specific feature to behave as expected. In this UI,
// include a "cancel" or "no thanks" button that allows the user to
// continue using your app without granting the permission.
showInContextUI(...)
}
else -> {
// Ask for both the ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions.
requestPermissions(CONTEXT,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION),
REQUEST_CODE)
}
}
MyActivity.java (Java)
if (ContextCompat.checkSelfPermission(
CONTEXT, Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED) {
// You can use the API that requires the permission.
performAction(...);
} else if (shouldShowRequestPermissionRationale(...)) {
// In an educational UI, explain to the user why your app requires this
// permission for a specific feature to behave as expected. In this UI,
// include a "cancel" or "no thanks" button that allows the user to
// continue using your app without granting the permission.
showInContextUI(...);
} else {
// Ask for both the ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions.
requestPermissions(CONTEXT,
new String[] { Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION },
REQUEST_CODE);
}
處理回應
MyActivity.kt (Kotlin)
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
REQUEST_CODE -> {
// If the request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty()) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// ACCESS_FINE_LOCATION is granted
} else if (grantResults[1] ==
PackageManager.PERMISSION_GRANTED) {
// ACCESS_COARSE_LOCATION is granted
}
} else {
// Explain to the user that the feature is unavailable because
// the feature requires a permission that the user has denied.
// At the same time, respect the user's decision. Don't link to
// system settings in an effort to convince the user to change
// their decision.
}
return
}
// Add other 'when' lines to check for other
// permissions this app might request.
else -> {
// Ignore all other requests.
}
}
}
MyActivity.java (Java)
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
// If the request is cancelled, the result arrays are empty.
if (grantResults.length > 0) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// ACCESS_FINE_LOCATION is granted
} else if (grantResults[1] ==
PackageManager.PERMISSION_GRANTED) {
// ACCESS_COARSE_LOCATION is granted
}
} else {
// Explain to the user that the feature is unavailable because
// the feature requires a permission that the user has denied.
// At the same time, respect the user's decision. Don't link to
// system settings in an effort to convince the user to change
// their decision.
}
return;
}
// Other 'case' lines to check for other
// permissions this app might request.
}
}
4. 僅要求 ACCESS_COARSE_LOCATION 權限
圖 4 顯示應用程式僅要求 ACCESS_COARSE_LOCATION
權限時顯示的權限對話方塊。
圖 4
如果只要使用概略位置存取權,應用程式僅需在每個步驟中宣告及處理概略權限。
5. 位置資訊設定
下圖 5 顯示新的位置存取權設定。提供新的切換按鈕,讓使用者控制應用程式是否能存取精確位置或概略位置。
圖 5
6. 目標 SDK 30 以下版本的應用程式
目標 SDK 30 以下版本的應用程式無法檢視新的位置精確度選項 (精確/概略)。
7. 恭喜!
您已瞭解如何在 Android 12 中要求位置存取權,並成功探索數個位置存取權的關鍵要素!
您現在可以根據應用程式需求,針對不同用途要求位置存取權。
進一步瞭解位置資訊: