DDMS Android : Un guide pour la console Android ultime

Publié: 2022-03-11

Le développement est une affaire délicate. La cible continue de bouger, de nouvelles technologies et de nouveaux domaines prennent périodiquement vie, de nouveaux outils apparaissent de temps en temps et les langues changent dans ce qui semble être un chaos géré.

Pourtant, même avec tous ces changements, les règles fondamentales restent les mêmes. L'une des plus importantes de ces règles sous-jacentes stipule que pour créer un logiciel vraiment génial, vous devez acquérir une introspection profonde, continue et détaillée de votre système d'exécution. Diagnostics , débogage et profilage sont des termes parfois utilisés dans ce contexte, mais la règle va plus loin. Un développeur de haut niveau « sent » littéralement son système. Il sait ce qui causera l'attente de la libération de plus de mémoire, ce qui entraînera la famine du processeur, quelles actions entraîneront des E/S étendues ou un accès réseau, ce qui ralentira l'ensemble de son fonctionnement.

Il n'y a vraiment aucun moyen de contourner cela. Vous pourriez être un développeur très intelligent écrivant du code génial, mais, jusqu'à ce que vous n'ayez pas la compétence ci-dessus, à savoir être capable de surveiller et d'étudier les détails du comportement d'exécution de votre système, vous échouerez toujours lorsqu'il s'agit de fournir vraiment top notch applications.

En fait, après avoir acquis un peu d'expérience, vous détecterez toute une catégorie de « maladies du code » qui peuvent être attribuées à la négligence de la règle de l'introspection : en bref, l'écriture de code (parfois du code intelligent) sans surveillance continue de ses effets sur la plate-forme réelle .

DDMS sous Android : mon arme de choix pour l'introspection

Heureusement pour nous, la communauté Android a réussi à fournir autant d'outils d'introspection de premier ordre. Stetho de Facebook est parmi les meilleurs, ARO ("Application Resource Optimizer") d'AT & T est un peu plus ancien mais toujours de premier ordre, avec probablement la meilleure console de surveillance réseau, tandis que LeakCanary adopte une approche beaucoup plus limitée en se concentrant (et en faisant très bien à it) sur la bibliothèque de détection de fuite de mémoire d'exécution. Pour faire court, les outils de débogage Android ne manquent pas.

Pourtant, le diamant de la couronne, l'outil d'introspection auquel faire confiance lorsque des données cruciales, précises et bien formatées doivent être extraites concernant le comportement d'exécution de votre application est toujours le bon vieux Dalvik Debug Monitor Server (DDMS) dans Android Studio, qui est avec nous (hélas sous-utilisé par tant d'équipes) depuis l'époque du plugin Eclipse Android.

Quelle est l'importance du DDMS dans le développement Android ? Eh bien, savoir ce que je sais maintenant sur le DDMS et la surveillance des applications mobiles en général, disons il y a 5-6 ans, en tant que développeur Android moins expérimenté, m'aurait épargné beaucoup de maux de tête et de nuits de débogage.

Illustration de la couverture du DDMS Android : Débogage du développeur avec le DDMS.

Et le fait est que le DDMS est si simple à maîtriser !

Bien sûr, une grande partie de son utilisation correcte, comme pour tout autre outil logiciel, vient avec l'expérience. Vous devez perfectionner vos compétences professionnelles pendant un certain temps jusqu'à ce que vous deveniez vraiment bon dans la surveillance des performances d'exécution. Mais même en quelques heures, disons après avoir lu cet article, si vous suivez mes suggestions et les appliquez sur votre prochaine application, les résultats seront incroyables ! Le profilage et le réglage de systèmes même complexes ne sont pas si difficiles. Cela peut aussi être amusant!

Une question est souvent posée concernant la différence entre les développeurs mobiles novices et de niveau maître. La maîtrise du DDMS sous Android - ou en termes généraux, des capacités de profilage et d'introspection des applications - est l'une de ces différences majeures.

Remarque : Pour devenir un développeur de premier plan, vous devez en grande partie utiliser les meilleures bibliothèques disponibles dans votre domaine. Dans un précédent article de Toptal, j'ai répertorié certaines des meilleures bibliothèques de développement disponibles pour Android. Dans un sens, cet article est une suite de l'article "bibliothèque" et couvre l'un des nombreux outils Android. Inutile de dire que si vous souhaitez améliorer vos compétences de développeur Android, lisez-le maintenant !

Un guide rapide sur DDMS dans Android Studio

Et maintenant, sans plus tarder, plongeons maintenant dans la description de DDMS, l'un des outils de développement Android ultimes.

Lorsque vous pesez les efforts par rapport aux avantages, aucun autre outil ne peut probablement améliorer la qualité de votre application et vous aider à localiser les bogues vraiment désordonnés et insaisissables qu'elle peut contenir. Mais encore, pour une raison quelconque (la paresse, quelqu'un ?), tant d'équipes n'utilisent pas le DDMS.

Commençons par un cours accéléré sur DDMS :

DDMS est accessible via Studio > Tools > Android > Android Device Monitor et en cliquant sur le bouton DDMS dans le menu. Vous pouvez également placer est comme icône de raccourci (je fais) dans votre panneau supérieur.

Une fois ouvert, voici ce que vous verrez :

Capture d'écran : Accéder au DDMS via Android Device Monitor

Le panneau de gauche permet la sélection de l'appareil/de l'application et la console de droite vous offre plusieurs vues, chacune dans son propre onglet, chacune présentant une vue spécifique de votre application.

Les principaux services fournis par Dalvik Debug Monitor Server sont :

  • Statistiques d'utilisation de la mémoire de l'application (statistiques totales sur le tas et l'allocation d'objets)
  • Statistiques sur les threads d'application
  • Capture d'écran de l'appareil
  • Explorateur de fichiers de périphérique
  • Usurpation d'appels entrants et de SMS
  • Usurpation des données de localisation
  • Logcat

Pour obtenir la valeur actuelle de la mémoire de tas utilisée par votre application, procédez simplement comme suit :

  • Connectez l'appareil sur lequel votre application s'exécute
  • Cliquez sur le bouton Mettre à jour le tas pour activer la collecte des statistiques du tas
  • Ouvrez l'onglet Tas
  • Cliquez sur "Cause GC" pour forcer une exécution du GC. Ce n'est qu'après cette exécution que la collecte de données de tas commencera
  • Gardez l'onglet ouvert, continuez à travailler sur votre application et re-cliquez périodiquement sur "Cause GC" pour actualiser les données statistiques du tas

Cette dernière ligne nécessite probablement des explications supplémentaires. L'utilisation de la mémoire est l'une de ces valeurs analytiques où sa dynamique est bien plus importante que la valeur initiale. Pour la plupart des applications, nous ne nous soucierons pas beaucoup de la valeur d'utilisation initiale du tas. Nous nous soucierons beaucoup de la progression de cette valeur, car elle nous fournira une indication claire de l'un des véritables cauchemars qui attendent les développeurs mobiles : les fuites de mémoire Android :

Capture d'écran : les données de tas sont utilisées pour identifier une fuite de mémoire Android dans DDMS

Mon utilisation du module heap stat est simple ; dans le cadre du cycle de vie du développement de l'application, après avoir introduit des modifications qui devraient avoir un impact sur l'utilisation du tas, j'activerai le module "Cause GC" pour init la collecte de statistiques, activer (généralement plus d'une fois) les positions à forte intensité de tas de mon application, et périodiquement "Cause GC" pour rafraîchir. Si l'utilisation du tas ne cesse de croître, j'ai une fuite de mémoire entre les mains et je dois la résoudre (détails sur comment - ci-dessous). Sinon, et quelle que soit la taille réelle du tas, je suis bon.

Si une fuite de mémoire est détectée, le prochain outil que j'utiliserai est l'Object Allocation Tracker. Voyons ce qu'il peut faire pour la gestion de la mémoire sous Android.

Suivi d'allocation d'objets

Le traqueur d'allocation, en termes simples, vous fournira les informations nécessaires pour déterminer qui est la partie à « blâmer » pour la taille actuelle du tas. Ce module vous indiquera de quels threads et méthodes proviennent les commandes d'allocation en temps réel, ce qui le rend inestimable pour l'analyse de la mémoire dans Android.

Pour commencer le suivi, procédez comme suit :

  • Sélectionnez le dispositif/processus pertinent comme précédemment
  • Passez à l'onglet Suivi des allocations et cliquez sur Démarrer le suivi pour commencer.
  • À partir de là, toutes les nouvelles allocations seront suivies
  • Cliquez sur "Obtenir les allocations" pour obtenir une vue de liste de toutes les dernières allocations (les dernières depuis le dernier "début")
  • Pour savoir qui est l'autorité d'attribution, cliquez sur une ligne spécifique dans la liste

Object Allocation Tracker dans DDMS, interface utilisateur

Maintenant, d'après ma propre expérience, effectuer des actions gourmandes en allocations sur votre application, puis cliquer sur "Obtenir des allocations" pour afficher les compteurs d'allocation devrait généralement vous diriger directement vers la fuite ; parfois, soit lorsque la fuite n'est pas linéaire (c'est-à-dire qu'elle se produit de temps en temps) OU lorsque votre application contient plusieurs fuites qui pourraient ne pas fonctionner. Dans de tels cas, et je n'en ai pas rencontré beaucoup, vous devrez créer manuellement un fichier de vidage HPROF et l'analyser. L'analyse de la mémoire et la gestion de la mémoire Android ne seront pas traitées en profondeur dans cet article. Voir ici pour quelques pistes.

Console d'informations sur les discussions : l'utilisation du processeur Android simplifiée

Bien connus de tout développeur, les chemins synchrones de la logique d'exécution sont regroupés en threads, chacun constituant un flux d'exécution en série au sein de votre application. Littéralement, toutes les applications utilisent plus d'un seul thread d'exécution. Certains d'entre eux en utilisent des dizaines.

Un examen global des problèmes potentiels lors de l'utilisation des threads sort du cadre de cet article. Concentrons-nous alors sur un seul, à savoir la famine des threads, qui est le principal problème pour lequel vous visiteriez la console d'informations sur les threads.

Dans toutes les applications mobiles, différents threads se disputent le temps CPU. Il n'y en a tout simplement pas assez pour tout le monde. Que se passe-t-il si, pour une raison quelconque, un ou plusieurs si ces threads n'obtiennent pas le temps d'exécution dont ils ont besoin ? Généralement de mauvaises choses. Le système ne se comportera pas comme vous l'aviez prévu, ce qui est toujours une mauvaise idée. Les raisons potentielles de ce problème peuvent être la définition d'une faible priorité, d'autres threads s'exécutant simultanément en se définissant eux-mêmes avec une priorité trop élevée, passer beaucoup de temps sur les moniteurs de synchronisation, etc. Tous notoirement difficiles à détecter par la seule revue de code.

Console de thread Android DDMS à la rescousse !

Thread Info Console dans DDMS, interface utilisateur

Lorsque vous entrez dans la vue des threads, vous verrez une liste composée d'enregistrements de threads, chacun contenant le nom et l'ID du thread, et deux compteurs supplémentaires appelés utime et stime. Utime mesure le temps total passé par le thread à exécuter le code utilisateur (pensez à vos fonctions et aux bibliothèques tierces), tandis que stime mesure le temps total passé sur le code système (veille, synchronisation, appels système - le lot). Le ppremier - utime - sera généralement plus intéressant pour nous, bien que je puisse penser à des problèmes qui se manifesteront principalement par le compteur stime.

OK, nous avons notre code en cours d'exécution, y compris plusieurs threads, et nous voulons nous assurer que tous nos threads obtiennent leur part de temps CPU. Pour cela, nous laissons d'abord notre système fonctionner pendant un certain temps, puis ouvrons l'onglet de fil et commençons à rechercher des valeurs utime "particulières". Zéro peut certainement représenter un problème - le thread n'a littéralement aucun temps CPU et aucune utilisation du CPU. Mais des valeurs trop élevées peuvent représenter un aspect différent du même problème : à savoir, des threads dont la priorité est si élevée qu'elle en affame d'autres.

Notez que pour un type de threads, une valeur utime nulle ou proche de zéro n'indiquera pas un problème réel. Ce sont les threads liés aux E/S, les threads qui effectuent principalement l'accès au réseau ou au disque (ou à la base de données). Ces threads doivent passer la plupart de leur temps à attendre l'arrivée des données ou à bloquer les appels système en attente, aucune de ces actions n'augmente le compteur utime. Connaissez vos fils !

Conseil : n'utilisez jamais le nom par défaut du thread. Cela ne signifie rien et vous ne parviendrez généralement pas à le détecter dans les vues DDMS. Au lieu de cela, chaque fois que vous créez un thread ou que vous le récupérez à partir d'un pool de threads, démarrez votre interaction en lui attribuant un nom explicite. Cela vous facilitera la vie plutôt que de déboguer/profiler votre système. J'ajoute généralement le nom de l'application afin de faire la distinction entre les threads générés par Android et ceux générés par mon propre code, par exemple : MyApp-server-connector, MyApp-db-interactor, etc.

Astuce : La priorité d'un thread indique (en gros) la quantité de temps CPU qui lui sera accordée par le planificateur. La priorité attribuée à vos threads de travail est d'une importance cruciale pour les performances globales et la "lisibilité" de votre application, et dans de nombreux cas, elle peut faire la différence entre un comportement rapide et un comportement lent et cahoteux. La règle ici est simple : la priorité par défaut attribuée par Android, qui est NORMAL=5, n'est presque toujours pas celle que vous souhaitez utiliser. Au lieu de cela, pour la plupart des threads de travail, vous souhaitez un impact bien moindre sur l'utilisation globale du processeur. Pour ce faire, au démarrage d'un thread, définissez sa priorité sur une valeur inférieure, j'utilise généralement la priorité = 3.

Console de statistiques réseau

Les statistiques réseau visent à vous permettre de surveiller les canaux de communication entrants et sortants vers votre application d'une manière raisonnablement lisible par l'homme.

L'axe des y dans le diagramme de réseau représente la vitesse de transfert de la transmission mesurée en Ko/seconde, tandis que l'axe des x représente le temps écoulé en secondes. Par conséquent, pour obtenir une estimation rapide de la taille de la transmission, essayez d'estimer la surface du pic pertinent. Au bout d'un moment, cela devient assez facile.

Notez qu'une fois cette console entrée, vous devrez cliquer sur le bouton supérieur "activer" pour que les mesures du réseau commencent à apparaître.

Avant que la console réseau n'atteigne son niveau actuel, les développeurs devaient généralement recourir à des applications de renifleur (certaines le font encore) pour obtenir des informations similaires.

La grande chose à propos de cette console est la façon dont elle visualise l'un des principaux comportements d'épuisement de la batterie, celui de la communication continue de petite taille de paquet. Comme beaucoup d'entre vous le savent, ce qui fera de votre application un épuiseur de batterie, ce ne sont pas les cinq minutes de mise en réseau intensive qu'elle effectue, mais plutôt les longues périodes de réseautage court et répétitif, par exemple, pour le maintien en vie, les diagnostics ou les mises à jour de statut.

Une fois qu'un tel modèle est détecté, et que l'affichage visuel des paquets de la console réseau le rend toujours aussi facile, pensez immédiatement au traitement par lots. Puis-je regrouper plusieurs petites transmissions en une seule grande? L'impact de ce changement sur la batterie ne manquera pas de faire passer les applications d'un épuiseur de batterie à une catégorie bien comportée !

Console de statistiques réseau dans DDMS

Conseil : ne chargez jamais une image en mémoire telle quelle. Il s'agit d'un crash de mémoire insuffisante en attente de se produire. Au lieu de cela, effectuez un chargement réduit, ou mieux encore, utilisez une bibliothèque tierce pour gérer la mise à l'échelle pour vous.

Bien que vous n'utilisiez que rarement ces informations, notez que le DDMS s'appuie sur la pile Android Debug Bridge (ADB) pour transmettre les données en retour/depuis l'appareil. Si le DDMS ne parvient pas à afficher votre application ou se fige au milieu d'une session DDMS, votre meilleur pari sera d'ouvrir une console et de taper :

 adb devices

pour vous assurer que votre appareil est accessible et autorisé avec ADB. Si ce n'est pas le cas, dans de nombreux cas, le redémarrage de votre serveur ADB local devrait résoudre le problème :

 adb kill-server adb devices # restarts the adb server and displays all detected devices

Si vous rencontrez toujours des problèmes et que votre application est installée sur un appareil physique, essayez de déconnecter toutes les instances de l'émulateur. Pourquoi? Étant donné que DDMS se connecte à la fois aux périphériques physiques et aux instances d'émulateur, la valeur par défaut étant la dernière.

Exemple d'utilisation réelle du DDMS : une application s'arrête (pas de plantage, juste des arrêts). L'utilisateur se précipite immédiatement vers le poste de travail à proximité, se connecte à l'USB et ouvre le DDMS en vue thread pour découvrir la pile de threads "thread échoué" trace de pile - dans mon cas, en raison d'un blocage de synchronisation qui, une fois détecté, a été facilement résolu en changeant.

Conseil : Si la mémoire RAM standard allouée à votre application par Android n'est pas suffisante, comme cela peut arriver, par exemple, pour les applications gourmandes en contenu multimédia, notez que vous pouvez gagner environ 15 à 20 % de mémoire supplémentaire sur la plupart des appareils en levant l'indicateur de manifeste _largeHeap : https://developer.android.com/guide/topics/manifest/application-element.html_

Émulation de l'état de l'appareil dans Android DDMS

En règle générale, les applications mobiles ne sont pas des constructions linéaires. Au lieu de cela, ils déploient des stratégies de sensibilisation qui leur permettent de surveiller et de réagir aux changements d'état de l'appareil. Une application peut, par exemple, écouter les appels entrants ou les messages texte, peut réaligner son état en fonction de l'état du réseau et peut suivre et réagir aux changements d'emplacement de l'appareil.

Un exemple trivial pour ce dernier serait une application GPS. La plupart d'entre nous ne développons pas de telles applications (hélas, le marché n'est pas assez grand…) mais, dans de nombreux cas, nous déployons une logique, qui dépend de l'emplacement, qu'il s'agisse d'une simple vue cartographique de la position actuelle de l'utilisateur, du suivi d'itinéraire , ou un affichage de données sensibles à l'emplacement.

Tester de telles conditions sensibles à l'état est notoirement complexe, parfois plus que d'écrire le code réel. Si vous avez un appareil physique avec SIM, vous pouvez bien sûr émettre et recevoir des appels et des SMS. Changer l'état de téléphonie de votre appareil est beaucoup plus difficile mais peut toujours être fait. Les changements de lieu de test pourraient être plus délicats, bien que se promener en ville avec votre ordinateur portable soit une option…

Mais quand même, comment gérerions-nous les instances d'émulateur ? Comment pouvons-nous les tester pour ces changements ?

Exemple d'émulation d'état de périphérique dans DDMS

DDMS à la rescousse, encore une fois. L'une des fonctionnalités les plus puissantes mais souvent négligées du DDMS est sa capacité à émettre des événements fictifs ("spoof") dans une instance d'émulateur en cours d'exécution. DDMS peut émettre un appel à partir d'un numéro spécifique vers l'émulateur, envoyer un SMS, modifier les données d'état de la téléphonie, etc.

Une fois arrivés dans l'émulateur, tous ces événements usurpés ne pourront plus être distingués des événements "réels", c'est-à-dire comme s'ils étaient reçus par les capteurs matériels sous-jacents. Plus précisément, tous les récepteurs de votre application concernée seront activés de la même manière qu'ils le feraient lors de la réception d'un véritable message d'appel/SMS.

L'activation de l'état de la téléphonie et des actions est assez simple :

Pour tester votre application en cas de faible connectivité réseau (ce que vous devriez faire dans toute application centrée sur le réseau), accédez à la section État de la téléphonie et définissez les valeurs de vitesse et de latence sur les valeurs souhaitées. J'utilise généralement la valeur GPRS pour les deux comme un moyen efficace d'émuler une faible connectivité, mais n'hésitez pas à définir vos propres valeurs.

Pour simuler des appels téléphoniques ou des SMS, accédez à la section Action de téléphonie, définissez le numéro de téléphone d'origine, ajoutez un message textuel si nécessaire et lancez. Cet outil est particulièrement efficace lorsque vous avez défini un itinéraire de code dédié pour les appels depuis l'étranger et que vous souhaitez le tester en respectant votre budget.

Les choses deviennent plus intéressantes lorsqu'il s'agit de se moquer d'un nouvel emplacement.

Si tout ce que vous visez est de définir un nouvel emplacement pour votre instance d'émulateur, choisissez Manuel, définissez les valeurs de latitude/longitude souhaitées et appuyez sur Envoyer.

Contrôles de localisation manuels utilisés pour l'usurpation d'identité dans le DDMS

Mais que se passe-t-il si, au lieu de définir un emplacement fixe, vous souhaitez que votre application suive un itinéraire prédéfini, par exemple, examinez son comportement lorsque l'utilisateur se déplace d'une ville à l'autre ? Un tel test peut avoir une grande valeur pour toute application basée sur une carte ainsi que pour d'autres applications sensibles à la localisation qui définissent leur fenêtre de données par emplacement d'utilisateur. Ici, vous voudrez voir que le déplacement de l'emplacement à une vitesse différente maintiendra la fenêtre de données affichée à jour.

Pour cela, nous utiliserons un format spécial appelé KML, qui a été spécifiquement développé pour être utilisé avec Google Earth, et qui représente des itinéraires, ou des chemins, comme un ensemble de points connectés dans l'espace, qui peuvent être par des appareils compatibles GPS.

GPX est un format de chemin alternatif pris en charge par DDMS. À toutes fins pratiques, ces deux éléments doivent être considérés comme interchangeables lorsqu'ils sont utilisés pour l'usurpation de localisation mobile.

Passons maintenant en revue les étapes de définition d'un itinéraire fictif dans l'émulateur.

  1. Créer un itinéraire. De loin, le moyen le plus simple serait d'utiliser l'option de direction de Google Maps en définissant l'origine et la destination appropriées.

Usurpation de position dans DDMS avec Google Maps

  1. Une fois l'itinéraire affiché sur la carte, accédez à la ligne d'adresse et copiez l'URL

  2. Avec l'URL dans le presse-papiers, accédez au visualiseur GPS, collez-la dans la zone de texte "Fournir l'URL", puis cliquez sur le bouton Convertir :

Usurpation d'emplacement DDMS : configuration du Wisualizer GPS

et cliquez pour télécharger le fichier GPX résultant (avec un nom un peu confus, par exemple, 20170520030103-22192-data.gpx)

  1. En revenant à DDMS Location Control, ouvrez l'onglet GPX, cliquez sur Load GPX et sélectionnez le fichier nouvellement téléchargé

Importation de GPX dans DDMS Location Control

  1. Avaient fini! Vous pouvez maintenant naviguer entre les différents emplacements de l'itinéraire en cliquant sur les boutons Précédent et Suivant, ou en cliquant sur le bouton Lecture pour parcourir automatiquement l'itinéraire à une vitesse définie.

Vous n'avez pas besoin de créer votre propre itinéraire. Beaucoup d'itinéraires à télécharger à partir de sites tels que OpenStreetMap (voir la section 'Traces GPS').

Enfin, veuillez noter que contrairement aux anciennes versions de DDMS, où le chargement du fichier d'itinéraire était un jeu d'enfant, les versions plus récentes peuvent nécessiter des essais et des erreurs lors du chargement d'un itinéraire spécifique.

Par exemple, il semble que seul GPX 1.1 soit pris en charge par DDMS. Les nouvelles versions de GPX peuvent nécessiter des ajustements manuels.

De plus, le format de waypoint GPX n'est plus pris en charge. Utilisez plutôt le format GPX Track :

 <trk> <name /> <cmt /> <trkseg> <trkpt lat="27.0512" lon="-80.4324"> <ele>0</ele> <time>2017-02-02T08:01:41Z</time> </trkpt> </trkseg> </trk>

Déboguer Android : une heure par semaine fait la différence !

Assez de théorie ! Il est maintenant temps de s'entraîner. Je suggère, en supposant que vous soyez un développeur Android, qu'à partir de votre prochain projet, vous ne consacriez qu'une heure par semaine à l'introspection des performances de votre application via DDMS.

Vous serez surpris de la quantité d' informations de qualité (c'est-à-dire des informations qui peuvent être utilisées pour améliorer immédiatement l'état de votre application) que cela vous fournira !

Android DDMS, comme j'en ai été témoin à maintes reprises avec des développeurs débutants, est un outil qui peut grandement améliorer les capacités d'un développeur, à condition qu'il soit maîtrisé et correctement utilisé. La capacité d'un développeur Android à fournir des systèmes de premier ordre augmentera littéralement d'un cran ou deux une fois qu'il aura exploité tout le potentiel du DDMS dans le développement Android. Par conséquent, réserver quelques heures pour faire bon usage du DDMS semble être un investissement intelligent, car il peut grandement améliorer les performances et l'efficacité d'Android.

Soyez l'un des gars intelligents. Utilise le.