大致位置

该对话框仅涉及大致位置,并且包含三个按钮,它们上下分布
图 1. 当您的应用仅请求 ACCESS_COARSE_LOCATION 时显示的系统权限对话框。

Android 12 基于最近平台对位置权限模型所做的变更,包括后台位置信息权限单次授权。当应用以 Android 12 为目标平台时,用户可以请求应用仅检索大致位置信息,即使应用请求 ACCESS_FINE_LOCATION 运行时权限也是如此。

如果您的应用请求 ACCESS_COARSE_LOCATION 但未请求 ACCESS_FINE_LOCATION,则本页介绍的变更不会带来任何影响。图 1 显示了您的应用以 Android 12 为目标平台且仅请求 ACCESS_COARSE_LOCATION 时显示的面向用户的对话框。

为了更好地尊重用户隐私,建议您仅请求 ACCESS_COARSE_LOCATION。即使您只能访问大致位置信息,也可以满足大多数用例的要求。

如果您的应用以 Android 12 为目标平台并且您请求 ACCESS_FINE_LOCATION 权限,则还必须请求 ACCESS_COARSE_LOCATION 权限。您必须在单个运行时请求中包含这两项权限。如果您尝试仅请求 ACCESS_FINE_LOCATION,则系统会忽略该请求,并在 Logcat 中记录以下错误消息:ACCESS_FINE_LOCATION must be requested with ACCESS_COARSE_LOCATION

用户在大致位置与确切位置之间进行选择

该对话框包含两组选项,它们上下分布
图 2. 当您的应用以 Android 12 为目标平台并且在单个运行时请求中同时请求 ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION 时显示的系统权限对话框。

当您的应用同时请求 ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION 时,系统权限对话框将为用户提供以下新选项:

  • 确切:提供 ACCESS_FINE_LOCATION 权限提供的位置信息精确度。
  • 大致:提供 ACCESS_COARSE_LOCATION 权限提供的位置信息精确度。

图 2 显示该对话框包含这两个新选项的视觉提示,以帮助用户做出选择。用户确定位置信息精确度后,他们可以点按三个按钮中的一个来选择权限授予的时长。这些按钮与搭载 Android 11(API 级别 30)的设备上的位置权限对话框中显示的按钮相同。

在 Android 12 中,用户可以转到系统设置,以设置任何应用的首选位置信息精确度,而不管该应用的目标 SDK 版本是什么。即使您的应用安装在搭载 Android 11 或更低版本的设备上,然后升级到 Android 12,也是如此。如果用户从权限对话框或在系统设置中将应用的位置信息访问权限从确切位置降级到大致位置,则系统会重启应用的进程。因此,遵循有关请求运行时权限的最佳做法特别重要。

用户的选择会影响权限授予

下表显示了系统根据用户在运行时权限对话框中选择的选项向您的应用授予的权限:

确切 大致
仅在使用该应用时允许 ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
仅限这一次 ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
拒绝 无位置权限 无位置权限

如需确定系统已向您的应用授予的权限,请查看权限请求的返回值。您可以在类似于下面的代码中使用 Jetpack 库,也可以使用平台库,在这种情况下,您自行管理权限请求代码

Kotlin

val locationPermissionRequest = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        when {
            permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false) -> {
                // Precise location access granted.
            }
            permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false) -> {
                // Only approximate location access granted.
            } else -> {
                // No location access granted.
            }
        }
    }

// ...

// Before you perform the actual permission request, check whether your app
// already has the permissions, and whether your app needs to show a permission
// rationale dialog. For more details, see Request permissions.
locationPermissionRequest.launch(arrayOf(
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION))

Java

ActivityResultLauncher<String[]> locationPermissionRequest =
    registerForActivityResult(new ActivityResultContracts
        .RequestMultiplePermissions(), result -> {
            Boolean fineLocationGranted = result.getOrDefault(
                    Manifest.permission.ACCESS_FINE_LOCATION, false);
            Boolean coarseLocationGranted = result.getOrDefault(
                    Manifest.permission.ACCESS_COARSE_LOCATION,false);
            if (fineLocationGranted != null && fineLocationGranted) {
                // Precise location access granted.
            } else if (coarseLocationGranted != null && coarseLocationGranted) {
                // Only approximate location access granted.
            } else {
                // No location access granted.
            }
        }
    );

// ...

// Before you perform the actual permission request, check whether your app
// already has the permissions, and whether your app needs to show a permission
// rationale dialog. For more details, see Request permissions.
locationPermissionRequest.launch(new String[] {
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION
});

用户的选择还会影响后台位置信息

如果系统向您的应用授予 ACCESS_BACKGROUND_LOCATION 权限,则用户在位置权限对话框中的选择也适用于后台位置信息。

例如,如果用户向您的应用授予 ACCESS_BACKGROUND_LOCATION 权限,但仅授予在前台访问大致位置信息的权限,则您的应用在后台也只有大致位置信息的访问权限。

升级到确切位置

如果您的应用当前依赖于使用 ACCESS_FINE_LOCATION 权限访问确切位置,则大致位置可能会影响您的应用。

在让用户将应用的访问权限升级到确切位置之前,请考虑应用的用例是否确实需要这一级别的精确度。如果您的应用需要通过蓝牙或 Wi-Fi 将某个设备与附近的设备配对,请考虑使用配套设备配对或新的蓝牙权限,而不是请求 ACCESS_FINE_LOCATION 权限。

如需请求用户将应用的位置信息访问权限从大致位置升级到确切位置,请执行以下操作:

  1. 如有必要,请说明您的应用为何需要获取权限
  2. 再次同时请求 ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION 权限。由于用户已允许系统向您的应用授予大致位置信息访问权限,因此这次系统对话框有所不同,如图 3图 4 所示:
该对话框包含“更改为确切位置”、“仅限这一次”和“拒绝”选项。
图 3. 用户之前选择了大致仅在使用该应用时允许(在图 2 的对话框中)。
该对话框包含“仅限这一次”和“拒绝”选项。
图 4. 用户之前选择了大致仅限这一次(在图 2 的对话框中)。

测试您的应用如何处理大致位置信息

如需评估您是否需要更新您的应用以支持用户可配置的位置信息精确度,请完成本部分中所述的测试。

处理对话框中的大致位置信息请求

对于用户要求在新对话框中让您的应用具有大致位置信息访问权限的请求,如需检查您的应用如何处理此类请求,请执行以下操作:

  1. 同时请求 ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION
  2. 在显示的对话框中(图 2),选择顶部附近的大致,以及底部附近的仅在使用该应用时允许仅限这一次
  3. 检查应用的用例是否仍按预期工作,即使您的应用只有大致位置信息访问权限也是如此。

处理系统设置中的大致位置信息降级

图 5. 系统设置中应用的位置权限屏幕现在包含使用确切位置。此选项独立于看起来更靠近屏幕顶部的位置访问权限设置。

对于用户要求在系统设置中将您的应用的位置信息访问权限从确切位置更改为大致位置的请求,如需检查您的应用如何处理此类请求,请执行以下操作:

  1. 同时请求 ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION
  2. 在显示的对话框中(图 2),选择顶部附近的确切,以及底部附近的仅在使用该应用时允许仅限这一次
  3. 转到系统设置中应用的权限屏幕。
  4. 在位置权限屏幕上,关闭使用确切位置图 5 中显示了此选项。

    与任何权限降级一样,系统会重启应用的进程。

  5. 检查应用的用例是否仍按预期工作,即使您的应用只有大致位置信息访问权限也是如此。

处理系统设置中的确切位置升级

对于用户要求在系统设置中将您的应用的位置信息访问权限从大致位置更改为确切位置的请求,如需检查您的应用如何处理此类请求,请执行以下操作:

  1. 同时请求 ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION
  2. 在显示的对话框中(图 2),选择顶部附近的大致,以及底部附近的仅在使用该应用时允许仅限这一次
  3. 转到系统设置中应用的权限屏幕。
  4. 在位置权限屏幕上,开启使用确切位置,如图 5 所示。

    由于此权限更改是升级,因此系统不会重启您的应用。

  5. 检查您的应用是否可以在其基于位置信息的用例中接收更准确的位置数据。

检查应用的 SDK 依赖项中的位置信息要求

检查您的应用是否使用任何依赖于 ACCESS_FINE_LOCATION 权限的 SDK。请参阅 Medium 上关于了解 SDK 依赖项的行为的这篇文章。