Attenzione: da agosto 2021, tutte le nuove app devono essere pubblicate come App Bundle. Se pubblichi la tua app su Google Play, crea e carica un Android App Bundle. Quando lo fai, Google Play genera e pubblica automaticamente APK ottimizzati per la configurazione del dispositivo di ogni utente, in modo che scarichi solo il codice e le risorse di cui ha bisogno per eseguire la tua app. La pubblicazione di più APK è utile se la stai pubblicando in uno store che non supporta il formato AAB. In questo caso, devi compilare, firmare e gestire ogni APK autonomamente.
Sebbene sia meglio creare un singolo APK per supportare tutti i dispositivi di destinazione , se possibile, questo potrebbe comportare un APK molto grande a causa dei file che supportano più densità di schermo o interfacce di codice macchina (ABI) per le app. Un modo per ridurre le dimensioni dell'APK è creare più APK contenenti file per ABI o densità dello schermo specifiche.
Gradle può creare APK separati che contengono solo codice e risorse specifiche per ogni densità o ABI. Questa pagina descrive come configurare la compilazione per generare più APK. Se devi creare versioni diverse della tua app che non si basano sulla densità dello schermo o sull'ABI, utilizza le varianti di build.
Configurare la build per più APK
Per configurare la compilazione per più APK, aggiungi un blocco
splits
al file build.gradle
a livello di modulo. All'interno del blocco splits
, fornisci un blocco density
che specifichi come vuoi che Gradle generi APK per densità o un blocco abi
che specifichi come vuoi che Gradle generi APK per ABI. Puoi fornire sia blocchi di densità che di ABI e il sistema di compilazione crea un APK per ogni combinazione di densità e ABI.
Configurare più APK per le densità dello schermo
Per creare APK separati per densità di schermo diverse, aggiungi un blocco density
all'interno del blocco splits
. Nel blocco density
, fornisci un
elenco delle densità dello schermo e delle dimensioni dello schermo compatibili che preferisci. Utilizza l'elenco delle dimensioni dello schermo compatibili solo se hai bisogno di elementi
<compatible-screens>
specifici nel manifest di ogni APK.
Le seguenti opzioni DSL di Gradle vengono utilizzate per configurare più APK per le densità dello schermo:
-
enable
per Groovy,isEnable
per lo script Kotlin -
Se imposti questo elemento su
true
, Gradle genera più APK in base alle densità dello schermo che definisci. Il valore predefinito èfalse
. -
exclude
-
Specifica un elenco separato da virgole di densità per le quali non vuoi che Gradle genere APK separati. Utilizza
exclude
se vuoi generare APK per la maggior parte delle densità, ma devi escluderne alcune che la tua app non supporta. -
reset()
-
Cancella l'elenco predefinito delle densità dello schermo. Da utilizzare solo se combinato con l'elemento
include
per specificare le densità da aggiungere.Il seguente snippet imposta l'elenco delle densità su solo
ldpi
exxhdpi
chiamandoreset()
per svuotare l'elenco e poi utilizzandoinclude
:reset() // Clears the default list from all densities // to no densities. include "ldpi", "xxhdpi" // Specifies the two densities to generate APKs // for.
-
include
-
Specifica un elenco separato da virgole di densità per le quali vuoi che Gradle generi APK. Da utilizzare solo in combinazione con
reset()
per specificare un elenco esatto di densità. -
compatibleScreens
-
Specifica un elenco separato da virgole delle dimensioni dello schermo compatibili. In questo modo viene inserito un nodo
<compatible-screens>
corrispondente nel file manifest per ogni APK.Questa impostazione offre un modo pratico per gestire sia le densità sia le dimensioni dello schermo nella stessa sezione
build.gradle
. Tuttavia, l'utilizzo di<compatible-screens>
può limitare i tipi di dispositivi con cui la tua app è compatibile. Per metodi alternativi per supportare schermi di dimensioni diverse, consulta la panoramica della compatibilità con lo schermo.
Poiché ogni APK basato sulla densità dello schermo include un
tag <compatible-screens>
con limitazioni specifiche
sui tipi di schermo supportati dall'APK, anche se pubblichi diversi
APK, alcuni nuovi dispositivi non corrispondono ai tuoi filtri APK. Di conseguenza,
Gradle genera sempre un APK universale aggiuntivo che contiene asset
per tutte le densità dello schermo e non include un
tag <compatible-screens>
. Pubblica questo
APK universale insieme agli APK per densità per fornire un'opzione di riserva per
i dispositivi che non corrispondono agli APK con un
tag <compatible-screens>
.
L'esempio seguente genera un APK separato per ogni
densità dello schermo, ad eccezione di ldpi
, xxhdpi
e
xxxhdpi
. Per farlo, utilizza exclude
per rimuovere queste tre densità dall'elenco predefinito di tutte le densità.
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") } } }
Per ulteriori dettagli sulla personalizzazione di diverse varianti di build della tua app per dispositivi e tipi di schermo specifici, consulta Dichiarare il supporto di schermi con limitazioni.
Configurare più APK per le ABI
Per creare APK separati per ABI diversi, aggiungi un blocco abi
all'interno del blocco splits
. Nel blocco abi
, fornisci un elenco di ABI desiderati.
Le seguenti opzioni DSL di Gradle vengono utilizzate per configurare più APK per ABI:
-
enable
per Groovy oisEnable
per lo script Kotlin - Se imposti questo elemento su
true
, Gradle genera più APK in base alle ABI che definisci. Il valore predefinito èfalse
. -
exclude
-
Specifica un elenco separato da virgole di ABI per i quali non vuoi che Gradle generi APK separati. Utilizza
exclude
se vuoi generare APK per la maggior parte degli ABI, ma devi escludere alcuni ABI non supportati dalla tua app. -
reset()
-
Cancella l'elenco predefinito di ABI. Da utilizzare solo se combinato con l'elemento
include
per specificare gli ABI da aggiungere.Il seguente snippet imposta l'elenco di ABI solo su
x86
ex86_64
chiamandoreset()
per svuotare l'elenco e poi utilizzandoinclude
: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
-
Specifica un elenco separato da virgole di ABI per i quali vuoi che Gradle generi APK. Da utilizzare solo in combinazione con
reset()
per specificare un elenco esatto di ABI. -
universalApk
per Groovy oisUniversalApk
per script Kotlin -
Se
true
, Gradle genera un APK universale oltre agli APK per ABI. Un APK universale contiene codice e risorse per tutte le ABI in un unico APK. Il valore predefinito èfalse
.Tieni presente che questa opzione è disponibile solo nel blocco
splits.abi
. Quando crei più APK in base alla densità dello schermo, Gradle genera sempre un APK universale che contiene codice e risorse per tutte le densità dello schermo.
L'esempio seguente genera un APK separato per ogni ABI: x86
e x86_64
. Per farlo, utilizza reset()
per iniziare con un elenco vuoto di ABI, seguito da include
con un
elenco di ABI a cui viene assegnato un 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 } } }
Per un elenco degli ABI supportati, consulta ABI supportati.
Progetti senza codice nativo/C++
Per i progetti senza codice nativo/C++, il riquadro Varianti di build contiene due colonne: Modulo e Variante di build attiva, come mostrato nella figura 1.
Figura 1. Il riquadro Varianti di compilazione contiene due colonne per i progetti senza codice nativo/C++.
Il valore Active Build Variant (Variante di build attiva) per il modulo determina la variante di build di cui è stato eseguito il deployment e che è visibile nell'editor. Per passare da una variante all'altra, fai clic sulla cella Variante di compilazione attiva per un modulo e scegli la variante che ti interessa dal campo dell'elenco.
Progetti con codice nativo/C++
Per i progetti con codice nativo/C++, il riquadro Varianti di build contiene tre colonne: Modulo, Variante di build attiva e ABI attivo, come mostrato nella figura 2.
Figura 2. Il riquadro Varianti di build aggiunge la colonna ABI attivo per i progetti con codice nativo/C++.
Il valore Active Build Variant (Variante di build attiva) per il modulo determina la variante di build di cui viene eseguito il deployment ed è visibile nell'editor. Per i moduli nativi, il valore ABI attivo determina l'ABI utilizzato dall'editor, ma non influisce su ciò che viene disegnato.
Per modificare il tipo di build o l'ABI:
- Fai clic sulla cella della colonna Variante di build attiva o ABI attivo.
- Scegli la variante o l'ABI che ti interessa dal campo dell'elenco. Viene eseguita automaticamente una nuova sincronizzazione.
La modifica di una delle colonne di un modulo di app o libreria applica la modifica a tutte le righe dipendenti.
Configurare il controllo delle versioni
Per impostazione predefinita, quando Gradle genera più APK, ogni APK ha le stesse informazioni sulla versione, come specificato nel file build.gradle
o build.gradle.kts
a livello di modulo. Poiché il
Google Play Store non consente più APK per la stessa app con tutte le stesse informazioni sulla versione, devi assicurarti che ogni APK abbia un valore
versionCode
univoco prima di caricarlo sul Play Store.
Puoi configurare il file build.gradle
a livello di modulo in modo da eseguire l'override del file versionCode
per ogni APK. Creando una mappatura
che assegna un valore numerico univoco per ogni ABI e densità per cui configuri
più APK, puoi sostituire il codice di versione in uscita con un valore che
combina il codice di versione definito all'interno del blocco defaultConfig
o
productFlavors
con il valore numerico assegnato alla
densità o all'ABI.
Nell'esempio seguente, l'APK per l'ABI x86
viene assegnato un versionCode
pari a 2004 e l'ABI x86_64
viene assegnato un versionCode
pari a 3004.
L'assegnazione di codici di versione con incrementi elevati, ad esempio 1000, consente di assegnare in un secondo momento codici di versione univoci se devi aggiornare l'app. Ad esempio, se defaultConfig.versionCode
esegue l'iterazione fino a 5 in un aggiornamento successivo, Gradle assegna un versionCode
di 2005 all'APK x86
e 3005 all'APK x86_64
.
Suggerimento:se la build include un APK universale, assegnagli un valore versionCode
inferiore a quello di qualsiasi altro APK.
Poiché Google Play Store installa la versione dell'app compatibile con il dispositivo di destinazione e con il valore versionCode
più elevato, l'assegnazione di un valore versionCode
inferiore all'APK universale garantisce che Google Play Store provi a installare uno dei tuoi APK prima di passare all'APK universale. Il seguente codice di esempio
gestisce questo problema non sostituendo il valore predefinito versionCode
di un APK universale.
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)) } } } }
Per altri esempi di schemi di codici di versione alternativi, consulta Assegnare i codici di versione.
Creare più APK
Dopo aver configurato il file build.gradle
o
build.gradle.kts
a livello di modulo per compilare più APK, fai clic su
Compila > Compila APK per compilare tutti gli APK per il modulo attualmente selezionato nel riquadro Progetto. Gradle crea gli APK per ogni densità o ABI nella directory build/outputs/apk/
del progetto.
Gradle genera un APK per ogni densità o ABI per cui configuri più APK. Se attivi più APK sia per le densità che per gli ABI, Gradle crea un APK per ogni combinazione di densità e ABI.
Ad esempio, lo snippet build.gradle
riportato di seguito consente di creare più APK per le densità mdpi
e hdpi
, nonché per le ABI 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") } }
L'output della configurazione di esempio include i seguenti quattro APK:
app-hdpiX86-release.apk
: contiene codice e risorse per la densitàhdpi
e l'ABIx86
.app-hdpiX86_64-release.apk
: contiene codice e risorse per la densitàhdpi
e l'ABIx86_64
.app-mdpiX86-release.apk
: contiene codice e risorse per la densitàmdpi
e l'ABIx86
.app-mdpiX86_64-release.apk
: contiene codice e risorse per la densitàmdpi
e l'ABIx86_64
.
Quando crei più APK in base alla densità dello schermo, Gradle genera sempre un APK universale che include codice e risorse per tutte le densità, oltre agli APK per densità.
Quando crei più APK in base all'ABI, Gradle genera un APK che include codice e risorse per tutti gli ABI solo se specifichi universalApk true
nel blocco splits.abi
del file build.gradle
(per Groovy) o isUniversalApk = true
nel blocco splits.abi
del file build.gradle.kts
(per lo script Kotlin).
Formato del nome del file APK
Quando viene eseguita la compilazione di più APK, Gradle genera i nomi dei file APK utilizzando il seguente schema:
modulename-screendensityABI-buildvariant.apk
I componenti dello schema sono:
-
modulename
- Specifica il nome del modulo in fase di compilazione.
-
screendensity
-
Se sono attivati più APK per la densità dello schermo, specifica la densità dello schermo per l'APK, ad esempio
mdpi
. -
ABI
-
Se sono abilitati più APK per l'ABI, specifica l'ABI per l'APK, ad esempio
x86
.Se sono abilitati più APK sia per la densità dello schermo sia per l'ABI, Gradle concatena il nome della densità con il nome dell'ABI, ad esempio
mdpiX86
. SeuniversalApk
è abilitato per gli APK per ABI, Gradle utilizzauniversal
come parte dell'ABI del nome del file dell'APK universale. -
buildvariant
-
Specifica la variante di build in fase di creazione, ad esempio
debug
.
Ad esempio, quando crei l'APK per la densità dello schermo mdpi
per la versione di debug di myApp, il nome del file APK è myApp-mdpi-debug.apk
. La versione di release di myApp configurata per creare più APK sia per la densità dello schermo mdpi
sia per l'ABI x86
ha il nome file APK myApp-mdpiX86-release.apk
.