Настройки доступа к данным о местоположении

Если вашему приложению требуется запрашивать данные о местоположении или получать обновления разрешений, на устройстве должны быть включены соответствующие системные настройки, например GPS или сканирование Wi-Fi. Вместо того чтобы напрямую включать такие сервисы, как GPS, приложение указывает требуемый уровень точности/энергопотребления и желаемый интервал обновления, а устройство автоматически вносит соответствующие изменения в системные настройки. Эти настройки определяются объектом данных LocationRequest.

В этом уроке рассказывается, как с помощью Settings Client проверить, какие настройки включены, и показать пользователю диалоговое окно, в котором он сможет изменить настройки геолокации одним нажатием.

Настроить сервисы геолокации

Чтобы использовать сервисы геолокации, предоставляемые сервисами Google Play и поставщиком геоданных из нескольких источников, подключите приложение с помощью Settings Client, а затем проверьте текущие настройки геолокации и при необходимости предложите пользователю включить нужные.

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

Как настроить запрос местоположения

Чтобы сохранить параметры для запросов к поставщику геоданных из нескольких источников, создайте объект LocationRequest. Параметры определяют уровень точности для запросов местоположения. Подробные сведения обо всех доступных параметрах запроса местоположения можно найти в справочной документации по классу LocationRequest. В этом уроке задаются интервал обновления, минимальный интервал обновления и приоритет, как описано ниже.

Интервал обновления
setIntervalMillis() – этот метод задает частоту (в миллисекундах), с которой приложение должно получать уведомления о местоположении. Обратите внимание, что для оптимизации расхода заряда батареи уведомления о местоположении могут приходить несколько быстрее или медленнее, чем указано. Также уведомления могут не приходить совсем, например если устройство не подключено к сети.
Самый короткий интервал обновления
setMinUpdateIntervalMillis() – этот метод задает максимальную частоту (в миллисекундах), с которой приложение может обрабатывать обновления местоположения. Если вашему приложению не требуется получать обновления чаще, чем указано в setInterval(), вызывать этот метод не нужно.
Приоритет

setPriority() – этот метод задает приоритет запроса, который указывает сервисам геолокации Google Play, какие источники данных о местоположении следует использовать. Поддерживаются следующие значения:

  • PRIORITY_BALANCED_POWER_ACCURACY – используйте эту настройку, чтобы запрашивать местоположение с точностью до городского квартала (примерно 100 метров). Это считается низким уровнем точности и, скорее всего, будет потреблять меньше энергии. В этом случае сервисы геолокации, скорее всего, будут использовать данные о сетях Wi-Fi и вышках сотовой связи. Однако обратите внимание, что выбор поставщика данных о местоположении зависит от многих других факторов, например от того, какие источники доступны.
  • PRIORITY_HIGH_ACCURACY – используйте эту настройку, чтобы запрашивать максимально точное местоположение. В этом случае сервис геолокации чаще всего использует GPS для определения местоположения.
  • PRIORITY_LOW_POWER – используйте этот параметр, чтобы запрашивать данные с точностью до города (примерно 10 км). Это считается приблизительным уровнем точности и, скорее всего, будет потреблять меньше энергии.
  • PRIORITY_PASSIVE – используйте эту настройку, если вам нужно, чтобы влияние на энергопотребление было незначительным, но вы хотите получать уведомления о местоположении, когда они доступны. При этом приложение не будет запрашивать данные о местоположении, но сможет получать их, когда это делают другие приложения.

Создайте запрос местоположения и задайте параметры, как показано в этом примере кода:

Kotlin

  fun createLocationRequest() {
    val locationRequest = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 10000)
        .setMinUpdateIntervalMillis(5000)
        .build()
}

Java

  protected void createLocationRequest() {
    LocationRequest locationRequest = new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 10000)
            .setMinUpdateIntervalMillis(5000)
            .build();
}

Приоритет PRIORITY_HIGH_ACCURACY в сочетании с настройкой разрешений ACCESS_FINE_LOCATION, заданной в манифесте приложения, и коротким интервалом обновления (5000 мс, или 5 с) позволяет поставщику геоданных из нескольких источников возвращать уведомления о местоположении с точностью до нескольких метров. Этот подход подходит для картографических приложений, которые отображают местоположение в режиме реального времени.

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

Как получить текущие настройки геолокации

После подключения к сервисам Google Play и API геолокации вы можете получить текущие настройки геолокации на устройстве пользователя. Для этого создайте объект LocationSettingsRequest.Builder и добавьте в него один или несколько запросов местоположения. В следующем фрагменте кода показано, как добавить запрос местоположения, созданный на предыдущем шаге:

Kotlin

val builder = LocationSettingsRequest.Builder()
        .addLocationRequest(locationRequest)

Java

LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
     .addLocationRequest(locationRequest);

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

Kotlin

val builder = LocationSettingsRequest.Builder()

// ...

val client: SettingsClient = LocationServices.getSettingsClient(this)
val task: Task<LocationSettingsResponse> = client.checkLocationSettings(builder.build())

Java

LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();

// ...

SettingsClient client = LocationServices.getSettingsClient(this);
Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());

Когда Task завершится, ваше приложение сможет проверить настройки геолокации, посмотрев на код статуса из объекта LocationSettingsResponse. Чтобы получить более подробную информацию о текущем состоянии соответствующих настроек геолокации, ваше приложение может вызвать метод getLocationSettingsStates() объекта LocationSettingsResponse.

Предложить пользователю изменить настройки геолокации

Чтобы определить, подходят ли настройки геолокации для запроса местоположения, добавьте OnFailureListener к объекту Task, который проверяет настройки геолокации. Затем проверьте, является ли объект Exception, переданный методу onFailure(), экземпляром класса ResolvableApiException. Если да, то настройки нужно изменить. Затем покажите диалоговое окно, в котором пользователю предлагается разрешить изменение настроек геолокации, вызвав startResolutionForResult().

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

Kotlin

task.addOnSuccessListener { locationSettingsResponse ->
    // All location settings are satisfied. The client can initialize
    // location requests here.
    // ...
}

task.addOnFailureListener { exception ->
    if (exception is ResolvableApiException){
        // Location settings are not satisfied, but this can be fixed
        // by showing the user a dialog.
        try {
            // Show the dialog by calling startResolutionForResult(),
            // and check the result in onActivityResult().
            exception.startResolutionForResult(this@MainActivity,
                    REQUEST_CHECK_SETTINGS)
        } catch (sendEx: IntentSender.SendIntentException) {
            // Ignore the error.
        }
    }
}

Java

task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
    @Override
    public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
        // All location settings are satisfied. The client can initialize
        // location requests here.
        // ...
    }
});

task.addOnFailureListener(this, new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        if (e instanceof ResolvableApiException) {
            // Location settings are not satisfied, but this can be fixed
            // by showing the user a dialog.
            try {
                // Show the dialog by calling startResolutionForResult(),
                // and check the result in onActivityResult().
                ResolvableApiException resolvable = (ResolvableApiException) e;
                resolvable.startResolutionForResult(MainActivity.this,
                        REQUEST_CHECK_SETTINGS);
            } catch (IntentSender.SendIntentException sendEx) {
                // Ignore the error.
            }
        }
    }
});

В следующем уроке, Запрос обновлений местоположения, показано, как периодически получать обновления местоположения.