Android Fuse API местоположения не обеспечивает согласованные обновления с выключенным экраном

У меня есть код, который запускается несколько раз в секунду в моем приложении. Я пытаюсь получить свое местоположение в каждом цикле. Я использую следующее:

Location myLastPos = LocationServices.FusedLocationApi.getLastLocation(googleApiClient)

Мое приложение также работает в фоновом режиме с использованием PARTIAL_WAKE_LOCK. С включенным экраном вроде все ОК. Когда я выключаю экран, мое приложение по-прежнему работает нормально, но я больше не получаю постоянно обновления местоположения. Похоже, я получаю обновления намного реже (часто минуты между обновлениями). Я проверяю временную метку местоположения, используя:

myLastPos.getElapsedRealtimeNanos()

Я также обнаружил, что даже при включенном экране я получаю странные результаты. Иногда я получаю несколько миллисекунд между обновлениями, иногда я получаю несколько секунд. Все это очень настораживает. Может ли кто-нибудь помочь мне правильно использовать FusedLocationApi или предложить альтернативу. Все, что я действительно хочу, это опрашивать GPS напрямую для широты / долготы несколько раз в секунду, не мешая библиотекам Google.


person Shahin    schedule 12.10.2016    source источник
comment
Метод getLastLocation() просто получает последнее известное местоположение, известное устройству. Устройство не определяет свое местоположение само по себе, а только тогда, когда какое-либо приложение запрашивает местоположение. Таким образом, ваше приложение теперь зависит от других приложений, запрашивающих обновления местоположения. Если вам нужны обновления каждые несколько секунд, запросите регулярные обновления местоположения самостоятельно. В разделе документации есть примеры кода.   -  person Markus Kauppinen    schedule 12.10.2016
comment
@MarkusKauppinen, ты прав. Документация не очень ясна по этому поводу, и я предположил, что ОС Android будет автоматически опрашивать GPS в фоновом режиме, а getLastLocation() просто предоставит последний результат. Если вы ответите на вопрос своим комментарием, я могу отметить его как отвеченный. Спасибо!   -  person Shahin    schedule 14.10.2016
comment
Кажется, это обычная путаница. Каким-то образом документация может прояснить, что это может быть старое и недопустимое местоположение. Технически это правильно, так как это действительно последнее известное местонахождение. Во всяком случае, я добавил правильный ответ сейчас. Это может быть дубликат какого-то старого вопроса, но мне нелегко найти хорошего кандидата. Большинство из них (с принятыми ответами) касаются просто получения null местоположения.   -  person Markus Kauppinen    schedule 14.10.2016


Ответы (1)


Метод getLastLocation() просто получает последнее известное местоположение, известное устройству. «Последнее известное местоположение» здесь означает именно это: оно может быть устаревшим. Местоположения имеют отметку времени, которую можно использовать для оценки того, может ли местоположение по-прежнему быть актуальным.

Устройство не определяет свое местоположение само по себе, а только тогда, когда какое-либо приложение запрашивает местоположение. Таким образом, ваше приложение теперь зависит от других приложений, запрашивающих обновления местоположения.

Если вам нужны обновления каждые несколько секунд, запросите регулярные обновления местоположения самостоятельно.

документация Android рекомендует использовать FusedLocationProvider, но LocationManager также является вполне допустимым вариантом, если есть какая-либо причина избегать сервисов Google Play.

Основная идея состоит в том, чтобы сначала запросить обновления местоположения:

// Using LocationManager as an example.
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// Using GPS, requesting location updates as soon as available and even for
// the smallest changes. Here 'this' refers to our LocationListener 
// implementation.
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);

Затем обновления принимаются слушателем:

@Override
    public void onLocationChanged(Location location) {
        // We received a location update.
        // Copy the value from the method parameter to our
        // class member variable.
        mLocation = location;
    }

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

mLocationManager.removeUpdates(this);

Подход очень похож на FusedLocationProvider.

person Markus Kauppinen    schedule 14.10.2016