Следуйте рекомендациям по блокировке пробуждения

Использование функции Wake Lock может снизить производительность устройства. Если вам необходимо использовать функцию Wake Lock, важно делать это правильно. В этом документе описаны некоторые рекомендации, которые помогут вам избежать распространённых ошибок, связанных с Wake Lock.

Правильно назовите блокировку пробуждения

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

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

Убедитесь, что ваше приложение отображается на переднем плане.

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

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

Сохраняйте логику простой

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

Убедитесь, что блокировка пробуждения всегда отключена.

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

Котлин

@Throws(MyException::class)
fun doSomethingAndRelease() {
    wakeLock.apply {
        acquire()
        doTheWork() // can potentially throw MyException
        release()   // does not run if an exception is thrown
    }
}

Ява

void doSomethingAndRelease() throws MyException {
    wakeLock.acquire();
    doTheWork();         // can potentially throw MyException
    wakeLock.release();  // does not run if an exception is thrown
}

Проблема здесь в том, что метод doTheWork() может сгенерировать исключение MyException . Если это происходит, метод doSomethingAndRelease() распространяет исключение наружу, и оно никогда не доходит до вызова release() . В результате блокировка пробуждения устанавливается, но не снимается, что очень плохо.

В исправленном коде doSomethingAndRelease() гарантирует снятие блокировки пробуждения, даже если возникло исключение:

Котлин

@Throws(MyException::class)
fun doSomethingAndRelease() {
    wakeLock.apply {
        try {
            acquire()
            doTheWork()
        } finally {
            release()
        }
    }
}

Ява

void doSomethingAndRelease() throws MyException {
    try {
        wakeLock.acquire();
        doTheWork();
    } finally {
        wakeLock.release();
    }
}