Suivre les bonnes pratiques concernant les wake locks

L'utilisation d'un wakelock peut nuire aux performances de l'appareil. Si vous devez utiliser un verrouillage de réveil, il est important de le faire correctement. Ce document présente quelques bonnes pratiques qui peuvent vous aider à éviter les écueils courants des wake locks.

Nommer correctement le wakelock

Nous vous recommandons d'inclure le nom du package, de la classe ou de la méthode dans la balise wakelock. De cette façon, en cas d'erreur, il est plus facile de trouver l'emplacement dans votre code source où le verrouillage de réveil a été créé. Voici quelques conseils supplémentaires :

  • N'indiquez aucune information permettant d'identifier personnellement l'utilisateur dans le nom, comme une adresse e-mail. Si l'appareil détecte des informations personnelles dans la balise de verrouillage de réveil, il enregistre _UNKNOWN au lieu de la balise que vous avez spécifiée.
  • N'obtenez pas le nom de la classe ou de la méthode par programmation, par exemple en appelant getName(). Si vous essayez d'obtenir le nom par programmation, il risque d'être obscurci par des outils tels que ProGuard. Utilisez plutôt une chaîne codée en dur.
  • N'ajoutez pas de compteur ni d'identifiants uniques pour réactiver les balises de wakelock. Le code qui crée un wake lock doit utiliser la même balise à chaque exécution. Cette pratique permet au système d'agréger l'utilisation du verrouillage de réveil de chaque méthode.

Assurez-vous que votre application est visible au premier plan

Lorsqu'un verrouillage de réveil est actif, l'appareil consomme de l'énergie. L'utilisateur de l'appareil doit être informé de cette opération. Pour cette raison, si vous utilisez un wakelock, vous devez afficher une notification à l'utilisateur. En pratique, cela signifie que vous devez obtenir et conserver le wakelock dans un service de premier plan. Les services de premier plan sont nécessaires pour afficher une notification.

Si un service de premier plan n'est pas le bon choix pour votre application, vous ne devriez probablement pas non plus utiliser de verrouillage de réveil. Consultez la documentation Choisir la bonne API pour maintenir l'appareil allumé pour découvrir d'autres façons de travailler lorsque votre application n'est pas au premier plan.

Simplifiez la logique

Assurez-vous que la logique d'acquisition et de libération des wakelocks est aussi simple que possible. Lorsque votre logique de wakelock est liée à des machines d'état, à des délais d'exécution, à des pools d'exécuteurs ou à des événements de rappel complexes, tout bug subtil dans cette logique peut entraîner le blocage du wakelock plus longtemps que prévu. Ces bugs sont difficiles à diagnostiquer et à déboguer.

Vérifier que le wakelock est toujours libéré

Si vous utilisez un wakelock, vous devez vous assurer que chaque wakelock que vous acquérez est correctement libéré. Ce n'est pas toujours aussi simple qu'il y paraît. Par exemple, le code suivant présente un problème:

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
}

Le problème ici est que la méthode doTheWork() peut générer l'exception MyException. Si tel est le cas, la méthode doSomethingAndRelease() propage l'exception vers l'extérieur et elle n'atteint jamais l'appel release(). Le résultat est que le verrouillage de réveil est acquis, mais pas libéré, ce qui est très mauvais.

Dans le code corrigé, doSomethingAndRelease() s'assure de libérer le verrouillage de réveil même si une exception est générée:

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();
    }
}