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

Надлежащее использование информации о местоположении может быть полезным для пользователей вашего приложения. Например, если ваше приложение помогает пользователю находить дорогу во время ходьбы или вождения, или если ваше приложение отслеживает местоположение объектов, ему необходимо регулярно получать информацию о местоположении устройства. Помимо географического положения (широта и долгота), вы можете предоставить пользователю дополнительную информацию, такую ​​как азимут (горизонтальное направление движения), высоту или скорость устройства. Эта и другая информация доступна в объекте Location , который ваше приложение может получить от поставщика объединенного местоположения . В ответ API периодически обновляет ваше приложение, указывая наилучшее доступное местоположение на основе доступных на данный момент поставщиков местоположения, таких как Wi-Fi и GPS (система глобального позиционирования). Точность местоположения определяется поставщиками, запрошенными вами разрешениями на определение местоположения и параметрами, заданными вами в запросе местоположения.

В этом уроке показано, как запрашивать регулярные обновления о местоположении устройства с помощью метода requestLocationUpdates() в объединенном поставщике местоположений.

Получить последнее известное местоположение

Последнее известное местоположение устройства обеспечивает удобную основу для начала, гарантируя, что приложение имеет известное местоположение, прежде чем запускать периодические обновления местоположения. В уроке «Получение последнего известного местоположения» показано, как получить последнее известное местоположение с помощью вызова getLastLocation() . В следующих разделах предполагается, что ваше приложение уже получило последнее известное местоположение и сохранило его как объект Location в глобальной переменной mCurrentLocation .

Сделать запрос местоположения

Прежде чем запрашивать обновления местоположения, ваше приложение должно подключиться к службам определения местоположения и отправить запрос местоположения. В уроке «Изменение настроек местоположения» показано, как это сделать. После запроса местоположения вы можете начать регулярные обновления, вызвав requestLocationUpdates() .

В зависимости от формы запроса поставщик объединенного местоположения либо вызывает метод обратного вызова LocationCallback.onLocationResult() и передает ему список объектов Location , либо выдает PendingIntent , который содержит местоположение в своих расширенных данных. На точность и частоту обновлений влияют запрошенные вами разрешения на определение местоположения и параметры, заданные вами в объекте запроса местоположения.

В этом уроке показано, как получить обновление с помощью обратного вызова LocationCallback . Вызовите requestLocationUpdates() , передав ему свой экземпляр объекта LocationRequest и LocationCallback . Определите метод startLocationUpdates() как показано в следующем примере кода:

Котлин

override fun onResume() {
    super.onResume()
    if (requestingLocationUpdates) startLocationUpdates()
}

private fun startLocationUpdates() {
    fusedLocationClient.requestLocationUpdates(locationRequest,
            locationCallback,
            Looper.getMainLooper())
}

Ява

@Override
protected void onResume() {
    super.onResume();
    if (requestingLocationUpdates) {
        startLocationUpdates();
    }
}

private void startLocationUpdates() {
    fusedLocationClient.requestLocationUpdates(locationRequest,
            locationCallback,
            Looper.getMainLooper());
}

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

Определите обратный вызов обновления местоположения

Поставщик объединенного местоположения вызывает метод обратного вызова LocationCallback.onLocationResult() . Входящий аргумент содержит объект Location списка, содержащий широту и долготу местоположения. В следующем фрагменте показано, как реализовать интерфейс LocationCallback и определить метод, затем получить метку времени обновления местоположения и отобразить широту, долготу и метку времени в пользовательском интерфейсе вашего приложения:

Котлин

private lateinit var locationCallback: LocationCallback

// ...

override fun onCreate(savedInstanceState: Bundle?) {
    // ...

    locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult?) {
            locationResult ?: return
            for (location in locationResult.locations){
                // Update UI with location data
                // ...
            }
        }
    }
}

Ява

private LocationCallback locationCallback;

// ...

@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...

    locationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            if (locationResult == null) {
                return;
            }
            for (Location location : locationResult.getLocations()) {
                // Update UI with location data
                // ...
            }
        }
    };
}

Остановить обновление местоположений

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

Чтобы остановить обновление местоположения, вызовите removeLocationUpdates() , передав ему LocationCallback , как показано в следующем примере кода:

Котлин

override fun onPause() {
    super.onPause()
    stopLocationUpdates()
}

private fun stopLocationUpdates() {
    fusedLocationClient.removeLocationUpdates(locationCallback)
}

Ява

@Override
protected void onPause() {
    super.onPause();
    stopLocationUpdates();
}

private void stopLocationUpdates() {
    fusedLocationClient.removeLocationUpdates(locationCallback);
}

Используйте логическое значение requestingLocationUpdates , чтобы отслеживать, включены ли в данный момент обновления местоположений. В методе onResume() активности проверьте, активны ли в данный момент обновления местоположения, и активируйте их, если нет:

Котлин

override fun onResume() {
    super.onResume()
    if (requestingLocationUpdates) startLocationUpdates()
}

Ява

@Override
protected void onResume() {
    super.onResume();
    if (requestingLocationUpdates) {
        startLocationUpdates();
    }
}

Сохраните состояние активности

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

В следующем примере кода показано, как использовать обратный вызов onSaveInstanceState() действия для сохранения состояния экземпляра:

Котлин

override fun onSaveInstanceState(outState: Bundle?) {
    outState?.putBoolean(REQUESTING_LOCATION_UPDATES_KEY, requestingLocationUpdates)
    super.onSaveInstanceState(outState)
}

Ява

@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putBoolean(REQUESTING_LOCATION_UPDATES_KEY,
            requestingLocationUpdates);
    // ...
    super.onSaveInstanceState(outState);
}

Определите метод updateValuesFromBundle() для восстановления сохраненных значений из предыдущего экземпляра действия, если они доступны. Вызовите метод из метода onCreate() действия, как показано в следующем примере кода:

Котлин

override fun onCreate(savedInstanceState: Bundle?) {
    // ...
    updateValuesFromBundle(savedInstanceState)
}

private fun updateValuesFromBundle(savedInstanceState: Bundle?) {
    savedInstanceState ?: return

    // Update the value of requestingLocationUpdates from the Bundle.
    if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) {
        requestingLocationUpdates = savedInstanceState.getBoolean(
                REQUESTING_LOCATION_UPDATES_KEY)
    }

    // ...

    // Update UI to match restored state
    updateUI()
}

Ява

@Override
public void onCreate(Bundle savedInstanceState) {
    // ...
    updateValuesFromBundle(savedInstanceState);
}

private void updateValuesFromBundle(Bundle savedInstanceState) {
    if (savedInstanceState == null) {
        return;
    }

    // Update the value of requestingLocationUpdates from the Bundle.
    if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) {
        requestingLocationUpdates = savedInstanceState.getBoolean(
                REQUESTING_LOCATION_UPDATES_KEY);
    }

    // ...

    // Update UI to match restored state
    updateUI();
}

Дополнительные сведения о сохранении состояния экземпляра см. в справочнике по классу Android Activity .

Примечание. Для более постоянного хранения вы можете сохранить настройки пользователя в SharedPreferences вашего приложения. Установите общее предпочтение в методе onPause() вашей активности и получите предпочтение в onResume() . Дополнительные сведения о сохранении настроек см. в статье Сохранение наборов ключей и значений .

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

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

Образцы