À partir d'Android 17, les applications ciblant Android 17 (niveau d'API 37) ou une version ultérieure reçoivent une nouvelle implémentation sans verrouillage de android.os.MessageQueue. La nouvelle implémentation améliore les performances et réduit le nombre d'images manquées, mais peut endommager les clients qui réfléchissent aux champs et méthodes privés de MessageQueue.
Android 17 apporte une refonte majeure du fonctionnement de Looper et Handler en réécrivant la classe MessageQueue sous-jacente.
Depuis la première version du système d'exploitation Android, MessageQueue s'appuie sur un seul verrou pour gérer la file d'attente des tâches du thread principal. Cette conception entraînait souvent des conflits de verrouillage. Le thread principal pouvait être bloqué par un thread d'arrière-plan, ce qui entraînait des pertes d'images et des à-coups de l'UI.
Limiter l'impact
Votre application peut être affectée par ce changement si elle ou ses dépendances s'appuient sur la réflexion d'exécution pour examiner MessageQueue. Évitez d'utiliser la réflexion d'exécution pour inspecter MessageQueue.
Avec l'ancienne implémentation, les développeurs accédaient parfois à des champs privés tels que MessageQueue.mMessages pour inspecter les messages en attente. Avec la nouvelle implémentation sans verrou, les structures de données internes ont complètement changé.
Pour maintenir la compatibilité binaire, Android 17 conserve le champ mMessages, mais dans la nouvelle implémentation, ce champ est toujours nul, qu'il y ait ou non des messages dans la file d'attente.
De plus, si vous utilisez des bibliothèques de test populaires, vous devrez les mettre à jour pour qu'elles soient compatibles avec la nouvelle implémentation de MessageQueue.
Espresso
Espresso est couramment utilisé pour les tests d'UI. La bibliothèque Espresso doit savoir quand le thread principal est inactif pour vérifier correctement l'état de l'UI. Les versions antérieures d'Espresso reposaient sur des techniques de réflexion qui ne sont plus compatibles avec la MessageQueue sans verrou.
Action
Passez à Espresso 3.7.0 ou version ultérieure. Cette version utilise l'API TestLooperManager, en particulier les nouvelles API introduites par Android 16, pour interagir de manière sécurisée avec Looper sans s'appuyer sur les détails d'implémentation interne.
Robolectric
De même, si vous exécutez des tests unitaires à l'aide de Robolectric, vous pouvez rencontrer des problèmes si vos tests reposent sur l'ancien mode Looper.
Action
Passez à Robolectric 4.17 ou version ultérieure. Si vous utilisez @LooperMode(LEGACY), vous devrez migrer vos tests vers le nouveau @LooperMode(PAUSED). Pour en savoir plus, consultez le guide de migration de Robolectric.
Tester le comportement
Vous pouvez tester votre application avec le changement de comportement sur Android 17 sans mettre à jour targetSDK en exécutant la commande suivante :
adb am compat enable USE_NEW_MESSAGEQUEUE <your-package-name>
Cette commande active le MessageQueue sans verrouillage dans votre application, s'il s'agit d'un build débogable.
Si votre application cible Android 17 (niveau d'API 37), le nouveau comportement est activé par défaut. Si vous remarquez un comportement inattendu ou des plantages après avoir ciblé ce niveau d'API, vous pouvez désactiver temporairement la nouvelle implémentation pour vérifier si MessageQueue en est la cause.
Vous pouvez activer ou désactiver la modification à l'aide de l'une des deux options suivantes :
Menu Modifications de la compatibilité de l'application dans Options pour les développeurs.
En exécutant la commande ADB suivante :
adb am compat disable USE_NEW_MESSAGEQUEUE <your-package-name>
Votre application revient ainsi à l'ancienne implémentation basée sur le verrouillage, ce qui vous permet d'identifier si le problème est dû à un changement de comportement de la file d'attente de messages.