Запросить доступ к местоположению во время выполнения

Если функция вашего приложения требует доступа к данным о местоположении, дождитесь, пока пользователь взаимодействует с этой функцией, прежде чем запрашивать разрешение. Этот рабочий процесс соответствует передовой практике запроса разрешений во время выполнения в контексте, как описано в руководстве, объясняющем, как запрашивать разрешения для приложения .

На рисунке 1 показан пример этого процесса. Приложение содержит функцию «поделиться местоположением», требующую доступа к данным о местоположении в активном режиме. Однако приложение не запрашивает разрешение на определение местоположения, пока пользователь не нажмёт кнопку « Поделиться местоположением» .

После того, как пользователь нажмет кнопку «Поделиться местоположением», появится диалоговое окно разрешения на доступ к местоположению системы.
Рисунок 1. Функция передачи данных о местоположении, требующая доступа к данным о местоположении в фоновом режиме. Функция включается, если пользователь выбирает «Разрешить только при использовании приложения» .

Пользователь может указать только приблизительное местоположение.

На устройствах с Android 12 (уровень API 31) и выше пользователи могут запросить, чтобы ваше приложение извлекало только приблизительную информацию о местоположении, даже если ваше приложение запрашивает разрешение среды выполнения ACCESS_FINE_LOCATION .

Чтобы предотвратить такое потенциальное поведение пользователя, не запрашивайте разрешение ACCESS_FINE_LOCATION отдельно. Вместо этого запросите оба разрешения ACCESS_FINE_LOCATION и ACCESS_COARSE_LOCATION — в одном запросе во время выполнения. Если вы попытаетесь запросить только ACCESS_FINE_LOCATION , система проигнорирует его в некоторых версиях Android 12. Если ваше приложение предназначено для Android 12 или более поздних версий, система запишет в Logcat следующее сообщение об ошибке:

ACCESS_FINE_LOCATION must be requested with ACCESS_COARSE_LOCATION.

Когда ваше приложение запрашивает и ACCESS_FINE_LOCATION , и ACCESS_COARSE_LOCATION , диалоговое окно системных разрешений включает следующие параметры для пользователя:

  • Точное : позволяет вашему приложению получать точную информацию о местоположении.
  • Приблизительное : позволяет вашему приложению получать только приблизительную информацию о местоположении.

На рисунке 3 показано, что диалоговое окно содержит визуальную подсказку для обоих вариантов, помогающую пользователю сделать выбор. После того, как пользователь выберет точность определения местоположения, он нажмет одну из трёх кнопок, чтобы выбрать срок действия разрешения.

На устройствах Android 12 и более поздних версиях пользователи могут перейти в системные настройки, чтобы установить предпочтительную точность определения местоположения для любого приложения, независимо от целевой версии SDK этого приложения. Это справедливо даже если приложение установлено на устройстве с Android 11 или более ранней версии, а затем пользователь обновляет устройство до Android 12 или более поздней версии.

Диалоговое окно указывает только приблизительное местоположение и содержит 3 кнопки, расположенные одна над другой.
Рисунок 2. Диалоговое окно системных разрешений, которое появляется, когда ваше приложение запрашивает только ACCESS_COARSE_LOCATION .
В диалоговом окне есть 2 набора опций, расположенных один над другим.
Рисунок 3. Диалоговое окно системных разрешений, которое появляется, когда ваше приложение запрашивает ACCESS_FINE_LOCATION и ACCESS_COARSE_LOCATION в одном запросе времени выполнения.

Выбор пользователя влияет на предоставление разрешений

В следующей таблице показаны разрешения, которые система предоставляет вашему приложению на основе параметров, которые пользователь выбирает в диалоговом окне разрешений во время выполнения:

Точный Приблизительный
Во время использования приложения ACCESS_FINE_LOCATION и
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
Только в этот раз ACCESS_FINE_LOCATION и
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
Отрицать Нет разрешений на местоположение Нет разрешений на местоположение

Чтобы определить, какие разрешения система предоставила вашему приложению, проверьте возвращаемое значение запроса разрешений. Вы можете использовать библиотеки Jetpack в коде, похожем на следующий, или использовать библиотеки платформы, где вы можете самостоятельно управлять кодом запроса разрешений .

Котлин

@RequiresApi(Build.VERSION_CODES.N)
fun requestPermissions() {
    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:
    // https://developer.android.com/training/permissions/requesting#request-permission
    locationPermissionRequest.launch(
        arrayOf(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
        )
    )
}

Ява

private void requestPermissions() {

    ActivityResultLauncher<String[]> locationPermissionRequest =
            registerForActivityResult(new ActivityResultContracts
                            .RequestMultiplePermissions(), result -> {

                Boolean fineLocationGranted = null;
                Boolean coarseLocationGranted = null;

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    fineLocationGranted = result.getOrDefault(
                            Manifest.permission.ACCESS_FINE_LOCATION, false);
                    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
    });
}

Запросить обновление до точного местоположения

Вы можете попросить пользователя расширить доступ вашего приложения с приблизительного местоположения до точного. Однако, прежде чем просить пользователя расширить доступ вашего приложения до точного местоположения, подумайте, действительно ли для вашего приложения требуется такой уровень точности. Если вашему приложению требуется сопряжение с устройствами поблизости по Bluetooth или Wi-Fi, рассмотрите возможность использования сопряжения сопутствующих устройств или разрешений Bluetooth вместо запроса разрешения ACCESS_FINE_LOCATION .

Чтобы попросить пользователя повысить уровень доступа к местоположению вашего приложения с приблизительного до точного, выполните следующие действия:

  1. При необходимости объясните, почему вашему приложению необходимо это разрешение .
  2. Запросите разрешения ACCESS_FINE_LOCATION и ACCESS_COARSE_LOCATION вместе ещё раз. Поскольку пользователь уже разрешил системе предоставлять вашему приложению приблизительное местоположение, системный диалог на этот раз выглядит иначе, как показано на рисунках 4 и 5:
Диалоговое окно содержит параметры «Изменить на точное местоположение», «Только в этот раз» и «Запретить».
Рисунок 4. Пользователь ранее выбрал «Приблизительно» и «Во время использования приложения» (в диалоговом окне на рисунке 3 ).
В диалоговом окне доступны опции «Только в этот раз» и «Запретить».
Рисунок 5. Пользователь ранее выбрал «Приблизительно» и «Только в этот раз» (в диалоговом окне на рисунке 3 ).

Первоначально запрашивать только местоположение на переднем плане

Даже если нескольким функциям вашего приложения требуется доступ к данным о местоположении, вероятно, только некоторым из них требуется доступ к данным о местоположении в фоновом режиме. Поэтому рекомендуется, чтобы ваше приложение выполняло поэтапные запросы на доступ к данным о местоположении, сначала в активном режиме, а затем в фоновом режиме. Выполняя поэтапные запросы, вы предоставляете пользователям больше контроля и прозрачности, поскольку они могут лучше понять, каким функциям вашего приложения требуется доступ к данным о местоположении в фоновом режиме.

На рисунке 6 показан пример приложения, предназначенного для обработки инкрементальных запросов. Обе функции — «Показать текущее местоположение» и «Рекомендовать места поблизости» — требуют доступа к данным о местоположении в активном режиме. Однако только функция «Рекомендовать места поблизости» требует доступа к данным о местоположении в фоновом режиме.

Кнопка, включающая доступ к переднему плану, расположена на расстоянии половины экрана от кнопки, включающей доступ к фоновому местоположению.
Рисунок 6. Обе функции требуют доступа к местоположению, но только функция «рекомендовать объекты поблизости» требует доступа к местоположению в фоновом режиме.

Процесс выполнения инкрементных запросов выглядит следующим образом:

  1. Сначала ваше приложение должно направлять пользователей к функциям, требующим доступа к данным о местоположении в фоновом режиме, например, к функции «поделиться местоположением» на рисунке 1 или к функции «показать текущее местоположение» на рисунке 2.

    Рекомендуется отключить доступ пользователей к функциям, требующим фонового доступа к данным о местоположении, пока ваше приложение не получит доступ к данным о местоположении в фоновом режиме.

  2. Позднее, когда пользователь будет исследовать функции, требующие фонового доступа к данным о местоположении, вы сможете запросить фоновый доступ к данным о местоположении .

Дополнительные ресурсы

Дополнительную информацию о разрешениях на определение местоположения в Android можно найти в следующих материалах:

Codelabs

Видео

Образцы

  • Пример приложения , демонстрирующего использование разрешений на определение местоположения.