1. 简介
在 Android 12(API 级别 31)及更高版本中,用户可以选择控制要为其应用授予的位置信息精确度。在较低版本的 Android 系统中,位置信息精确度由相应应用是请求 ACCESS_FINE_LOCATION
权限还是 ACCESS_COARSE_LOCATION
权限来隐式控制。
此 Codelab 将为目标 SDK 版本为 31 及更高版本的应用提供请求位置信息权限方面的指导信息和最佳实践。
前提条件
学习内容
- 如何在 Android S 中请求位置信息权限
- 如何实现最佳位置信息请求流程,以便用户向应用授予确切位置信息权限
术语
确切位置:ACCESS_FINE_LOCATION
权限的位置粒度。
大致位置:ACCESS_COARSE_LOCATION
权限的位置粒度。
涵盖的 API
2. 请求 ACCESS_FINE_LOCATION 权限
新版界面流程
我们首先来看一下新版界面,了解位置信息精确度的一些变化。
下面的图 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 中请求位置信息权限,并成功探索了位置信息权限的多个重要组成部分!
现在,您可以针对不同的用例请求位置权限,以满足应用的需求。
详细了解位置信息: