Новости о продуктах

Как оптимизировать расход заряда батареи с помощью показателя запрета блокировки в Android Vitals

Время на чтение: 7 минут
Посмотреть профиль пользователя Alice Yuan
Alice Yuan Инженер по связям с разработчиками, Android

Время работы от батареи – важный аспект удобства использования, и запреты блокировки играют в этом большую роль. Не слишком ли часто вы их используете? В этой записи блога мы расскажем, что такое запрет блокировки, как его использовать и как с помощью показателя в Play Console лучше понять поведение своего приложения.

Слишком долгая работа частичных запретов блокировки в Android Vitals

Теперь в Play Console отслеживается расход батареи. Ключевым показателем эффективности является слишком долгая работа частичных запретов блокировки.

Эта функция повышает важность эффективности батареи наряду с существующими основными показателями стабильности: слишком частыми сбоями в активном режиме и ошибками ANR. Мы определили порог соответствия для слишком длительных запретов блокировки. С 1 марта 2026 года, если ваш продукт не соответствует этому порогу качества, мы можем исключить его из рекомендаций и других разделов, где он хорошо заметен. В некоторых случаях на странице приложения в Google Play может показываться предупреждение о том, что оно может вызывать быстрый расход батареи.

warning.png

Предупреждение о слишком частом запрете блокировки в обзоре Android Vitals.

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

  • Запрет блокировки действует не менее двух часов в течение 24-часового периода.
  • Она затрагивает более 5% сеансов в приложении (среднее значение за 28 дней).

Запреты блокировки, созданные API, которые инициированы пользователем и связаны с аудио, местоположением и JobScheduler, не учитываются при расчете.

Что такое запрет блокировки

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

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

Частичные запреты блокировки могут быть получены двумя способами:

  • Приложение вручную получает и снимает запрет блокировки с помощью API PowerManager для определенного сценария использования. Часто это происходит в сочетании с активной службой – API жизненного цикла платформы, предназначенным для заметных пользователю операций.
  • Запрет блокировки может быть получен другим API и приписан приложению из-за использования этого API. Подробнее об этом рассказывается в разделе с рекомендациями.

Запрет блокировки необходим для выполнения некоторых задач, например скачивания большого файла, инициированного пользователем. Однако чрезмерное или неправильное использование этой функции может привести к значительному расходу заряда батареи. Мы сталкивались со случаями, когда приложения удерживали запрет блокировки часами или не снимали его должным образом. Это приводило к жалобам пользователей на значительный расход заряда батареи, даже когда они не взаимодействовали с приложением.

Рекомендации по использованию запрета блокировки

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

Рассмотрим четыре критических вопроса.


1. Рассматривали ли вы альтернативные варианты запрета блокировки?

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

wakelock.png

Блок-схема, которая поможет решить, когда нужно вручную запретить блокировку

  1. Должен ли экран оставаться включенным?
  2. Запущена ли в приложении активная служба?
    • Нет. Вам не нужно вручную запрашивать запрет блокировки.
  3. Не ухудшится ли удобство для пользователей, если устройство перейдет в спящий режим?
    • Нет. Например, чтобы обновить уведомление после выхода устройства из спящего режима, запрет блокировки не требуется.
    • Да. Если важно, чтобы устройство не переходило в спящий режим, например при обмене данными с внешним устройством, продолжайте.
  4. Есть ли API, который не дает устройству перейти в спящий режим?
    • Чтобы определить, в каких случаях запреты блокировки создаются другими API, например LocationManager, воспользуйтесь документацией Identify wake locks created by other APIs.
    • Если API нет, перейдите к последнему вопросу.
  5. Если вы ответили на все эти вопросы и определили, что альтернативы нет, вы должны продолжить вручную получать запрет блокировки.

2. Правильно ли вы называете запрет блокировки?

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

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

3. Всегда ли снимается запрет блокировки?

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

Например, если во время processingWork() возникает необработанное исключение, вызов release() может не произойти. Вместо этого используйте блок try-finally, чтобы гарантировать снятие запрета блокировки, даже если возникнет исключение.

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

fun processingWork() {
    wakeLock.apply {
        try {
            acquire(60 * 10 * 1000) // timeout after 10 minutes
            doTheWork()
        } finally {
            release()
        }
    }
}

4. Можно ли снизить частоту пробуждения?

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

  • WorkManager. Увеличьте периодический интервал в PeriodicWorkRequest.
  • SensorManager. Используйте пакетную обработку, указав maxReportLatencyMs при регистрации прослушивателя.
  • Поставщик геоданных из нескольких источников:
    • Чтобы реже запрашивать данные о местоположении, используйте метод getLastLocation, который возвращает последнее сохраненное в кеше местоположение.
    • Чтобы снизить расход заряда батареи, используйте метод setPriority(PRIORITY_PASSIVE).
    • Вы также можете использовать механизм пакетной обработки местоположений, установив минимальный интервал обновления с помощью setMinUpdateIntervalMillis.

Подробную информацию можно найти в документации по рекомендациям для запрета блокировки.

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

Даже при самых лучших намерениях запрет блокировки может использоваться слишком часто. Если ваше приложение помечено в Play Console, выполните следующие действия:

Первоначальная идентификация в Play Console

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

breakdowns2.png

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

Отладка чрезмерного запрета блокировки, удерживаемого рабочими процессами или заданиями

Запреты блокировки, удерживаемые рабочими процессами, можно определить по следующему названию:

*job*/<package_name>/androidx.work.impl.background.systemjob.SystemJobService

Полный список вариантов названий запретов блокировки, удерживаемых рабочими процессами, доступен в документации. Для отладки запретов блокировки можно использовать инспектор фоновых задач (локально) или метод getStopReason (удаленно).

Инспектор фоновых задач Android Studio

taskinspector.png


Скриншот инспектора фоновых задач, на котором показан рабочий поток WeatherSyncWorker, часто повторяющий попытки и завершающийся сбоем.

Для локальной отладки проблем с WorkManager используйте этот инструмент на эмуляторе или подключенном устройстве (уровень API 26 или выше). Он показывает список исполнителей и их статусы (завершено, выполняется, в очереди), позволяя просматривать подробности и понимать цепочки исполнителей. 

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

Подробную информацию можно найти в документации по инспектору фоновых задач.

WorkManager getStopReason

Для отладки рабочих процессов с чрезмерным количеством запретов блокировки используйте WorkInfo.getStopReason() в WorkManager 2.9.0 или более поздней версии, а для JobScheduler – JobParameters.getStopReason(), доступный в SDK 31 и более поздних версиях. 

Этот API помогает регистрировать причину остановки воркера (например, STOP_REASON_TIMEOUT, STOP_REASON_QUOTA), выявляя такие проблемы, как частые тайм-ауты из-за исчерпания времени выполнения.

backgroundScope.launch {
    WorkManager.getInstance(context)
        .getWorkInfoByIdFlow(workRequest.id)
        .collect { workInfo ->
            logStopReason(workRequest.id, workInfo?.stopReason)
        }
}

Подробнее о том, как оптимизировать расход заряда батареи при использовании API для планирования задач…

Как отлаживать другие типы слишком долгих запретов блокировки

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

Сбор данных трассировки системы

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

Записать трассировку системы можно несколькими способами: 

powermgmt.png

Включите категорию Atrace power:PowerManagement в интерфейсе Perfetto на вкладке Android apps & svcs (Приложения и сервисы Android). 

Независимо от выбранного метода, важно убедиться, что вы собираете категорию Atrace "power:PowerManagement", чтобы включить просмотр дорожек состояния устройства. 

Проверка интерфейса Perfetto и анализ SQL

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

perfetto.png


Закрепите дорожки в разделе Device State (Состояние устройства), например Top app (Основное приложение), Screen state (Состояние экрана), Long Wake locks (Длительные запреты блокировки) и Jobs (Задания), чтобы визуально определить фрагменты длительных запретов блокировки.

В каждом блоке указано название мероприятия, а также время его начала и окончания. В Perfetto это называется срезом.

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

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

SELECT slice.name as name, track.name as track_name,SUM(dur / 100000) as total_dur_ms
FROM slice
JOIN track ON slice.track_id = track.id
WHERE track.name = 'WakeLocks'GROUP BY slice.name, track.name
ORDER BY total_dur_ms DESC

Как использовать ProfilingManager для сбора трассировок в полевых условиях

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

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

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

Заключение

Показатель "Слишком долгая работа частичных запретов блокировки" в Android Vitals – это лишь малая часть того, что мы делаем, чтобы помочь разработчикам снизить расход батареи и повысить качество приложений. 

Правильно настроив запрет блокировки, вы сможете значительно оптимизировать расход заряда батареи. Чтобы ваше приложение было успешным в Google Play, используйте альтернативные API, следуйте рекомендациям по запрету блокировки и применяйте эффективные инструменты отладки, такие как инспектор фоновых задач, трассировка системы и ProfilingManager.

Автор:
Продолжить чтение