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

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

На рисунке 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 , диалоговое окно системных разрешений включает следующие параметры для пользователя:

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

На рисунке 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
        )
    )
}

Java

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 ознакомьтесь со следующими материалами:

Кодлабс

Видео

Образцы

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