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

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

На рис. 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 .
В диалоговом окне есть два набора параметров, один над другим.
Рисунок 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 просмотрите следующие материалы:

Кодлабы

Видео

Образцы

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