Los usuarios suelen evitar la descarga de 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 entrega de apps de Google Play usa el paquete de aplicación para generar y entregar APK optimizados para la configuración del dispositivo de cada usuario, de manera que solo descarguen el código y los recursos necesarios para ejecutar la app. Ya no tendrás que compilar, firmar ni administrar múltiples APK para admitir diferentes dispositivos, y los usuarios podrá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 para 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.
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 archivo APK consiste en un archivo ZIP que contiene todos los archivos que conforman la app, lo que incluye archivos de clase Java y de recursos, y uno que contiene recursos compilados.
Un APK incluye los siguientes directorios:
META-INF/
: Contiene los archivos de firmaCERT.SF
yCERT.RSA
, además del archivo de manifiestoMANIFEST.MF
.assets/
: Contiene los elementos de la app, que esta puede recuperar mediante un objetoAssetManager
.-
res/
: Contiene recursos que no están incluidos enresources.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, comoarmeabi
,armeabi-v7a
,arm64-v8a
,x86
,x86_64
ymips
.
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 carpetares/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 archivoresources.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, y se 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 que se incluye 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.
Groovy
android { // Other settings buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
Kotlin
android { // Other settings buildTypes { getByName("release") { minifyEnabled = true shrinkResources = true proguardFiles(getDefaultProguardFile('proguard-android.txt'), "proguard-rules.pro") } } }
Para usar shrinkResources
, también debes habilitar la reducción de código. Durante el proceso de compilación, R8 primero quita el código que no se utiliza. Luego, el complemento de Android para Gradle quita los recursos que no se utilizan.
Para obtener más información sobre la reducción de código y 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 Android para Gradle 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 las variantes 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 Cómo quitar recursos alternativos que no se usan.
Minimiza el uso de recursos de la biblioteca
Cuando se desarrolla una app para Android, se suelen utilizar 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 para agregar alguna funcionalidad específica a la app.
Nota: La reducción de código puede borrar parte del código innecesario de una biblioteca, pero es posible que no sea capaz de quitar algunas dependencias internas grandes.
Decodificación de imágenes animadas nativas
En Android 12 (nivel de API 31), se expandió la API de ImageDecoder
del NDK para decodificar todos los fotogramas y datos de tiempo de las imágenes que usan el GIF animado y formatos de archivo WebP animados. Cuando se introdujo en Android 11, esta API decodificaba solo la primera imagen de las animaciones en estos formatos.
Usa ImageDecoder
en lugar de bibliotecas de terceros para reducir el tamaño del APK y aprovechar las actualizaciones futuras relacionadas con la seguridad y el rendimiento.
Para obtener más información sobre la API, consulta API reference
y el ejemplo en GitHub.
Admite únicamente densidades específicas
Android admite muchísimos dispositivos, que incluyen una variedad de densidades de pantalla. En Android 4.4 (nivel de API 19) y versiones posteriores, el framework 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 tiene 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 framework 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 (nivel de API 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" />
Renderiza desde un código
También puedes reducir el tamaño del APK mediante el procesamiento mediante renderizaciones 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 en 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 carpetaasset/
. - Los archivos de imágenes deben tener 256 colores o menos para que la herramienta
aapt
pueda optimizarlas. - La herramienta
aapt
puede aumentar el tamaño de los archivos PNG que ya se comprimieron. Con el objeto de evitar este aumento, puedes usar la marcaisCrunchPngs
para inhabilitar este proceso para los archivos PNG:
Groovy
buildTypes.all { isCrunchPngs = false }
Kotlin
buildTypes.all { isCrunchPngs = 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 (nivel de API 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 Cómo crear imágenes WebP con Android Studio.
Usa gráficos vectoriales
Puedes usar gráficos vectoriales 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 renderice 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 vectoriales solo para mostrar imágenes pequeñas.
Para obtener más información para trabajar con objetos VectorDrawable
, consulta Trabaja con elementos de diseño.
Usa gráficos vectoriales 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 vectoriales 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 actualización 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 aplicación está en desarrollo y todavía necesita depuración, es conveniente usar símbolos de depuración. Usa la herramienta arm-eabi-strip
, que se proporciona 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 compiles la versión de actualización de tu app, incluye en un paquete los archivos .so
sin comprimir en el APK. Para hacerlo, asegúrate de que el elemento useLegacyPackaging
esté configurado en false
del archivo build.gradle
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 sea mínima para los usuarios, deberías subir tu app a Google Play mediante Android App Bundles. Subir de paquetes de aplicaciones permite a Google Play generar y publicar APKs optimizados para la configuración del dispositivo de cada uno de los usuarios, 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 APKs para tener compatibilidad con diferentes dispositivos, y los usuarios podrán realizar descargas más pequeñas y optimizadas.
Si no vas a publicar la app en Google Play, puedes segmentarla en varios APKs, 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 recibe 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 con pantallas de mayor densidad.
Para obtener más información, consulta Cómo configurar divisiones de APK y Cómo mantener múltiples APK.