概略位置

1. 簡介

在 Android 12 (API 級別 31) 以上版本中,使用者可以控制要授予應用程式的位置精確度。在舊版 Android 中,系統會根據應用程式要求 ACCESS_FINE_LOCATION 權限或 ACCESS_COARSE_LOCATION 權限,間接控制位置精確度。

本程式碼研究室將針對目標 SDK 31 以上版本的應用程式,提供指引與最佳做法,以要求位置存取權。

必要條件

學習目標

  • 如何在 Android S 中要求位置存取權
  • 如何實作最佳位置要求流程,以利使用者授予應用程式精確位置存取權

用語

精確位置ACCESS_FINE_LOCATION 權限的位置精細程度。

概略位置ACCESS_COARSE_LOCATION 權限的位置精細程度。

涵蓋的 API

2. 要求 ACCESS_FINE_LOCATION 權限

新版 UI 流程

我們先來看看新版 UI,瞭解位置精確度的變化。

下圖 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 中要求位置存取權,並成功探索數個位置存取權的關鍵要素!

您現在可以根據應用程式需求,針對不同用途要求位置存取權。

進一步瞭解位置資訊: