Reduza o tamanho do seu app

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 com limite de dados. Esta página descreve como reduzir o tamanho do download do seu app para que mais usuários tenham acesso a ele.

Fazer upload do app com Android App Bundles

Faça upload do app como um Android App Bundle para economizar imediatamente no tamanho ao publicá-lo no Google Play. O Android App Bundle é um formato de upload que inclui todo o código e os recursos compilados do app, mas transfere a geração e assinatura do APK para o Google Play.

O modelo de exibição de apps do Google Play usa seu pacote para gerar e disponibilizar APKs otimizados para a configuração do dispositivo de cada usuário. Assim, eles podem fazer 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 suporte 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 200 MB por app publicado em pacotes, ainda é recomendável seguir as diretrizes descritas nesta página para reduzir o máximo possível o tamanho do download do seu app.

A estrutura do APK

Antes de reduzir o tamanho do app, é útil entender a estrutura do APK. Um APK consiste em um arquivo ZIP que contém todos os arquivos que compõem seu app, incluindo arquivos de classe Java, arquivos de recursos e um arquivo que contém recursos compilados.

Um APK contém estes diretórios:

  • META-INF/: contém os arquivos de assinatura CERT.SF e CERT.RSA, bem como o arquivo de manifesto MANIFEST.MF.
  • assets/: contém os recursos do app, que podem ser extraidos usando um objeto AssetManager.
  • res/: contém recursos que não são compilados no resources.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, como armeabi, armeabi-v7a, arm64-v8a, x86, x86_64 e mips.

Um APK também contém os arquivos abaixo. Apenas AndroidManifest.xml é obrigatório:

  • resources.arsc: contém recursos compilados. Esse arquivo contém o conteúdo XML de todas as configurações da pasta res/values/. A ferramenta de empacotamento extrai esse conteúdo XML, que é compilado em formato binário e arquivado. Esse conteúdo inclui estilos e strings de idioma, bem como caminhos para conteúdos que não estão incluídos diretamente no arquivo resources.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 ou 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. Ele 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. É possível tornar o APK menor reduzindo o número e o tamanho dos recursos que ele contém. Em particular, é possível remover os recursos que o app não usa mais e usar objetos Drawable dimensionáveis em vez de arquivos de imagem. Esta seção discute esses métodos e outras maneiras de reduzir os recursos do app para diminuir o tamanho geral do 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 deste exemplo:

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

Bibliotecas adicionadas ao código podem incluir recursos não utilizados. Se shrinkResources for ativado no arquivo build.gradle.kts do app, o Gradle poderá remover recursos automaticamente por você.

Kotlin

android {
    // Other settings.

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

Groovy

android {
    // Other settings.

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

Para usar shrinkResources, ative 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ódigo e de recursos, bem como outras estratégias do Android Studio para reduzir o tamanho do APK, consulte Reduzir, ofuscar e otimizar o app.

No Plug-in do Android para Gradle 7.0 e mais recentes, você pode declarar as configurações com suporte no app. O Gradle transmite essas informações para o sistema de build usando a variação resourceConfigurations e a opção defaultConfig. Em seguida, 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 versatilidade do app. Por exemplo, você pode referenciar o AndroidX para melhorar a experiência do usuário em dispositivos anteriores ou usar o Google Play Services para acessar traduções automáticas de texto no seu app.

Se uma biblioteca foi projetada para um servidor ou computador, ela pode ter muitos objetos e métodos desnecessários para o app. Para incluir apenas o que o app precisa, você pode editar os arquivos da biblioteca caso a licença permita modificá-la. Você também pode usar uma biblioteca alternativa e compatível com dispositivos móveis para acrescentar funcionalidades específicas ao app.

Decodificar imagens animadas nativas

No Android 12 (nível 31 da API), 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 animado.

Use ImageDecoder em vez de bibliotecas de terceiros para diminuir o tamanho do APK e aproveitar as atualizações futuras relacionadas à segurança e à performance.

Para saber mais sobre a API ImageDecoder, consulte o API reference e o exemplo no GitHub (link em inglês).

Suporte apenas a densidades específicas

O Android oferece suporte a diferentes densidades de tela, como estas:

  • ldpi
  • mdpi
  • tvdpi
  • hdpi
  • xhdpi
  • xxhdpi
  • xxxhdpi

Embora o Android ofereça suporte a essas densidades, você não precisa exportar os recursos rasterizados para cada uma delas.

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 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 redimensionadas, você pode economizar ainda mais espaço com uma única variante de imagem em drawable-nodpi/. Recomendamos incluir pelo menos uma variante de imagem xxhdpi no app.

Para saber mais sobre densidades de tela, consulte Tamanhos e densidades da tela.

Usar objetos drawable

Algumas imagens não exigem um recurso de imagem estática. O framework pode renderizar a imagem dinamicamente durante a execução. Objetos Drawable (ou <shape> em XML) podem ocupar um pequeno espaço no APK. Além disso, objetos Drawable no XML produzem imagens monocromáticas de acordo 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 reutilizar o mesmo conjunto de recursos e personalizá-los conforme necessário durante a execução.

O Android oferece vários utilitários para mudar a cor de um recurso usando os atributos android:tint e tintMode.

Você também pode ocultar recursos que são apenas um equivalente rotacionado de outro. O snippet de código abaixo é 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 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 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 build. Por exemplo, a ferramenta aapt pode converter um PNG de cores verdadeiras que não exige 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 consome menos memória.

O aapt tem algumas limitações:

  • A ferramenta aapt não reduz os arquivos PNG na pasta asset/.
  • 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 flag isCrunchPngs e desative esse processo em arquivos PNG:
  • Kotlin

        buildTypes.all { isCrunchPngs = false }
        

    Groovy

        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 (links em inglês). Todas essas ferramentas podem reduzir o tamanho do arquivo PNG e preservar a qualidade percebida 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 no menor tamanho.

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 nas suas imagens. Ele oferece compactação e transparência com perda, como JPG e PNG, e pode ter uma compactação melhor do que esses dois formatos.

Você pode converter as imagens BMP, JPG, PNG ou GIFs estáticos que estão em uso para o formato WebP usando o Android Studio. Para saber mais, consulte Criar imagens WebP.

Usar gráficos vetoriais

É possível usar gráficos vetoriais para criar ícones independentes de resolução e outras mídias redimensionáveis. Use esses gráficos para reduzir bastante o tamanho do 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 muito mais tempo para renderizar cada objeto VectorDrawable, e imagens maiores demoram ainda mais para aparecer na tela. Por isso, use-os somente para mostrar imagens pequenas.

Para saber mais sobre como trabalhar com objetos VectorDrawable, consulte Drawables.

Usar gráficos vetoriais para imagens animadas

Não use AnimationDrawable para criar animações frame a frame, já que isso exige que você inclua um arquivo bitmap separado para cada frame da animação, o que aumenta muito o tamanho do APK.

Em vez disso, use AnimatedVectorDrawableCompat para criar drawables vetoriais animados.

Reduzir os códigos nativo e Java

Você pode usar os métodos abaixo para reduzir o tamanho da base de código nativa e do Java no app.

Remover código gerado desnecessário

Entenda bem o tamanho 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 app.

Evitar enumerações

Um único tipo enumerado pode adicionar de 1 a 1,4 KB de tamanho ao arquivo classes.dex do app. Essas adições podem se acumular rapidamente em 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 dos tipos enumerados.

Diminuir o tamanho dos binários nativos

Se o app usa código nativo e o Android NDK, você também pode otimizar o código para reduzir o tamanho da versão de lançamento. 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 do Android NDK para remover símbolos de depuração desnecessários de bibliotecas nativas. Depois, você pode compilar o build de lançamento.

Evitar a extração de bibliotecas nativas

Ao criar a versão de lançamento do app, empacote arquivos .so descompactados no APK definindo useLegacyPackaging como false no arquivo build.gradle.kts. Desativar essa flag impede que PackageManager copie arquivos .so do APK para o sistema de arquivos durante a instalação. Esse método diminui o tamanho das 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 app no Google Play usando Android App Bundles. O envio de pacotes de app permite que o Google Play gere e disponibilize APKs otimizados para a configuração de cada dispositivo. 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 criar, assinar e gerenciar vários APKs para oferecer suporte a dispositivos diferentes, e os usuários fazem downloads menores e mais otimizados.

Se você não está publicando o app no Google Play, pode segmentá-lo em vários APKs diferenciados por fatores como tamanho da tela ou suporte da GPU a texturas.

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 não possuem. Por exemplo, um usuário que tem um dispositivo hdpi não precisa de recursos xxxhdpi, que podem ser necessários para dispositivos com telas de densidade mais alta.

Para saber mais, consulte Criar vários APKs e Suporte a vários APKs.