À partir d'Android 17, les applications ciblant Android 17 ou 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 les images manquantes, mais peut casser les clients qui reflètent les champs et méthodes privés MessageQueue.
Android 17 apporte une refonte importante 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 une contention de verrouillage : le thread principal pouvait être bloqué par un thread en 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 verrouillage, les structures de données internes ont été complètement modifiées.
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 certaines bibliothèques de test populaires, vous devrez les mettre à jour pour qu'elles soient compatibles avec la nouvelle implémentation MessageQueue.
Espresso
Espresso est couramment utilisé pour les tests d'UI. La bibliothèque Espresso doit savoir quand le thread principal est inactif pour pouvoir affirmer correctement l'état de l'UI. Les versions antérieures d'Espresso s'appuyaient sur des techniques de réflexion qui ne sont plus compatibles avec MessageQueue sans verrouillage.
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 internes.
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'une version débogable.
Si votre application cible Android 17, le nouveau comportement est activé par défaut. Si vous constatez 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 est la cause.
Vous pouvez activer ou désactiver la modification de deux manières :
Le menu Modifications de la compatibilité de l'application dans les Options pour les développeurs.
En exécutant la commande ADB suivante :
adb am compat disable USE_NEW_MESSAGEQUEUE <your-package-name>
Cela rétablit l'ancienne implémentation basée sur le verrouillage dans votre application, ce qui vous permet de déterminer si le problème est dû à un changement de comportement de la file d'attente des messages.