Оптимизируйте место для аккумулятора

Фоновые ограничения местоположения , представленные в Android 8.0 (уровень API 26), привлекли новое внимание к вопросу о том, как использование служб определения местоположения влияет на расход заряда батареи. На этой странице описаны некоторые передовые методы работы служб определения местоположения и то, что вы можете сделать сейчас , чтобы ваши приложения более эффективно тратили заряд батареи. Применение этих рекомендаций принесет пользу вашему приложению независимо от версии платформы, на которой оно работает.

Ограничения фонового местоположения в Android 8.0 внесли следующие изменения:

  • Сбор данных о местоположении в фоновом режиме ограничивается, местоположение вычисляется и доставляется только несколько раз в час.
  • Сканирование Wi-Fi более консервативно, и обновления местоположения не вычисляются, когда устройство остается подключенным к той же статической точке доступа.
  • Скорость реагирования геозон меняется от десятков секунд до примерно двух минут. Это изменение заметно повышает производительность аккумулятора — на некоторых устройствах до 10 раз.

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

Понимание разряда аккумулятора

Сбор местоположения и расход батареи напрямую связаны в следующих аспектах:

  • Точность: точность данных о местоположении. В общем, чем выше точность, тем выше расход батареи.
  • Частота: как часто вычисляется местоположение. Чем чаще вычисляется местоположение, тем больше расходуется батарея.
  • Задержка: как быстро доставляются данные о местоположении. Меньшая задержка обычно требует большего заряда батареи.

Точность

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

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

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

Частота

Вы можете указать частоту местоположений двумя способами:

  • Используйте метод setinterval() , чтобы указать интервал, с которым вычисляется местоположение вашего приложения .
  • Используйте setFastestInterval() , чтобы указать интервал, с которым местоположение, вычисленное для других приложений, будет доставлено в ваше приложение .

При использовании setInterval() вам следует передать максимально возможное значение. Это особенно актуально для фонового сбора данных о местоположении, что часто является источником нежелательного разряда батареи. Использование интервалов в несколько секунд следует зарезервировать для случаев приоритетного использования. Ограничения фонового местоположения, введенные в Android 8.0, обеспечивают соблюдение этих стратегий, но ваше приложение должно стремиться обеспечить их соблюдение на устройствах Android 7.0 или более ранних версий.

Задержка

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

Если вашему приложению не требуется немедленное обновление местоположения, вам следует передать максимально возможное значение методу setMaxWaitTime() , эффективно обменивая задержку на больший объем данных и эффективность использования батареи.

При использовании геозон приложения должны передавать большое значение в метод setNotificationResponsiveness() для сохранения мощности. Рекомендуется значение пять минут или больше.

Варианты использования местоположения

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

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

Пример: картографическое приложение, которому необходимы частые и точные обновления с очень малой задержкой. Все обновления происходят на переднем плане: пользователь запускает действие, использует данные о местоположении, а затем через короткое время останавливает действие.

Используйте метод setPriority() со значением PRIORITY_HIGH_ACCURACY или PRIORITY_BALANCED_POWER_ACCURACY .

Интервал, указанный в методе setInterval() зависит от варианта использования: для сценариев реального времени установите значение в несколько секунд; в противном случае ограничьтесь несколькими минутами (рекомендуется примерно две минуты или больше, чтобы минимизировать использование батареи).

Знание местоположения устройства

Пример. Приложение погоды хочет узнать местоположение устройства.

Используйте метод getLastLocation() , который возвращает последнее доступное местоположение (которое в редких случаях может быть нулевым). Этот метод обеспечивает простой способ определения местоположения и не требует затрат, связанных с активным запросом обновлений местоположения. Используйте в сочетании с методом isLocationAvailable() , который возвращает true , если местоположение, возвращаемое методом getLastLocation() достаточно актуально.

Запуск обновлений, когда пользователь находится в определенном месте

Пример. Запрос обновлений, когда пользователь находится на определенном расстоянии от работы, дома или другого места.

Используйте геозоны в сочетании с объединенными обновлениями поставщика местоположений. Запрашивайте обновления, когда приложение получает триггер входа в геозону, и удаляйте обновления, когда приложение получает триггер выхода из геозоны. Это гарантирует, что приложение будет получать более детальные обновления местоположения только тогда, когда пользователь войдет в определенную область.

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

Запуск обновлений в зависимости от состояния активности пользователя

Пример. Запрос обновлений только тогда, когда пользователь водит машину или ездит на велосипеде.

Используйте API распознавания действий в сочетании с обновлениями объединенного поставщика местоположений. Запрашивайте обновления при обнаружении целевого действия и удаляйте обновления, когда пользователь прекращает выполнять это действие.

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

Длительные фоновые обновления местоположения, привязанные к географическим регионам.

Пример. Пользователь хочет получать уведомления, когда устройство находится в непосредственной близости от розничного продавца.

Это отличный вариант использования геозон. Поскольку вариант использования почти наверняка включает фоновое местоположение, используйте метод addGeofences(GeofencingRequest, PendingIntent) .

Вам следует установить следующие параметры конфигурации:

  • Если вы отслеживаете переходы задержки, используйте метод setLoiteringDelay() , передавая значение примерно пять минут или меньше.

  • Используйте setNotificationResponsiveness() , передав значение примерно пять минут. Однако рассмотрите возможность использования значения примерно в десять минут, если ваше приложение может справиться с дополнительной задержкой отклика.

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

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

Пример: приложение, которое пассивно отслеживает местоположение.

Если возможно, используйте метод setPriority() с опцией PRIORITY_NO_POWER , поскольку он практически не разряжает батарею. Если использование PRIORITY_NO_POWER невозможно, используйте PRIORITY_BALANCED_POWER_ACCURACY или PRIORITY_LOW_POWER , но избегайте использования PRIORITY_HIGH_ACCURACY для продолжительной фоновой работы, поскольку этот параметр существенно разряжает батарею.

Если вам нужно больше данных о местоположении, используйте пассивное местоположение, вызвав метод setFastestInterval() , передав меньшее значение, чем то, которое вы передаете в setInterval() . В сочетании с опцией PRIORITY_NO_POWER пассивное определение местоположения может без каких-либо дополнительных затрат предоставлять местоположение, рассчитанное другими приложениями.

Умерьте частоту, добавив некоторую задержку с помощью метода setMaxWaitTime() . Например, если вы используете метод setinterval() со значением примерно 10 минут, вам следует рассмотреть возможность вызова setMaxWaitTime() со значением от 30 до 60 минут. При использовании этих параметров местоположение вашего приложения вычисляется примерно каждые 10 минут, но приложение просыпается только каждые 30–60 минут, при этом некоторые данные о местоположении доступны в виде пакетного обновления. При таком подходе задержка позволяет получить больше доступных данных и повысить производительность батареи.

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

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

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

Рекомендации по определению местоположения

Внедрение рекомендаций из этого раздела поможет сократить расход заряда батареи вашим приложением.

Удалить обновления местоположения

Распространенным источником ненужного расхода заряда батареи является неспособность удалить обновления местоположения, когда они больше не нужны. Это может произойти, например, когда методы жизненного цикла onStart() или onResume() действия содержат вызов requestlocationUpdates() без соответствующего вызова removeLocationUpdates() в методах жизненного цикла onPause() или onStop() .

Вы можете использовать компоненты, учитывающие жизненный цикл, чтобы лучше управлять жизненным циклом действий в вашем приложении. Дополнительные сведения см. в разделе «Обработка жизненных циклов с помощью компонентов, учитывающих жизненный цикл» .

Установить таймауты

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

Для запроса объединенного поставщика местоположения добавьте тайм-аут, вызвав setExpirationDuration() , который получает параметр, представляющий время в миллисекундах с момента последнего вызова метода. Вы также можете добавить тайм-аут, вызвав setExpirationTime() , который получает параметр, представляющий время истечения срока действия в миллисекундах с момента последней загрузки системы.

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

Пакетные запросы

Для всех случаев использования, не являющихся приоритетными, группируйте несколько запросов вместе. Вы можете использовать метод setInterval() , чтобы указать интервал, с которым вы хотите вычислить местоположение. Затем используйте метод setMaxWaitTime() чтобы установить интервал, с которым местоположение будет доставлено в ваше приложение. Значение, передаваемое методу setMaxWaitTime() должно быть кратно значению, передаваемому методу setInterval() . Например, рассмотрим следующий запрос местоположения:

Котлин

val request = LocationRequest()
request.setInterval(10 * 60 * 1000)
request.setMaxWaitTime(60 * 60 * 1000)

Ява

LocationRequest request = new LocationRequest();
request.setInterval(10 * 60 * 1000);
request.setMaxWaitTime(60 * 60 * 1000);

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

Используйте пассивные обновления местоположения

В фоновых случаях рекомендуется ограничить обновление местоположения. Ограничения Android 8.0 усиливают эту практику, но приложения, работающие на старых устройствах, должны стремиться максимально ограничить местоположение в фоновом режиме.

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

Котлин

val request = LocationRequest()
request.setInterval(15 * 60 * 1000)
request.setFastestInterval(2 * 60 * 1000)

Ява

LocationRequest request = new LocationRequest();
request.setInterval(15 * 60 * 1000);
request.setFastestInterval(2 * 60 * 1000);

В предыдущем примере местоположение вашего приложения вычисляется примерно каждые 15 минут. Если другие приложения запрашивают местоположение, данные предоставляются вашему приложению с максимальным интервалом в две минуты.

Пассивное использование местоположения не приводит к разрядке батареи, поэтому будьте особенно осторожны в тех случаях, когда получение данных о местоположении вызывает дорогостоящие операции ЦП или ввода-вывода. Чтобы минимизировать затраты на батарею, интервал, указанный в setFastestInterval() не должен быть слишком маленьким.

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