Atenção:desde agosto de 2021, todos os novos apps precisam ser publicados como App Bundles. Se você publicar seu app no Google Play, crie e faça upload de um Android App Bundle. Quando você faz isso, o Google Play gera e disponibiliza automaticamente 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 para executar o app. A publicação de vários APKs é útil se você estiver publicando em uma loja que não oferece suporte ao formato AAB. Nesse caso, você precisa criar, assinar e gerenciar cada APK por conta própria.
Embora seja melhor criar um único APK para oferecer suporte a todos os dispositivos de destino sempre que possível, isso pode resultar em um APK muito grande devido aos arquivos que oferecem suporte a várias densidades de tela ou Interfaces binárias do aplicativo (ABIs, na sigla em inglês). Uma maneira de reduzir o tamanho do APK é criar vários APKs que contenham arquivos para densidades de tela ou ABIs específicas.
O Gradle pode criar APKs separados que contenham apenas códigos e recursos específicos para cada densidade ou ABI. Esta página descreve como configurar seu build para gerar vários APKs. Se você precisar criar versões diferentes do app que não sejam baseadas na densidade de tela ou na ABI, use variantes de build.
Configurar o build para vários APKs
Para configurar o build para vários APKs, adicione um
bloco
splits
ao arquivo de nível de módulo
build.gradle
(link em inglês). No bloco
splits
, forneça
um bloco density
que especifique como você quer que o Gradle gere
APKs por densidade ou um bloco abi
que especifique como
você quer que o Gradle gere APKs por ABI. Você pode fornecer blocos de densidade e ABI, e
o sistema de build cria um APK para cada combinação de densidade e ABI.
Configurar vários APKs para densidades de tela
Para criar APKs separados para diferentes densidades de tela, adicione um
bloco density
dentro do
bloco splits
. No bloco density
, forneça uma
lista de densidades de tela e dos tamanhos de tela compatíveis. Use a lista de
tamanhos de tela compatíveis apenas se você precisar de elementos
<compatible-screens>
específicos no manifesto de cada APK.
As seguintes opções de DSL do Gradle são usadas para configurar vários APKs para densidades de tela:
-
enable
para Groovy,isEnable
para script Kotlin -
Se você definir esse elemento como
true
, o Gradle vai gerar vários APKs com base nas densidades de tela definidas. O valor padrão éfalse
. -
exclude
-
Especifica uma lista de densidades separadas por vírgulas para as quais você não quer que o
Gradle gere APKs separados. Use
exclude
se você quiser gerar APKs para a maioria das densidades, mas precisar excluir algumas que não oferecem suporte ao app. -
reset()
-
Apaga a lista padrão de densidades de tela. Use somente quando combinado com o elemento
include
para especificar as densidades que você quer adicionar.O snippet a seguir define a lista de densidades como
ldpi
exxhdpi
chamandoreset()
para limpar a lista e, em seguida, usandoinclude
:reset() // Clears the default list from all densities // to no densities. include "ldpi", "xxhdpi" // Specifies the two densities to generate APKs // for.
-
include
-
Especifica uma lista de densidades separadas por vírgulas para as quais o Gradle precisa gerar
APKs. Use somente em combinação com
reset()
para especificar uma lista exata de densidades. -
compatibleScreens
-
Especifica uma lista separada por vírgulas de tamanhos de tela compatíveis. Isso injeta um nó
<compatible-screens>
correspondente no manifesto para cada APK.Essa configuração é uma maneira conveniente de gerenciar as densidades e os tamanhos de tela na mesma seção
build.gradle
. No entanto, o uso de<compatible-screens>
pode limitar os tipos de dispositivos com que seu app funciona. Para conhecer outras formas de suporte a diferentes tamanhos de tela, consulte a visão geral de compatibilidade de tela.
Como cada APK que é baseado na densidade da tela inclui uma
tag <compatible-screens>
com restrições específicas
sobre os tipos de tela com suporte, mesmo que você publique vários
APKs, alguns dispositivos novos não corresponderão aos vários filtros de APK. Assim,
o Gradle sempre gera outro APK universal contendo recursos
para todas as densidades de tela e não inclui uma
tag <compatible-screens>
. Publique esse
APK universal com seus APKs por densidade para fornecer um substituto para
dispositivos que não correspondam aos APKs com uma
tag <compatible-screens>
.
O exemplo a seguir gera um APK separado para cada
densidade
de tela, exceto ldpi
, xxhdpi
e
xxxhdpi
. Isso é feito usando exclude
para remover
essas três densidades da lista padrão de todas as densidades.
Groovy
android { ... splits { // Configures multiple APKs based on screen density. density { // Configures multiple APKs based on screen density. enable true // Specifies a list of screen densities you don't want Gradle to create multiple APKs for. exclude "ldpi", "xxhdpi", "xxxhdpi" // Specifies a list of compatible screen size settings for the manifest. compatibleScreens 'small', 'normal', 'large', 'xlarge' } } }
Kotlin
android { ... splits { // Configures multiple APKs based on screen density. density { // Configures multiple APKs based on screen density. isEnable = true // Specifies a list of screen densities you don't want Gradle to create multiple APKs for. exclude("ldpi", "xxhdpi", "xxxhdpi") // Specifies a list of compatible screen size settings for the manifest. compatibleScreens("small", "normal", "large", "xlarge") } } }
Para mais detalhes sobre como personalizar diferentes variantes de build do app para tipos de tela e dispositivos específicos, consulte Declarar suporte restrito à tela.
Configurar vários APKs para ABIs
Para criar APKs separados para diferentes ABIs, adicione um bloco abi
dentro do seu bloco splits
. No bloco abi
, forneça uma lista de
ABIs desejadas.
As seguintes opções de DSL do Gradle são usadas para configurar vários APKs por ABI:
-
enable
para Groovy ouisEnable
para script Kotlin -
Se você definir esse elemento como
true
, o Gradle vai gerar vários APKs com base nas ABIs definidas. O valor padrão éfalse
. -
exclude
-
Especifica uma lista de ABIs separadas por vírgulas para as quais você não quer que o
Gradle gere APKs separados. Use
exclude
se você quiser gerar APKs para a maioria das ABIs, mas precisar excluir algumas que não oferecem suporte ao app. -
reset()
-
Limpa a lista padrão de ABIs. Use somente quando combinado com o elemento
include
para especificar as ABIs que você quer adicionar.O snippet a seguir define a lista de ABIs como
x86
ex86_64
chamandoreset()
para limpar a lista e, em seguida, usandoinclude
:reset() // Clears the default list from all ABIs to no ABIs. include "x86", "x86_64" // Specifies the two ABIs we want to generate APKs for.
-
include
-
Especifica uma lista de ABIs separadas por vírgulas para as quais o Gradle precisa gerar APKs. Use somente em combinação com
reset()
para especificar uma lista exata de ABIs. -
universalApk
para Groovy ouisUniversalApk
para script Kotlin -
Se for
true
, o Gradle vai gerar um APK universal, além dos APKs por ABI. Um APK universal contém código e recursos para todas as ABIs em um único APK. O valor padrão éfalse
.Observe que essa opção só está disponível no bloco
splits.abi
. Ao criar vários APKs com base na densidade da tela, o Gradle sempre gera um APK universal que contém código e recursos para todas as densidades.
O exemplo a seguir gera um APK separado para cada ABI: x86
e x86_64
. Isso é feito usando reset()
para começar com uma lista vazia de ABIs, seguida por include
com uma
lista de ABIs que recebem um APK.
Groovy
android { ... splits { // Configures multiple APKs based on ABI. abi { // Enables building multiple APKs per ABI. enable true // By default all ABIs are included, so use reset() and include to specify that you only // want APKs for x86 and x86_64. // Resets the list of ABIs for Gradle to create APKs for to none. reset() // Specifies a list of ABIs for Gradle to create APKs for. include "x86", "x86_64" // Specifies that you don't want to also generate a universal APK that includes all ABIs. universalApk false } } }
Kotlin
android { ... splits { // Configures multiple APKs based on ABI. abi { // Enables building multiple APKs per ABI. isEnable = true // By default all ABIs are included, so use reset() and include to specify that you only // want APKs for x86 and x86_64. // Resets the list of ABIs for Gradle to create APKs for to none. reset() // Specifies a list of ABIs for Gradle to create APKs for. include("x86", "x86_64") // Specifies that you don't want to also generate a universal APK that includes all ABIs. isUniversalApk = false } } }
Para conferir uma lista de ABIs compatíveis, consulte ABIs compatíveis.
Projetos sem código nativo/C++
Para projetos sem código nativo/C++, o painel Build Variants tem duas colunas: Module e Active Build Variant, conforme mostrado na Figura 1.
Figura 1. O painel Build Variants tem duas colunas para projetos sem
código nativo/C++.
O valor Active Build Variant para o módulo determina a variante de build que é implantada e visível no editor. Para alternar entre variantes, clique na célula Active Build Variant de um módulo e escolha a variante desejada no campo de lista.
Projetos com código nativo/C++
Para projetos com código nativo/C++, o painel Build Variants tem três colunas: Module, Active Build Variant e Active ABI, conforme mostrado na Figura 2.
Figura 2. O painel Build Variants adiciona a coluna Active ABI para projetos com código nativo/C++.
O valor Active Build Variant para o módulo determina a variante de build que é implantada e fica visível no editor. Para módulos nativos, o valor de Active ABI determina a ABI que o editor usa, mas não afeta o que é implantado.
Para mudar o tipo de build ou a ABI:
- Clique na célula da coluna Active Build Variant ou Active ABI.
- Escolha a variante ou ABI desejada no campo da lista. Uma nova sincronização é executada automaticamente.
Mudar uma coluna para um módulo de app ou de biblioteca aplica a mudança a todas as linhas dependentes.
Configurar o controle de versões
Por padrão, quando o Gradle gera vários APKs, cada um deles tem as
mesmas informações de versão, conforme especificado no arquivo
build.gradle
ou build.gradle.kts
do módulo. Como a
Google Play Store não permite que o mesmo app tenha vários APKs com
as mesmas informações de versão, é necessário garantir que cada APK tenha um
versionCode
exclusivo antes de fazer upload para a Play Store.
Você pode configurar o arquivo build.gradle
do módulo para
substituir o versionCode
de cada APK. Ao criar um mapeamento
que atribua um valor numérico exclusivo para cada ABI e densidade para os quais você configura
vários APKs, é possível substituir o código de versão de saída por um valor que
combine o código de versão definido no bloco defaultConfig
ou
productFlavors
com o valor numérico atribuído à
densidade ou ABI.
No exemplo a seguir, o APK da ABI x86
recebe um versionCode
de 2004, e a ABI x86_64
recebe um versionCode
de 3004.
Atribuir códigos de versão em incrementos maiores, como 1.000, permite
que você atribua posteriormente códigos de versão exclusivos se precisar atualizar seu app. Por
exemplo, se defaultConfig.versionCode
itera para 5 em uma
atualização subsequente, o Gradle atribui um versionCode
de 2005 ao
APK x86
e 3005 ao APK x86_64
.
Dica:se o build inclui um APK universal, atribua um
versionCode
menor do que o dos outros APKs.
Como a Google Play Store instala a versão do app compatível com o
dispositivo de destino e que tem o maior
versionCode
, atribuir um versionCode
menor ao
APK universal garante que a Play Store tente instalar um dos seus
APKs antes do APK universal. O exemplo de código abaixo
processa isso sem substituir o versionCode
padrão de um
APK universal.
Groovy
android { ... defaultConfig { ... versionCode 4 } splits { ... } } // Map for the version code that gives each ABI a value. ext.abiCodes = ['armeabi-v7a':1, x86:2, x86_64:3] // For per-density APKs, create a similar map: // ext.densityCodes = ['mdpi': 1, 'hdpi': 2, 'xhdpi': 3] import com.android.build.OutputFile // For each APK output variant, override versionCode with a combination of // ext.abiCodes * 1000 + variant.versionCode. In this example, variant.versionCode // is equal to defaultConfig.versionCode. If you configure product flavors that // define their own versionCode, variant.versionCode uses that value instead. android.applicationVariants.all { variant -> // Assigns a different version code for each output APK // other than the universal APK. variant.outputs.each { output -> // Stores the value of ext.abiCodes that is associated with the ABI for this variant. def baseAbiVersionCode = // Determines the ABI for this variant and returns the mapped value. project.ext.abiCodes.get(output.getFilter(OutputFile.ABI)) // Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes, // the following code doesn't override the version code for universal APKs. // However, because you want universal APKs to have the lowest version code, // this outcome is desirable. if (baseAbiVersionCode != null) { // Assigns the new version code to versionCodeOverride, which changes the // version code for only the output APK, not for the variant itself. Skipping // this step causes Gradle to use the value of variant.versionCode for the APK. output.versionCodeOverride = baseAbiVersionCode * 1000 + variant.versionCode } } }
Kotlin
android { ... defaultConfig { ... versionCode = 4 } splits { ... } } // Map for the version code that gives each ABI a value. val abiCodes = mapOf("armeabi-v7a" to 1, "x86" to 2, "x86_64" to 3) // For per-density APKs, create a similar map: // val densityCodes = mapOf("mdpi" to 1, "hdpi" to 2, "xhdpi" to 3) import com.android.build.api.variant.FilterConfiguration.FilterType.* // For each APK output variant, override versionCode with a combination of // abiCodes * 1000 + variant.versionCode. In this example, variant.versionCode // is equal to defaultConfig.versionCode. If you configure product flavors that // define their own versionCode, variant.versionCode uses that value instead. androidComponents { onVariants { variant -> // Assigns a different version code for each output APK // other than the universal APK. variant.outputs.forEach { output -> val name = output.filters.find { it.filterType == ABI }?.identifier // Stores the value of abiCodes that is associated with the ABI for this variant. val baseAbiCode = abiCodes[name] // Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes, // the following code doesn't override the version code for universal APKs. // However, because you want universal APKs to have the lowest version code, // this outcome is desirable. if (baseAbiCode != null) { // Assigns the new version code to output.versionCode, which changes the version code // for only the output APK, not for the variant itself. output.versionCode.set(baseAbiCode * 1000 + (output.versionCode.get() ?: 0)) } } } }
Para ver mais exemplos de esquemas de código de versão alternativos, consulte Como atribuir códigos de versão.
Desenvolver vários APKs
Depois de configurar o arquivo build.gradle
ou
build.gradle.kts
do módulo para criar vários APKs, clique em
Build > Build APK para criar todos os APKs para o
módulo selecionado no painel Project. O Gradle cria os APKs
para cada densidade ou ABI no diretório build/outputs/apk/
do projeto.
O Gradle cria um APK para cada densidade ou ABI para as quais você configura vários APKs. Se você habilitar vários APKs para densidades e ABIs, o Gradle criará um APK para cada combinação desses elementos.
Por exemplo, o snippet
build.gradle
a seguir permite criar vários APKs para densidades mdpi
e
hdpi
, bem como para ABIs x86
e x86_64
:
Groovy
... splits { density { enable true reset() include "mdpi", "hdpi" } abi { enable true reset() include "x86", "x86_64" } }
Kotlin
... splits { density { isEnable = true reset() include("mdpi", "hdpi") } abi { isEnable = true reset() include("x86", "x86_64") } }
O resultado da configuração de exemplo inclui os quatro APKs a seguir:
app-hdpiX86-release.apk
: contém código e recursos para densidadehdpi
e ABIx86
.app-hdpiX86_64-release.apk
: contém código e recursos para densidadehdpi
e ABIx86_64
.app-mdpiX86-release.apk
: contém código e recursos para densidademdpi
e ABIx86
.app-mdpiX86_64-release.apk
: contém código e recursos para densidademdpi
e ABIx86_64
.
Ao criar vários APKs com base na densidade de tela, o Gradle sempre gera um APK universal que inclui código e recursos para todas as densidades de tela, além dos APKs por densidade.
Ao criar vários APKs com base na
ABI, o Gradle só gera um APK que inclui código e recursos para todas as
ABIs se você especificar universalApk true
no
bloco splits.abi
do arquivo build.gradle
(para Groovy) ou isUniversalApk = true
no
bloco splits.abi
do arquivo build.gradle.kts
(para script Kotlin).
Formato de nome de arquivo do APK
Ao criar vários APKs, o Gradle gera nomes de arquivos do APK usando o seguinte esquema:
modulename-screendensityABI-buildvariant.apk
Os componentes do esquema são:
-
modulename
- Especifica o nome do módulo que está sendo criado.
-
screendensity
-
Se vários APKs para densidade da tela estão ativados, especifica a densidade
do APK, como
mdpi
. -
ABI
-
Se vários APKs para ABI estão ativados, especifica a ABI do APK, como
x86
.Se vários APKs para densidade de tela e ABI estão ativados, o Gradle concatena o nome da densidade com o nome da ABI, por exemplo,
mdpiX86
. SeuniversalApk
estiver ativado para APKs por ABI, o Gradle vai usaruniversal
como a parte ABI do nome de arquivo do APK universal. -
buildvariant
-
Especifica a variante de build que está sendo criada, como
debug
.
Por exemplo, ao criar o APK de densidade de tela mdpi
para a
versão de depuração de myApp, o nome do arquivo do APK será
myApp-mdpi-debug.apk
. A versão de lançamento
do myApp configurada para criar vários APKs para a
densidade de tela mdpi
e a ABI x86
tem o nome de arquivo do APK
myApp-mdpiX86-release.apk
.