Geralmente, os usuários evitam o download de apps que pareçam muito grandes, principalmente em mercados emergentes em que os dispositivos são conectados a redes 2G e 3G instáveis ou usam planos de pagamento por tráfego de dados. Esta página descreve como reduzir o tamanho do seu app para que mais usuários façam o download dele.
Fazer upload do app com Android App Bundles
A maneira mais fácil e imediata de diminuir o tamanho do app ao publicá-lo no Google Play é fazer upload dele como um Android App Bundle. Esse é um novo formato de upload que inclui todos os recursos e o código compilado do seu app, mas repassa a geração e assinatura do APK para o Google Play.
O novo modelo de exibição de apps do Google Play usa seu pacote de apps para gerar e disponibilizar APKs otimizados para a configuração do dispositivo de cada usuário, para que eles façam o download apenas do código e dos recursos necessários à execução do app. Você não precisa mais criar, assinar e gerenciar vários APKs para oferecer compatibilidade a dispositivos diferentes, e os usuários recebem downloads menores e mais otimizados.
Como o Google Play aplica uma restrição de tamanho de download de 150 MB ou menos por app publicado em pacotes, é recomendável seguir as diretrizes descritas aqui para reduzir o máximo possível o tamanho do download.
Para os apps publicados no Google Play por upload de APKs assinados, a restrição de downloads compactados é de 100 MB ou menos.
A estrutura do APK
Antes de discutir como reduzir o tamanho do seu app, é útil entender a estrutura do APK de um app. Um arquivo APK consiste em um arquivo ZIP que contém todos os arquivos que compõem seu app. Eles incluem arquivos de classe Java, arquivos de recursos e um arquivo que contém recursos compilados.
Um APK contém os seguintes diretórios:
META-INF/
: contém os arquivos de assinaturaCERT.SF
eCERT.RSA
, bem como o arquivo de manifestoMANIFEST.MF
.assets/
: contém os recursos do app, que podem ser recuperados usando um objetoAssetManager
.-
res/
: contém recursos que não são compilados noresources.arsc
. lib/
: contém o código compilado específico para a camada de software de um processador. Esse diretório contém um subdiretório para cada tipo de plataforma, comoarmeabi
,armeabi-v7a
,arm64-v8a
,x86
,x86_64
emips
.
Um APK também contém os arquivos a seguir. Entre todos eles,
somente AndroidManifest.xml
é obrigatório.
resources.arsc
: contém recursos compilados. Esse arquivo contém o conteúdo XML de todas as configurações da pastares/values/
. A ferramenta de empacotamento extrai esse conteúdo XML, compila-o em formato binário e arquiva o conteúdo. Esse conteúdo inclui estilos e strings de idioma, assim como caminhos para conteúdos que não estão incluídos diretamente no arquivoresources.arsc
, como arquivos de layout e imagens.classes.dex
: contém as classes compiladas no formato de arquivo DEX compreendido pela máquina virtual Dalvik/ART.AndroidManifest.xml
: contém o arquivo de manifesto principal do Android. Esse arquivo lista o nome, a versão, os direitos de acesso e os arquivos de biblioteca referenciados do app. O arquivo usa o formato XML binário do Android.
Reduzir o número e o tamanho dos recursos
O tamanho do APK tem impacto na velocidade de carregamento do seu app, na quantidade de
memória usada e na quantidade de energia consumida. Para reduzir o tamanho do seu APK
de forma simples, diminua o número e o tamanho dos
recursos contidos nele. Em particular, é possível remover os recursos
que seu app não usa mais e usar objetos Drawable
dimensionáveis em vez de arquivos de imagem. Esta
seção expõe esses métodos, além de várias outras maneiras de
reduzir os recursos do app para diminuir o tamanho geral do seu APK.
Remover recursos não utilizados
A ferramenta lint
, um
analisador de código estático incluído no Android Studio, detecta recursos na
pasta res/
que não são referenciados pelo seu código. Quando a
ferramenta lint
descobre um recurso possivelmente não utilizado no
projeto, ela gera uma mensagem como a do exemplo a seguir.
res/layout/preferences.xml: Warning: The resource R.layout.preferences appears to be unused [UnusedResources]
Observação: a ferramenta lint
não verifica a pasta assets/
, os recursos referenciados por reflexão ou os arquivos de biblioteca
vinculados ao app. Além disso, ela não remove recursos, só
avisa sobre a presença deles.
Bibliotecas adicionadas ao seu código podem incluir recursos não utilizados. Se shrinkResources
for ativado no arquivo build.gradle
do app, o Gradle
poderá remover recursos por você.
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
, também é necessário ativar a redução de código. Durante o
processo de build, o R8 remove primeiro o código não utilizado. Em seguida, o Plug-in do Android para Gradle remove os recursos
não utilizados.
Para saber mais sobre a redução de códigos e recursos e outras maneiras com que o Android Studio ajuda a reduzir o tamanho do APK, consulte Reduzir, ofuscar e otimizar o aplicativo.
Da versão 0.7 do Plug-in do Android para Gradle em diante, você pode declarar as configurações
com suporte no seu app. O Gradle passa essas informações para o sistema de build
usando as variações resConfig
e resConfigs
e a
opção defaultConfig
. O sistema de build impede que os recursos
de outras configurações sem suporte apareçam no APK, reduzindo
o tamanho dele. Para saber mais sobre esse recurso, consulte Remover recursos alternativos
não utilizados.
Minimizar o uso de recursos das bibliotecas
Ao desenvolver um app Android, normalmente são usadas bibliotecas externas para melhorar a usabilidade e a versatilidade do app. Por exemplo, você pode consultar a Biblioteca de Suporte do Android para melhorar a experiência do usuário em dispositivos mais antigos ou usar o Google Play Services para acessar traduções automáticas de texto no app.
Se uma biblioteca foi projetada para um servidor ou área de trabalho, ela pode ter muitos objetos e métodos de que seu app não precisa. Para incluir apenas o que o app precisa, você pode editar os arquivos da biblioteca (se a licença permitir modificá-la). Você também pode usar uma biblioteca alternativa e otimizada para dispositivos móveis para acrescentar funcionalidades específicas ao seu app.
Observação: a redução de código pode limpar parte do código desnecessário de uma biblioteca, mas talvez não seja possível remover algumas dependências internas grandes.
Decodificar imagens animadas nativas
No Android 12 (API de nível 31), a API
ImageDecoder
do NDK foi expandida
para decodificar todos os frames e dados de tempo de imagens que usam os formatos de arquivo
GIF e
WebP animados. Quando foi
lançada no Android 11, essa API decodificava somente a primeira imagem das animações nesses formatos.
Use ImageDecoder
em vez de bibliotecas de terceiros para diminuir o tamanho
do APK
e aproveitar as atualizações futuras relacionadas à segurança e ao desempenho.
Para ver mais detalhes sobre a API, consulte
API reference
e o
exemplo no GitHub (link em inglês).
Compatibilidade apenas com densidades específicas
O Android tem suporte a um conjunto muito grande de dispositivos, abrangendo várias
densidades de tela. No Android 4.4 (API de nível 19) e versões mais recentes, o framework
oferece suporte a diversas densidades: ldpi
, mdpi
,
tvdpi
, hdpi,
, xhdpi
,
xxhdpi
e xxxhdpi
. Embora o Android seja compatível com todas
essas densidades, você não precisa exportar os materiais rasterizados para cada
densidade.
Se você sabe que apenas uma pequena parcela dos usuários tem dispositivos com densidades específicas, avalie se existe necessidade de agrupá-las no seu app. Se você não incluir recursos para uma densidade de tela específica, o Android vai dimensionar automaticamente os recursos que foram originalmente projetados para outras densidades de tela.
Caso o app precise apenas de imagens dimensionadas, você poderá economizar ainda mais espaço com
uma única variante de imagem em drawable-nodpi/
. Recomendamos
que todos os apps incluam pelo menos uma variante de imagem xxhdpi
.
Para saber mais sobre densidades de tela, consulte Tamanhos e densidades da tela.
Usar objetos drawable
Algumas imagens não precisam de um recurso de imagem estática. Nesses casos, o framework pode
desenhar dinamicamente a imagem no momento da execução. Objetos Drawable
(<shape>
em
XML) podem ocupar um pequeno espaço no APK. Além disso, objetos XML Drawable
produzem imagens monocromáticas
em conformidade com as diretrizes do Material Design.
Reutilizar recursos
Você pode incluir um recurso separado para variações de uma imagem, como versões coloridas, sombreadas ou rotacionadas da mesma imagem. No entanto, recomendamos que você reutilize o mesmo conjunto de recursos, personalizando-os conforme necessário no momento da execução.
O Android oferece vários utilitários para mudar a cor de um recurso,
usando os atributos android:tint
e tintMode
no Android 5.0
(API de nível 21) ou versões mais recentes. Para versões anteriores da plataforma, use a classe ColorFilter
.
Você também pode ocultar recursos que são apenas um equivalente rotacionado de outro recurso. O snippet de código a seguir fornece um exemplo de como transformar um "gostei" em um "não gostei" ao girar a imagem 180 graus:
<?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" />
Renderizar a partir do código
Você também pode reduzir o tamanho do seu APK com a renderização processual das imagens. Esse procedimento libera espaço, porque você não armazena mais um arquivo de imagem no seu APK.
Fragmentar arquivos PNG
A ferramenta aapt
pode otimizar os recursos de imagem colocados em
res/drawable/
com compactação sem perdas durante o processo
de compilação. Por exemplo, a ferramenta aapt
pode converter um PNG de cores verdadeiras
que não requer mais de 256 cores em um PNG de 8 bits com uma paleta
de cores. Com isso, a imagem continua com a mesma qualidade, mas ocupa um espaço
menor de memória.
A aapt
tem as seguintes limitações:
- A ferramenta
aapt
não reduz os arquivos PNG na pastaasset/
. - Os arquivos de imagem precisam usar 256 cores ou menos para que a
ferramenta
aapt
possa otimizá-los. - A ferramenta
aapt
pode aumentar os arquivos PNG que já foram compactados. Para evitar isso, use a sinalizaçãoisCrunchPngs
para desativar esse processo em arquivos PNG:
Groovy
buildTypes.all { isCrunchPngs = false }
Kotlin
buildTypes.all { isCrunchPngs = false }
Compactar arquivos PNG e JPEG
É possível reduzir o tamanho dos arquivos PNG sem perder a qualidade da imagem usando ferramentas como pngcrush, pngquant ou zopflipng (em inglês). Todas essas ferramentas podem reduzir o tamanho do arquivo PNG e, ao mesmo tempo, preservar a qualidade perceptiva da imagem.
A ferramenta pngcrush
é particularmente eficaz. Ela faz a iteração dos
filtros PNG e dos parâmetros zlib (Deflate), usando cada combinação de filtros
e parâmetros para compactar a imagem. Em seguida, ela escolhe a configuração que
resulta na menor imagem compactada.
Para compactar arquivos JPEG, use ferramentas como packJPG e guetzli (links em inglês).
Usar o formato de arquivo WebP
Em vez de usar arquivos PNG ou JPEG, você pode usar o formato de arquivo WebP para suas imagens ao criar para o Android 3.2 (API de nível 13) e versões mais recentes. O formato WebP fornece compactação com perda (como JPEG) e transparência (como PNG), mas pode oferecer uma compactação melhor do que JPEG ou PNG.
Você pode converter imagens BMP, JPG, PNG existentes ou GIFs estáticos para o formato WebP usando o Android Studio. Para ver mais informações, consulte Criar imagens WebP usando o Android Studio.
Usar gráficos vetoriais
Você pode usar gráficos vetoriais para criar ícones independentes de resolução e outras
mídias dimensionáveis. Usar esses gráficos pode reduzir muito a área de ocupação do seu APK.
Imagens vetoriais são representadas no Android como objetos VectorDrawable
. Com um objeto VectorDrawable
, um arquivo de 100 bytes pode
gerar uma imagem nítida do tamanho da tela.
No entanto, o sistema leva um tempo significativo para renderizar cada
objeto VectorDrawable
e imagens maiores
demoram ainda mais para aparecer na tela. Por isso, use esses
gráficos vetoriais somente ao exibir imagens pequenas.
Para saber mais sobre como trabalhar com objetos VectorDrawable
, consulte a seção Como trabalhar
com drawables.
Usar gráficos vetoriais para imagens animadas
Não use AnimationDrawable
para criar animações
frame a frame, porque isso vai exigir que você inclua um arquivo bitmap separado para cada frame da
animação, aumentando muito o tamanho do APK.
Em vez disso, use
AnimatedVectorDrawableCompat
para criar drawables vetoriais animados.
Reduzir os códigos nativo e Java
Existem vários métodos para reduzir o tamanho do codebase nativo e do Java no seu app.
Remover código gerado desnecessário
Entenda bem a área de ocupação de todos os códigos gerados automaticamente. Por exemplo, muitas ferramentas de buffer de protocolo geram um número excessivo de métodos e classes, o que pode duplicar ou triplicar o tamanho do seu app.
Evitar enumerações
Um único tipo enumerado pode adicionar de 1,0 a 1,4 KB de tamanho ao arquivo
classes.dex
do app. Essas adições podem se acumular rapidamente para
sistemas complexos ou bibliotecas compartilhadas. Se possível, use a
anotação @IntDef
e a redução de código para remover tipos enumerados
e convertê-los em números inteiros. Essa conversão de tipo preserva todos os
benefícios de segurança de tipo das enumerações.
Diminuir o tamanho dos binários nativos
Se o app usa o código nativo e o Android NDK, você também pode reduzir o tamanho da versão de lançamento do app otimizando o código. Duas técnicas úteis são a remoção de símbolos de depuração e a não extração de bibliotecas nativas.
Remover os símbolos de depuração
O uso de símbolos de depuração é útil quando o app está em desenvolvimento e
ainda precisa de depuração. Use a ferramenta arm-eabi-strip
, fornecida
no Android NDK, para remover símbolos de depuração desnecessários de bibliotecas
nativas. Depois disso, você pode compilar sua versão de lançamento.
Evitar a extração de bibliotecas nativas
Ao criar a versão de lançamento do seu app, empacote arquivos .so
descompactados
no APK, definindo
useLegacyPackaging
como false
no arquivo build.gradle
do seu app. Desativar essa flag
impede
que PackageManager
copie arquivos .so
do APK para o sistema de arquivos durante a instalação, além de
fazer atualizações do app.
Manter vários APKs enxutos
É possível que seu APK tenha conteúdo que os usuários transferem por download, mas nunca usam, como outros idiomas e recursos de densidade de tela. Para garantir um download mínimo para seus usuários, faça upload do seu app no Google Play usando Android App Bundles. O envio de pacotes de app permite que o Google Play gere e veicule APKs otimizados para a configuração de dispositivos. Dessa forma, os usuários fazem o download apenas do código e dos recursos necessários para a execução do app. Você não precisa mais criar, assinar e gerenciar vários APKs para oferecer suporte a dispositivos diferentes, e os usuários fazem downloads de apps menores e mais otimizados.
Se você não estiver publicando seu app no Google Play, poderá segmentar o app em vários APKs, diferenciados por fatores como tamanho da tela ou compatibilidade com a textura da GPU.
Quando um usuário faz o download do seu app, o dispositivo dele recebe o APK correto com base
nos recursos e nas configurações do dispositivo. Dessa forma, os dispositivos não recebem materiais
para recursos que os dispositivos não possuem. Por exemplo, um usuário que tenha um
dispositivo hdpi
não precisará de recursos xxxhdpi
, que
podem precisar ser incluídos para dispositivos com telas de densidade mais alta.
Para saber mais, consulte Desenvolver vários APKs e Compatibilidade com vários APKs.