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

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

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

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

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

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

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

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

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

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

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

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

Котлин

@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() . Результатом является то, что wake-блокировка получена, но не снята, что очень плохо.

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

Котлин

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

Ява

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