Сканирование радиомаяков и получение местоположения периодически на переднем плане - PullRequest
0 голосов
/ 08 апреля 2019

Я использую библиотеку маяков для сканирования маяков с сервисом переднего плана и постоянным уведомлением.Я проверил это на Android 9.0 и 7.0, и приложение работает, как и ожидалось, и отправляет маяки, отсканированные на сервер, каждые 30 секунд.Теперь я пытаюсь добавить сканирование местоположения в приложение, чтобы оно получало обновления местоположения каждые 30 секунд.Я использую Google Play API и настраиваю запрос местоположения с интервалом в 30 секунд.Затем я создал клиента FusedLocationProvider в своем классе приложения, поэтому я дал ему контекст моего приложения (не действия).Затем я передал свой запрос и следующий обратный вызов клиенту:

locationCallback = new LocationCallback()
  {
     @Override
     public void onLocationResult(LocationResult locationResult)
     {
        if ( locationResult != null )
        {
           Log.d(TAG, "location acquired: " + locationResult.getLastLocation());
           beaconContainer.setLocation(locationResult.getLastLocation());
        }
     }
  };

Объект beaconContainer содержит список маяков и последнее местоположение (и временную метку, когда последнее местоположение было получено с использованием LocalTime.now.()) и отправляет их на сервер каждые 30 секунд.Сначала приложение работает, и временная метка местоположения находится в пределах 30 секунд с момента отправки запроса на сервер.Однако по прошествии некоторого времени (и экран был отключен в течение некоторого времени), создается впечатление, что метод onLocationResult в обратном вызове не вызывается и местоположение не обновляется.Например, запрос к серверу был сделан в 12:34, но местоположение было обновлено в 10:21.Обратите внимание, что сканирование маяка по-прежнему выполняется правильно, как и ожидалось.

Мне было интересно, связано ли это с тем, что телефон, на котором я проверял, был стационарным или потому, что я не использовал службу для обновления местоположения,Мне кажется, что это первое, потому что мое приложение имеет службу переднего плана (ble scanner) и постоянное уведомление, поэтому, согласно документации, оно находится на переднем плане и не должно подвергаться ограничениям фона.Если это последнее, как я могу объединить службу переднего плана библиотеки маяков с моим сканированием местоположения, чтобы они оба работали, как ожидалось.

Спасибо.

РЕДАКТИРОВАТЬ:

Вот скриншот истории аккумулятора, показывающий, как BLE регулярно и последовательно используется, в то время как GPS используется в течение периодических периодов.Battery historian

1 Ответ

1 голос
/ 08 апреля 2019

Документация для FusedLocationProviderClient указывает, что в Android 8+, если приложение не на переднем плане, вы будете получать обновления только «несколько раз в час». Смотрите здесь . Вероятно, это связано с тем, что реализация в Службах Google Play использует JobScheduler на Android 8+, чтобы обойти ограничения фонового обслуживания, а задания ограничены выполнением каждые 15 минут +/- 5 минут в фоновом режиме. Поскольку API Google Play Services являются закрытыми исходными кодами и являются проприетарными, сложно сказать больше о его внутренней реализации, но маловероятно, что в нем учтены службы переднего плана. (Библиотека маяков Android, напротив, явно разработана для работы по-разному при настройке с помощью службы Foreground, поэтому вы получаете более частые обновления.)

Непонятно, как FusedLocationProviderClient работает по-разному в фоновом режиме на Android 7. Он может вообще не работать по-разному и может следовать шаблону, описанному выше в фоновом режиме, просто если ваше приложение предназначено SDK 26 или выше. Вы должны проверить, чтобы убедиться - эффективно пересмотреть службы Google Play. Даже если вы поймете это, поведение может измениться в следующей версии Google Play Services, и вы никогда не узнаете об этом, если не проведете обратный инжиниринг. В этом и заключается опасность использования SDK с закрытым исходным кодом.

Альтернативой было бы вместо этого использовать API определения местоположения с открытым исходным кодом, предоставляемый Android.

LocationManager locationManager = (LocationManager)
          this.getSystemService(Context.LOCATION_SERVICE);
try {

        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 400l, (float) 1000.0, this); //You can also use LocationManager.GPS_PROVIDER and LocationManager.PASSIVE_PROVIDER
}
catch (SecurityException e) {
        Log.d(TAG, "Can't get location -- permission denied");
}

Конечно, вы захотите настроить точность и интервал обновления в соответствии с вашими потребностями и сэкономить заряд батареи. И вы наверняка найдете выпадения в обратных вызовах, когда ваш телефон перейдет в режим ожидания. Но вы должны иметь возможность использовать вышеперечисленное в своем классе приложений, как вы описываете в своем вопросе, без раздражающего непрозрачного поведения, добавленного сервисами Google Play.

...