Reducción del tamaño del APK usando R8 y ProGuard

  • Implementación de R8 y ProGuard para la eliminación de código muerto y la ofuscación de clases.
  • Uso de Android App Bundles para optimizar la entrega de recursos según el dispositivo del usuario.
  • Sustitución de activos pesados por formatos eficientes como WebP y Vector Drawables.
  • Configuración de módulos dinámicos para descargar funcionalidades bajo demanda.

Reducción del tamaño del APK usando R8 y ProGuard

A medida que nuestras aplicaciones van sumando funciones y se vuelven más complejas, es muy normal que el peso del archivo final se dispare. Esto es un problema serio, porque si una app pesa demasiado, muchos usuarios se lo piensan dos veces antes de darle al botón de instalar o, peor aún, abandonan la descarga a mitad de camino. Además, una aplicación pesada consume más almacenamiento en el móvil y puede acabar afectando la velocidad de respuesta del sistema.

Para evitar que tu proyecto se convierta en un «monstruo» digital, existen diversas estrategias que van desde la limpieza de código hasta la optimización de imágenes. En este artículo vamos a analizar a fondo cómo utilizar herramientas como R8 y ProGuard, así como la magia de los App Bundles, para que tu app sea lo más ligera y rápida posible, asegurando que funcione de lujo incluso en dispositivos de gama baja.

Entendiendo qué es lo que realmente pesa en tu app

Antes de ponernos manos a la obra, hay que saber dónde está la grasa. Normalmente, el tamaño de una aplicación se divide en cuatro grandes bloques. Primero tenemos el código bytecode de Java o Kotlin y sus bibliotecas, que suelen ocupar entre el 30% y 40%. Luego están los recursos como layouts y animaciones, con un peso similar. También contamos con las librerías nativas (C/C++) compiladas para distintas arquitecturas (15-25%) y, finalmente, los assets o archivos brutos (5-15%).

Para no dar palos de ciego, lo ideal es usar el APK Analyzer de Android Studio (yendo a Build > Analyze APK). Esta herramienta te permite ver exactamente cuánto pesan las clases DEX, la carpeta de recursos y las librerías nativas, permitiéndote comparar versiones actuales con anteriores para detectar qué cambio disparó el tamaño del archivo. Para profundizar en este tema, es útil comprender la jerarquía de archivos en Android y cómo se organizan.

Limpieza de código: El salto de ProGuard a R8

La reducción de código es, sin duda, la vía más efectiva para recortar bytes. Aquí es donde entran en juego ProGuard y su sucesor moderno, R8. ProGuard fue el estándar durante años, encargándose de eliminar clases, campos y métodos que no se usan, optimizando el bytecode y ofuscando los nombres para que sean más cortos (y difíciles de leer para quien quiera piratear tu código).

APK, AAB y APKM
Artículo relacionado:
Guía Avanzada de Diferencias entre Formatos APK, AAB y APKM en Android: Todo lo que debes saber para instalar aplicaciones como un experto

Hoy en día, R8 es el compilador predeterminado y hace todo lo que hacía ProGuard, pero mucho mejor y más rápido. R8 implementa un «Tree shaking» más agresivo, fusiona clases con funciones similares y optimiza las enumeraciones convirtiéndolas en enteros. Además, permite la desazucarización (desugaring) para usar funciones modernas de Java 8 en versiones antiguas de Android.

Configuración técnica en el build.gradle

Para activar estas optimizaciones en la versión de lanzamiento, debes configurar el archivo de compilación estableciendo minifyEnabled como true y vinculando los archivos de reglas. Es fundamental usar proguard-android-optimize.txt para aprovechar las optimizaciones máximas. Un ejemplo de configuración básica incluiría mantener las clases de aplicación o aquellas anotadas con @Keep para evitar que R8 las borre por error.

Gestión de reglas para librerías externas

A veces, R8 es demasiado eficiente y borra código que se usa mediante reflexión, provocando errores como ClassNotFoundException. Por eso, librerías como Retrofit, OkHttp o Gson necesitan reglas específicas. Por ejemplo, con Gson es vital preservar los nombres de los campos de los modelos de datos para que la deserialización de JSON no falle. Si encuentras errores tras la ofuscación, el archivo mapping.txt es tu mejor aliado para traducir los rastros de pila (stack traces) y saber dónde ocurrió el fallo.

¿es posible crear una APK sin ser programador?
Artículo relacionado:
Diferencias entre APKM, APKS y XAPK: guía completa de formatos de instalación en Android

Optimización inteligente de recursos

Los recursos suelen ser el punto donde más se desperdicia espacio. Una técnica sencilla pero potente es activar shrinkResources en el build.gradle. Esto elimina los archivos que no tienen ninguna referencia en el código, aunque es importante saber que si llamas a un recurso dinámicamente mediante getIdentifier, deberás declararlo en un archivo keep.xml para que no desaparezca.

Imágenes y Gráficos: Menos es Más

El formato PNG es el culpable de muchos megabytes innecesarios. La recomendación actual es migrar todo a formato WebP, que ofrece una compresión muy superior manteniendo la calidad. Puedes hacer esta conversión directamente en Android Studio haciendo clic derecho sobre la imagen. Para iconos y formas simples, lo ideal es usar Vector Drawables; un solo archivo XML sustituye a cinco versiones de diferentes densidades, simplificando el mantenimiento y reduciendo el peso.

Recortando idiomas y densidades

Muchas librerías externas vienen con traducciones a 50 idiomas que tu app probablemente no soporte. Para limpiar esto, usa la propiedad resConfigs en el defaultConfig, especificando solo los idiomas que realmente utilizas (por ejemplo, "es", "en"). De igual modo, puedes limitar las densidades de pantalla incluidas si sabes que tu público objetivo usa dispositivos modernos, eliminando los recursos ldpi o mdpi que ya nadie usa.

Extraer APK de aplicaciones
Artículo relacionado:
Guía Completa para Extraer el APK de Cualquier Aplicación en Android: Opciones, Seguridad y Tutoriales

Estrategias de Distribución Avanzada

Si quieres dar el golpe definitivo al tamaño del APK, debes dejar de usar APKs universales y pasarte a los Android App Bundles (.aab). En lugar de enviar un archivo gigante con todo lo posible, Google Play genera un APK optimizado para cada dispositivo. Así, un usuario con un móvil ARM64 y pantalla xxhdpi descarga solo lo que su hardware necesita, reduciendo el tamaño de descarga hasta en un 40%.

Módulos de Funciones Dinámicas y Apps Instantáneas

No todo el código tiene que estar disponible desde el primer segundo. A través de los Dynamic Feature Modules, puedes separar partes de la app (como un editor de fotos avanzado o un modo offline) para que se descarguen solo cuando el usuario acceda a esa función. Por otro lado, las Aplicaciones Instantáneas permiten que la gente pruebe tu app sin instalarla, cargando un módulo base extremadamente ligero vía URL o botón de Google Play.

Auditoría de dependencias y detalles finales

A veces el problema no es tu código, sino lo que traes de fuera. Librerías como Guava o Jackson pueden ser muy pesadas; considera sustituirlas por alternativas más ligeras como kotlinx.serialization o Gson. También es recomendable usar fuentes descargables de Google Fonts en lugar de empaquetar archivos TTF pesados en los assets, lo que puede ahorrarte varios megabytes si usas múltiples variantes de una tipografía.

Para cerrar el círculo de optimización, recuerda que Android Go es un mercado creciente. Si quieres que tu app brille en dispositivos con menos de 1GB de RAM, intenta mantener el peso por debajo de los 40MB. Utilizar Android Lint para detectar recursos huérfanos y mantener una disciplina de limpieza constante permitirá que tu aplicación sea eficiente, se instale rápido y ofrezca una experiencia de usuario fluida, independientemente de la potencia del dispositivo.

Actualizaciones para seguridad en Android
Artículo relacionado:
Cómo acelerar y optimizar Android al máximo: guía completa, trucos y recomendaciones imprescindibles

Añadir como fuente preferida en Google