大致位置

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_LOCATIONACCESS_COARSE_LOCATION 权限时显示的权限对话框。

7acc5e2fe09d67ca.jpeg a5e9363364fcc9f9.jpeg

图 1a:选择了“确切”位置 图 1b:选择了“大致”位置

下面的图 2a 显示了在应用获取 ACCESS_COARSE_LOCATION 权限后显示的权限升级对话框。如果用户在前一个屏幕(如图 1b 所示)中为“大致”位置选择了“仅在使用该应用时允许”,就会显示这个对话框。

2624d89993700ea5.jpeg

图 2a

下面的图 2b 显示了在应用仅针对当前会话获取 ACCESS_COARSE_LOCATION 权限后显示的权限升级对话框。如果用户在前一个屏幕(如图 1b 所示)中选择了“仅限这一次”,就会显示这个对话框。

a2dfb923b8f3548d.jpeg

图 2b

3. 代码实现

在应用的清单中声明位置权限

为了请求 ACCESS_FINE_LOCATION,系统将要求您的应用同时在应用清单中声明 ACCESS_FINE_LOCATIONACCESS_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 权限后显示的权限对话框。

9d20729f14673547.jpeg

图 4

为了只使用大致位置信息权限,您的应用只需要在每一步中声明和处理大致权限。

5. 位置信息设置

下面的图 5 显示了新的位置信息权限设置。其中新增了切换开关,供用户控制应用是获取确切位置还是大致位置。

a9553249c3e2b90c.jpeg

图 5

6. 对于目标 SDK 版本为 30 及更低版本的应用

新的位置精确度选项(确切/大致)对目标 SDK 版本为 30 及更低版本的应用不可见。

7. 恭喜!

您了解了如何在 Android 12 中请求位置信息权限,并成功探索了位置信息权限的多个重要组成部分!

现在,您可以针对不同的用例请求位置权限,以满足应用的需求。

详细了解位置信息: