Reduce el tamaño de tu app

A menudo, los usuarios evitan descargar apps que parecen muy pesadas, particularmente en mercados emergentes, donde la conexión 2G y 3G suele ser intermitente o los dispositivos se conectan mediante planes de pago por consumo. En esta página, se describe cómo reducir el tamaño de tu app para aumentar la cantidad de usuarios que la descargan.

Sube tu app con Android App Bundles

La manera más simple de ahorrar espacio cuando publicas en Google Play es subir la app como Android App Bundle, que es un nuevo formato de carga que incluye todos los recursos y el código compilado de tu app, pero delega la generación del APK y la firma a Google Play.

El nuevo modelo de publicación de apps de Google Play, llamado Dynamic Delivery, usa tu paquete de aplicación a fin de generar y publicar APK optimizados para cada configuración de dispositivos de manera que los usuarios puedan descargar por su cuenta el código y los recursos necesarios para ejecutar tu app. Ya no tendrás que compilar, firmar y administrar varios APK para tener compatibilidad con diferentes dispositivos, y los usuarios deberán realizar descargas más pequeñas y optimizadas.

Ten en cuenta que, debido a que Google Play aplica una restricción de tamaño de descarga comprimida de 150 MB o menos para apps publicadas con paquetes de aplicaciones, recomendamos aplicar los lineamientos que se describen en este documento a fin de reducir el tamaño de descarga de tu app tanto como sea posible.

En el caso de las apps que publicas en Google Play mediante la carga de APK firmados, las descargas comprimidas están restringidas a 100 MB o menos.

Usa el analizador de tamaño de Android

La herramienta Android Size Analyzer sirve para identificar e implementar de manera fácil muchas estrategias con el objetivo de reducir el tamaño de tu app. Está disponible como un complemento de Android Studio y como un JAR independiente.

Cómo usar el analizador en Android Studio

Puedes descargar el complemento de Android Size Analyzer desde el mercado de complementos de Android Studio, como se muestra en la figura 1. Para abrir el mercado de complementos e instalar el complemento, sigue estos pasos:

  1. Selecciona File > Settings (o, en Mac, Android Studio > Preferences).
  2. Selecciona la sección Plugins en el panel izquierdo.
  3. Haz clic en la pestaña Marketplace.
  4. Busca el complemento "Android Size Analyzer".
  5. Haz clic en el botón Install del complemento del analizador.

Figura 1: El complemento de Android Size Analyzer en la pestaña Marketplace

Después de instalar el complemento, ejecuta un análisis del tamaño de la app en tu proyecto actual seleccionando Analyze > Analyze App Size en la barra de menú. Después del análisis del proyecto, aparecerá una ventana de herramientas con recomendaciones sobre cómo reducir el tamaño de la app, como se muestra en la figura 2.

Figura 2: La ventana de la herramienta del complemento Android Size Analyzer con recomendaciones

Cómo usar el analizador desde la línea de comandos

Puedes descargar la versión más reciente de Android Size Analyzer como archivo TAR o ZIP desde GitHub. Después de extraer el archivo, ejecuta la secuencia de comandos size-analyzer (en Linux o MacOS) o size-analyzer.bat (en Windows) en tu proyecto de Android o Android App Bundle mediante uno de los siguientes comandos:

    ./size-analyzer check-bundle <path-to-aab>
    ./size-analyzer check-project <path-to-project-directory>
    

Comprende la estructura de APK

Antes de explicar cómo reducir el tamaño de tu app, es útil comprender la estructura de su archivo APK. El APK está compuesto por un archivo ZIP que contiene todos los archivos que conforman la app, lo que incluye archivos de clase Java, de recursos y uno que contiene recursos compilados.

Un APK incluye los siguientes directorios:

  • META-INF/: Contiene los archivos de firma CERT.SF y CERT.RSA, además del archivo de manifiesto MANIFEST.MF.
  • assets/: Contiene los elementos de la app, que esta puede recuperar mediante un objeto AssetManager.
  • res/: Contiene recursos que no están incluidos en resources.arsc.
  • lib/: Contiene el código compilado específico para la capa del software de un procesador. Este directorio contiene un subdirectorio para cada tipo de plataforma, como armeabi, armeabi-v7a, arm64-v8a, x86, x86_64 y mips.

Además, un APK contiene los siguientes archivos. De todos ellos, el único obligatorio es AndroidManifest.xml.

  • resources.arsc: Contiene recursos compilados. El archivo incluye el contenido XML de todas las configuraciones de la carpeta res/values/. La herramienta empaquetadora extrae el contenido XML, lo compila en formato binario y lo archiva. Dentro de este contenido, se incluyen strings de idioma y estilos, además de rutas al contenido que no está incluido directamente en el archivo resources.arsc, como imágenes y archivos de diseño.
  • classes.dex: Contiene las clases compiladas en el formato de archivo DEX que comprende la máquina virtual Dalvik/ART.
  • AndroidManifest.xml: Contiene el archivo de manifiesto principal de Android. En este archivo, se incluyen el nombre, la versión, los derechos de acceso y los archivos de la biblioteca mencionados de la app. El archivo utiliza el formato XML binario de Android.

Reduce el tamaño y la cantidad de recursos

El tamaño del APK influye en la velocidad de carga de la app, la cantidad de memoria que usa y cuánta batería consume. Una de las formas más sencillas de reducir el tamaño del APK es disminuir la cantidad de recursos que contiene y su tamaño. Específicamente, puedes quitar recursos que tu app ya no usa y, además, utilizar objetos Drawable escalables, en lugar de archivos de imagen. En esta sección, se explican estos métodos y, además, se proporcionan otras alternativas para reducir los recursos de tu app y el tamaño total del APK.

Quita recursos que no se usan

La herramienta lint, un analizador de código estático incluido en Android Studio, detecta los recursos de la carpeta res/ a los que el código no hace referencia. Si la herramienta lint detecta un recurso que posiblemente no se use en tu proyecto, muestra un mensaje como el que aparece a continuación.

    res/layout/preferences.xml: Warning: The resource R.layout.preferences appears
        to be unused [UnusedResources]
    

Nota: La herramienta lint no analiza la carpeta assets/, los elementos a los que se hace referencia mediante reflejo ni los archivos de la biblioteca que vinculaste a la app. Tampoco quita los recursos, solo te muestra una alerta para que sepas que existen.

Es posible que las bibliotecas que agregues al código incluyan recursos que no se usen. Gradle puede quitar automáticamente los recursos por ti si habilitas shrinkResources en el archivo build.gradle de la app.

    android {
        // Other settings

        buildTypes {
            release {
                minifyEnabled true
                shrinkResources true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    

Para usar shrinkResources, también debes habilitar la reducción del código. Durante el proceso de compilación, R8 primero quita el código que no se utiliza. Luego, el complemento de Gradle para Android quita los recursos que no se utilizan.

Para obtener más información sobre la reducción del código y los recursos, y sobre otras formas en que Android Studio te ayuda a reducir el tamaño del APK, consulta Cómo reducir, ofuscar y optimizar tu app.

En el complemento de Gradle para Android 0.7 y versiones posteriores, puedes informar las configuraciones que admite tu app. Gradle le transmite esa información al sistema de compilación mediante los valores resConfig y resConfigs, y la opción defaultConfig. Este sistema de compilación evita que aparezcan recursos de otras configuraciones no admitidas en el APK y, de esta forma, reduce su tamaño. Para obtener más información sobre esta función, consulta Quitar recursos alternativos sin usar.

Minimiza el uso de recursos de la biblioteca

Cuando se desarrolla una app de Android, normalmente se usan bibliotecas externas para mejorar la usabilidad y versatilidad de la app. Por ejemplo, puedes establecer una referencia a la biblioteca de compatibilidad de Android para mejorar la experiencia del usuario en dispositivos más antiguos. También puedes usar los servicios de Google Play para recuperar traducciones automáticas del texto en tu app.

Si se diseñó una biblioteca para un servidor o una computadora de escritorio, puede incluir varios objetos y métodos que no son necesarios para la app. Para incluir solamente las partes de la biblioteca que son necesarias, puedes editar sus archivos (si la licencia te permite modificar la biblioteca). También puedes usar una biblioteca alternativa y optimizada para dispositivos móviles a fin de agregar alguna funcionalidad específica a la app.

Nota: La reducción del código puede quitar parte del código innecesario de una biblioteca, pero es posible que no sea capaz de quitar algunas dependencias internas grandes.

Admite únicamente densidades específicas

Android admite muchísimos dispositivos, que incluyen una variedad de densidades de pantalla. En Android 4.4 (API nivel 19) y versiones posteriores, el marco de trabajo admite varias densidades: ldpi, mdpi, tvdpi, hdpi, xhdpi, xxhdpi y xxxhdpi. Aunque Android admite todas esas densidades, no es necesario exportar los elementos de los cuales se generó una trama a cada una de ellas.

Si sabes que solo un pequeño porcentaje de los usuarios tienen dispositivos con densidades específicas, considera si es necesario agrupar esas densidades en la app. Si no incluyes recursos para una densidad de pantalla específica, Android ajustará automáticamente la escala de los recursos existentes que fueron diseñados originalmente para otras densidades de pantalla.

Si tu app solo necesita imágenes ajustadas a escala, puedes incluir una sola variante de la imagen en drawable-nodpi/ para ahorrar más espacio. Recomendamos que cada app incluya, al menos, una variante de imagen xxhdpi.

Para obtener más información sobre las densidades de pantalla, consulta Tamaños y densidades de pantalla.

Usa elementos de diseño

En algunas imágenes, no se necesita un recurso de imagen estática, ya que el marco de trabajo puede diseñar dinámicamente la imagen durante el tiempo de ejecución. Los objetos Drawable (<shape> en XML) pueden ocupar muy poco espacio en el APK. Además, los objetos Drawable de XML producen imágenes monocromáticas que cumplen con los lineamientos de material design.

Vuelve a usar recursos

Puedes incluir un recurso separado para variaciones de una imagen, por ejemplo, versiones en las que se modifique el tono, el matiz o la rotación. Sin embargo, te recomendamos que vuelvas a usar el mismo conjunto de recursos y que los personalices según sea necesario durante el tiempo de ejecución.

Android proporciona varias utilidades para cambiar el color de un elemento mediante los atributos android:tint y tintMode en Android 5.0 (API nivel 21) y versiones posteriores. Si tienes una versión anterior de la plataforma, usa la clase ColorFilter.

También puedes omitir recursos cuando se trata de la versión rotada de otro recurso. El siguiente fragmento de código proporciona un ejemplo en el cual un "Me gusta" se transforma en un "No me gusta". Para hacerlo, hay que rotar el centro de la imagen en 180°:

    <?xml version="1.0" encoding="utf-8"?>
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:drawable="@drawable/ic_thumb_up"
        android:pivotX="50%"
        android:pivotY="50%"
        android:fromDegrees="180" />
    

Procesa desde un código

También puedes reducir el tamaño del APK mediante el procesamiento de tus imágenes. Este método permite liberar espacio gracias a que deja de ser necesario almacenar un archivo de imagen en el APK.

Procesa los archivos PNG

Con la herramienta aapt, se pueden optimizar los recursos de imagen que se encuentran en res/drawable/ mediante una compresión sin pérdidas durante el proceso de compilación. Por ejemplo, la herramienta aapt puede convertir un archivo PNG con color verdadero en el que no se necesitan más de 256 colores a un PNG de 8 bits con una paleta de colores. De este modo, la imagen tiene la misma calidad, pero el uso de memoria es menor.

Recuerda que aapt tiene las siguientes limitaciones:

  • La herramienta aapt no reduce los archivos PNG que se encuentran en la carpeta asset/.
  • Las imágenes deben tener 256 colores o menos para que la app aapt pueda optimizarlas.
  • La herramienta aapt puede aumentar el tamaño de los archivos PNG que ya se comprimieron. Para evitar este aumento, puedes usar la marca cruncherEnabled en Gradle a fin de inhabilitar este proceso para los archivos PNG:
    aaptOptions {
        cruncherEnabled = false
    }
    

Comprime los archivos PNG y JPEG

Puedes reducir el tamaño de un archivo PNG sin perder la calidad de la imagen con herramientas como pngcrush, pngquant o zopflipng, que reducen el tamaño del archivo y, a la vez, preservan la calidad perceptiva de la imagen.

La herramienta pngcrush es particularmente efectiva porque itera en todos los filtros PNG y parámetros zlib (reducción de tamaño) mediante una combinación de filtros y parámetros para comprimir la imagen. Luego, selecciona la configuración que produce la salida comprimida de menor tamaño.

Para comprimir archivos JPEG, puedes usar herramientas como packJPG y guetzli.

Usa el formato de archivo WebP

En lugar de usar archivos PNG o JPEG, puedes usar el formato de archivo WebP para las imágenes cuando tu app se orienta a Android 3.2 (API nivel 13) y versiones posteriores. El formato WebP proporciona una compresión con pérdidas (como JPEG) y transparencia (como PNG). Sin embargo, puede proporcionar una mejor compresión que los archivos con formato JPEG o PNG.

Con Android Studio, puedes convertir imágenes GIF estáticas o BMP, JPG o PNG ya existentes a formato WebP. Para obtener más información, consulta Crear imágenes WebP con Android Studio.

Nota: Google Play acepta APK solamente si los íconos de selector están en formato PNG.

Usa gráficos de vectores

Puedes usar gráficos de vectores para crear íconos con resolución independiente y otro contenido multimedia escalable. Si usas estos gráficos, reducirás notablemente el tamaño del APK. En Android, las imágenes vectoriales se representan como objetos VectorDrawable. Con un objeto VectorDrawable, un archivo de 100 bytes puede generar una imagen nítida del tamaño de la pantalla.

Sin embargo, se necesita una cantidad considerable de tiempo para que el sistema procese cada objeto VectorDrawable. Debido a que las imágenes más grandes tardarán más en aparecer en la pantalla, es recomendable que uses estos gráficos de vectores solo para mostrar imágenes pequeñas.

Para obtener más información sobre cómo trabajar con objetos VectorDrawable, consulta Trabaja con elementos de diseño.

Usa gráficos de vectores para imágenes animadas

No uses AnimationDrawable para crear animaciones por fotograma, ya que será necesario que incluyas un archivo de mapa de bits distinto para cada fotograma de la animación, con lo cual el tamaño del APK aumentará considerablemente.

En cambio, debes usar AnimatedVectorDrawableCompat para crear elementos de diseño en vector animados.

Reduce el código nativo y Java

Hay varios métodos que puedes usar para reducir el tamaño de la base de código nativo o Java en la app.

Quita el código que se generó innecesariamente

Asegúrate de comprender el impacto de cualquier código que se genere automáticamente. Por ejemplo, varias herramientas de búfer de protocolo generan una cantidad excesiva de métodos y clases, que pueden duplicar o triplicar el tamaño de la app.

Evita las enumeraciones

Una enumeración puede agregar entre 1.0 y 1.4 KB al archivo classes.dex de la app. En el caso de sistemas complejos y bibliotecas compartidas, estas adiciones podrían acumularse rápidamente. Te recomendamos que, si es posible, uses la anotación @IntDef y la reducción de código para evitar las enumeraciones y convertirlas en enteros. Este tipo de conversión conserva todos los beneficios de seguridad de las enumeraciones.

Reduce el tamaño de los objetos binarios nativos

Si tu app usa código nativo y NDK de Android, puedes optimizar el código para reducir el tamaño de la versión de lanzamiento de la app. Para ello, hay dos técnicas útiles: quitar los símbolos de depuración y no extraer las bibliotecas nativas.

Quita los símbolos de depuración

Si la app está en desarrollo y todavía necesita depuración, es conveniente usar símbolos de depuración. Usa la herramienta arm-eabi-strip, proporcionada en el NDK de Android, para quitar los símbolos de depuración innecesarios de las bibliotecas nativas. Después de hacerlo, podrás crear la compilación de lanzamiento.

Evita extraer bibliotecas nativas

Cuando crees la versión de lanzamiento de la app, incluye en un paquete los archivos .so sin comprimir en el APK. Para hacerlo, tienes que configurar android:extractNativeLibs="false" en el elemento <application> del manifiesto de la app. Inhabilitar esta marca evita que PackageManager copie archivos .so del APK al sistema de archivos durante la instalación y, además, reduce el tamaño de las actualizaciones de la app.

Conserva varios APK de menor tamaño

Tu APK puede incluir contenido que los usuarios descargan, pero que nunca usan, como idiomas adicionales o recursos según la densidad de la pantalla. A fin de garantizar que la descarga de los usuarios sea mínima, deberías subir tu app en Google Play mediante Android App Bundles. La carga de paquetes de aplicaciones permite a Google Play generar y publicar APK optimizados para la configuración de cada dispositivo de usuario, de manera que solo tengan que descargar el código y los recursos necesarios para ejecutar tu app. Ya no tendrás que compilar, firmar y administrar varios APK para tener compatibilidad con diferentes dispositivos, y los usuarios deberán realizar descargas más pequeñas y optimizadas.

Si no vas a publicar la app en Google Play, puedes segmentarla en varios APK, diferenciados por factores, como el tamaño de la pantalla o la compatibilidad con la textura de la GPU.

Cuando un usuario descarga la app, el dispositivo recibe el APK correcto en función de sus características y configuración. De esta forma, no reciben elementos para características que el dispositivo no incluye. Por ejemplo, si un usuario tiene un dispositivo hdpi, no necesita recursos xxxhdpi que podrías incluir para dispositivos que tienen pantallas de mayor densidad.

Para obtener más información, consulta Cómo configurar divisiones de APK y Cómo mantener múltiples APK.