Register now for Android Dev Summit 2019!

Reduza o tamanho do seu app

Geralmente os usuários evitam fazer o download de apps que pareçam muito grandes, especialmente em mercados emergentes, onde os dispositivos são conectados a redes 2G e 3G instáveis ou utilizam planos pagos por tráfego de dados. Esta página descreve como reduzir o tamanho do download 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, que é um novo formato de upload que inclui todos os recursos e o código compilado do seu app, mas repassa a geração e a assinatura do APK para o Google Play.

O novo modelo de veiculação de apps do Google Play, chamado de Dynamic Delivery, 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. Não é mais necessário criar, assinar e gerenciar vários APKs para ter compatibilidade com diferentes dispositivos, 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 aplicar as diretrizes descritas aqui para reduzir o máximo possível o tamanho do download do app.

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 falarmos sobre como reduzir o tamanho do seu app, é importante entender a estrutura do APK de um app. Um arquivo APK é um ZIP que contém todos os arquivos que compõem o app. Esses arquivos incluem os 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 assinatura CERT.SF e CERT.RSA, além do arquivo de manifesto MANIFEST.MF.
  • assets/: contém os materiais do app, que podem ser recuperados usando um objeto AssetManager.
  • res/: contém recursos que não são compilados no resources.arsc.
  • lib/: contém o código compilado que é 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 a seguir. Entre eles, apenas o AndroidManifest.xml é obrigatório.

  • resources.arsc: contém recursos compilados. Esse arquivo apresenta o conteúdo XML de todas as configurações da pasta res/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údo que não está incluído 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/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 recursos que seu app não usa mais e utilizar objetos Drawable escalonáveis no lugar dos 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/ aos quais seu código não faz referência. Quando a ferramenta lint descobre um recurso possivelmente não utilizado no seu 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 materiais referenciados por meio de reflexão ou os arquivos de biblioteca vinculados ao seu app. Ela também não remove recursos, só avisa você sobre a presença deles.

Bibliotecas adicionadas ao seu código podem incluir recursos não utilizados. O Gradle pode remover automaticamente recursos em seu nome se você ativar shrinkResources no arquivo build.gradle do app.

    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 criação, primeiro o ProGuard remove o código não utilizado, mas deixa os recursos não utilizados. Depois, o Gradle remove os recursos não utilizados.

Para ver mais informações sobre o ProGuard e outras formas em que o Android Studio ajuda a reduzir o tamanho do APK, consulte Reduza seus códigos e recursos.

No Android Gradle Plugin versão 0.7 e posterior, você pode declarar as configurações compatíveis com seu app. O Gradle passa essa informação para o sistema de compilação usando as variações resConfig e resConfigs e a opção defaultConfig. O sistema de compilação impede que os recursos de outras configurações não compatíveis apareçam no APK, reduzindo o tamanho dele. Para saber mais sobre esse recurso, consulte Remova 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 Android Support Library para melhorar a experiência do usuário em dispositivos mais antigos ou pode 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 área de trabalho, ela pode ter muitos objetos e métodos dos quais 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: o ProGuard pode limpar algum código desnecessário importado com uma biblioteca, mas não pode remover as grandes dependências internas de uma biblioteca.

Compatibilidade apenas com densidades específicas

O Android é compatível com um conjunto muito grande de dispositivos, abrangendo várias densidades de tela. No Android 4.4 (API nível 19) e versões posteriores, o framework é compatível com várias 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 parte dos seus usuários tem dispositivos com densidades específicas, pode ser uma boa ideia agrupar essas densidades no seu app. Caso você não inclua recursos para uma densidade de tela específica, o Android dimensionará automaticamente os recursos existentes que foram projetados para outras densidades de tela.

Se o app precisar apenas de imagens dimensionadas, você poderá economizar ainda mais espaço com uma única variante de uma 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 tempo de execução. Os objetos Drawable (<shape> em XML) podem ocupar uma quantidade de espaço muito pequena no seu APK. Além disso, os objetos Drawable XML produzem imagens monocromáticas compatíveis 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 tempo de execução.

O Android fornece vários utilitários para alterar a cor de um material, usando os atributos android:tint e tintMode no Android 5.0 (API level 21) e versões posteriores. 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 criaçã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 contidos 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 inflar arquivos PNG que já foram compactados. Para evitar isso, você pode usar o sinalizador cruncherEnabled no Gradle para desabilitar esse processo para arquivos PNG:
    aaptOptions {
        cruncherEnabled = 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. 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, você pode usar ferramentas como packJPG e guetzli.

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 nível 13) e versões posteriores. O formato WebP fornece compactação com perdas (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.

Observação: o Google Play aceita os APKs apenas se os ícones na tela de início utilizarem o formato PNG.

Usar gráficos vetoriais

Você pode usar gráficos vetoriais para criar ícones independentes de resolução e outras mídias escaloná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 Como trabalhar com drawables.

Usar gráficos vetoriais para imagens animadas

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

Em vez disso, use AnimatedVectorDrawableCompat para criar drawables de vetor animados.

Reduzir os códigos nativo e Java

Existem vários métodos para reduzir o tamanho da codebase nativa 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

Uma única enumeração pode adicionar cerca de 1,0 a 1,4 KB de tamanho ao arquivo classes.dex do seu app. Essas adições podem se acumular rapidamente para sistemas complexos ou bibliotecas compartilhadas. Se possível, use a anotação @IntDef e o ProGuard para eliminar as enumerações e convertê-las 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 seu 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

Utilizar símbolos de depuração é útil se seu app está em desenvolvimento e ainda requer 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 android:extractNativeLibs="false" no elemento <application> do manifesto do app. Desabilitar esse sinalizador impede que o PackageManager copie arquivos .so do APK para o sistema de arquivos durante a instalação e tem o benefício adicional de diminuir o tamanho das atualizações do seu 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 upload de pacotes de apps permite que o Google Play gere e veicule APKs otimizados para cada configuração de dispositivo, assim, os usuários fazem o download apenas do código e dos recursos necessários à execução do app. Não é mais necessário criar, assinar e gerenciar vários APKs para ter compatibilidade com diferentes dispositivos, e os usuários recebem downloads 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, se um usuário tiver um dispositivo hdpi, ele não precisará de recursos xxxhdpi que você possa incluir para dispositivos com telas de densidade mais alta.

Para ver mais informações, consulte Configurar divisões de APK e Manutenção de vários APKs.