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

Запрет блокировки может снизить производительность устройства. Если вам нужно использовать запрет блокировки, важно сделать это правильно. В этом документе приведены рекомендации, которые помогут вам избежать распространенных проблем с запретом блокировки.

Укажите правильное название запрета блокировки

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

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

Убедитесь, что приложение открыто на переднем плане.

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

Если активная служба не подходит для вашего приложения, то, скорее всего, вам не стоит использовать и запрет блокировки. Ознакомьтесь с документацией Choose the right API to keep the device awake (Как выбрать подходящий API, чтобы устройство не переходило в спящий режим), чтобы узнать, как выполнять задачи, когда приложение неактивно.

Используйте простую логику

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

Убедитесь, что запрет блокировки всегда снимается

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

Kotlin

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

Java

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() гарантирует, что запрет блокировки будет снят, даже если возникнет исключение:

Kotlin

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

Java

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