Aprovechando el analizador de APK

Wojtek Kaliciński

Follow

23 de noviembre, 2016 – 6 min read

Una de mis adiciones recientes favoritas a Android Studio es el Analizador APK, que puedes encontrar en el menú superior en Build → Analyze APK.

Pro-tip: también puedes arrastrar y soltar archivos APK en el editor para abrirlos

APK Analyzer te permite abrir e inspeccionar el contenido de cualquier archivo APK que tengas en tu ordenador, ya sea construido desde tu proyecto local de Android Studio o adquirido desde tu servidor de construcción u otro repositorio de artefactos. No tiene que ser construido desde cualquier proyecto que tengas abierto en Android Studio y no necesitas el código fuente de ese APK en particular.

Nota: APK Analyzer funciona mejor con builds de lanzamiento. Si necesitas analizar una compilación de depuración de tu aplicación, asegúrate de que estás utilizando un APK que no está instrumentado para Instant Run. Para obtenerlo, puedes utilizar el comando Build → Build APK. Puedes ver si has abierto un APK instrumentado para la ejecución instantánea comprobando la presencia de un archivo instant-run.zip dentro del archivo.

Usar el analizador de APK es una gran manera de hurgar en los archivos APK y aprender sobre su estructura, verificar el contenido del archivo antes de liberarlo o depurar algunos problemas comunes, incluyendo el tamaño del APK y los problemas de DEX.

El analizador de APK puede darte mucha información útil y procesable sobre el tamaño de la aplicación. En la parte superior de la pantalla, se puede ver el tamaño del archivo bruto, que es sólo el tamaño del APK en el disco. El tamaño de la descarga muestra una estimación de la cantidad de datos que se utilizará para descargar su aplicación teniendo en cuenta la compresión aplicada por el Play Store.

La lista de archivos y carpetas se clasifica por el tamaño total en orden descendente. Esto hace que sea grande para la identificación de la fruta colgante baja de la optimización del tamaño de APK. Cada vez que profundizas en una carpeta, puedes ver los recursos y otras entidades que ocupan más espacio en tu APK.

Recursos ordenados en orden descendente según su tamaño

En este ejemplo, al examinar un APK en busca de posibles reducciones de tamaño, pude notar inmediatamente que una animación PNG de 3 fotogramas es lo más grande de nuestros recursos dibujables, con un peso de 1.5MB, y eso es sólo para la densidad xxhdpi!

Como estas imágenes parecen candidatas perfectas para ser almacenadas como vectores, encontramos los archivos de origen de las ilustraciones y los importamos como VectorDrawables utilizando el nuevo soporte PSD en la herramienta de importación de Activos Vectoriales en Android Studio 2.2.

Al pasar por el mismo proceso para la otra animación restante (instruction_touch_*.png) y eliminando estos archivos PNG en todas las densidades, pudimos ahorrar más de 5MB. Para mantener la compatibilidad con versiones anteriores utilizamos VectorDrawableCompat de la biblioteca de soporte.

Mirando otras carpetas de recursos, fue fácil detectar algunos archivos WAV sin comprimir que se podían convertir a OGG, lo que supuso un ahorro aún mayor sin tocar una línea de código.

Buscando en otras carpetas del APK

Lo siguiente en la lista de cosas a comprobar era la carpeta lib/, que contiene bibliotecas nativas para las tres ABIs que soportamos.

Se tomó la decisión de utilizar el soporte de APK splits en nuestro build de Gradle para crear versiones separadas de la app para cada ABI.

Rápidamente revisé el AndroidManifest.xml a continuación y me di cuenta de que a <application> le falta el atributo android:extractNativeLibs. Poner este atributo en false puede ahorrar algo de espacio en el dispositivo ya que evita copiar las librerías nativas del APK al sistema de archivos. El único requisito es que los archivos estén alineados con la página y se almacenen sin comprimir dentro del APK, lo cual es compatible con el nuevo empaquetador en el plugin de Android Gradle versión 2.2.0+.

El AndroidManifest.xml completo visto en APK Analyzer

Después de hacer estas modificaciones, tenía curiosidad por ver cómo se comparaba la nueva versión de la app con la anterior. Para ello, comprobé el código fuente del commit de git con el que empecé, compilé el APK y lo guardé en otra carpeta. Luego utilicé la función Comparar con… para ver un desglose de las diferencias de tamaño entre las builds antiguas y las nuevas.

Comparación del APK – accede a través del botón de la parte superior derecha

Hemos avanzado mucho en los recursos y las librerías nativas, ahorrando un total de 17MB con muy pocos cambios en la app. Sin embargo, puedo ver que el tamaño de nuestro DEX retrocedió, con el classes2.dex creciendo en 400KB.

Debugging DEX issues

En este caso, la diferencia vino de actualizar nuestras dependencias a versiones más nuevas y añadir nuevas bibliotecas. Proguard y Multidex ya estaban habilitados para nuestras construcciones, así que no hay mucho que se pueda hacer sobre nuestro tamaño DEX. Aún así, el analizador APK es una gran herramienta para depurar cualquier problema con esta configuración, especialmente cuando estás habilitando Multidex o Proguard para tu proyecto por primera vez.

Explorando el contenido de las clases.dex

Cuando haces clic en cualquier archivo DEX, verás un resumen de cuántas clases y métodos define, y cuántas referencias totales contiene (son las referencias las que cuentan contra el límite de 64K en un solo archivo DEX). En esta captura de pantalla de ejemplo, la aplicación está a punto de alcanzar el límite, lo que significa que necesitará que MultiDex divida las clases en archivos separados en un futuro próximo.

Puedes profundizar en los paquetes para ver cuáles están utilizando todas las referencias. En este caso, podemos ver que la biblioteca de soporte y los servicios de Google Play son los principales causantes de esta situación:

Cuentas de referencias por paquete

Una vez que hayas habilitado MultiDex y compilado tu aplicación, notarás un segundo archivo classes2.dex (y posiblemente classes3.dex, y así sucesivamente). La solución MultiDex en el plugin gradle de Android calcula qué clases son necesarias para iniciar tu aplicación y las pone en el archivo primario classes.dex, pero en el raro caso de que no funcione y obtengas una ClassNotFoundException, puedes usar APK Analyzer para inspeccionar los archivos DEX, y luego forzar que las clases que faltan se pongan en el archivo DEX primario.

Te encontrarás con problemas similares cuando habilites Proguard y uses clases o métodos por reflexión o desde diseños XML. El analizador de APK puede ayudarte a verificar que tu configuración de Proguard es correcta, permitiéndote comprobar fácilmente si los métodos y clases que necesitas están presentes en el APK y si están siendo renombrados (ofuscados). También puedes asegurarte de que las clases que quieres que desaparezcan se han eliminado realmente, y no están ocupando tu precioso número de métodos de referencia.

Tenemos curiosidad por saber qué otros usos encuentras para el Analizador de APK y qué otras características te gustaría ver integradas en la herramienta.

Deja un comentario