Questa pagina mostra come configurare le varianti di compilazione per creare versioni diverse della tua app da un singolo progetto e come gestire correttamente le dipendenze e le configurazioni di firma.
Ogni variante di compilazione rappresenta una versione diversa della tua app che puoi creare. Ad esempio, potresti voler creare una versione della tua app senza costi con un insieme limitato di contenuti e un'altra versione a pagamento che ne include di più. Puoi anche creare versioni diverse della tua app destinate a dispositivi diversi, in base al livello API o ad altre varianti del dispositivo.
Le varianti di compilazione sono il risultato dell'utilizzo da parte di Gradle di un insieme specifico di regole per combinare impostazioni, codice e risorse configurati nei tipi di compilazione e nelle versioni prodotto. Anche se non configuri direttamente le varianti di compilazione, configuri i tipi di compilazione e le versioni prodotto che le formano.
Ad esempio, una versione prodotto "demo" potrebbe specificare determinate funzionalità e requisiti del dispositivo, come codice sorgente, risorse e livelli API minimi personalizzati, mentre il tipo di build "debug" applica impostazioni di build e pacchettizzazione diverse, come opzioni di debug e chiavi di firma. La variante di compilazione che combina questi due elementi è la versione "demoDebug" della tua app e include una combinazione delle configurazioni e delle risorse incluse nella versione prodotto "demo", nel tipo di build "debug" e nel set di risorse main/.
Configura i tipi di build
Puoi creare e configurare i tipi di build all'interno del blocco android del file build.gradle.kts a livello di modulo. Quando crei un nuovo modulo, Android Studio crea automaticamente i tipi di build di debug e di release. Sebbene il tipo di build di debug non venga visualizzato nel file di configurazione di compilazione, Android Studio lo configura con debuggable
true. In questo modo puoi eseguire il debug dell'app su dispositivi Android sicuri e configurare la firma dell'app con un archivio chiavi di debug generico.
Puoi aggiungere il tipo di build di debug alla configurazione se vuoi aggiungere o modificare determinate impostazioni. L'esempio seguente specifica un
applicationIdSuffix per il tipo di build di debug e configura
un tipo di build "staging" inizializzato utilizzando le impostazioni del tipo di build di debug:
Kotlin
android { defaultConfig { manifestPlaceholders["hostName"] = "www.example.com" ... } buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") } getByName("debug") { applicationIdSuffix = ".debug" isDebuggable = true } /** * The `initWith` property lets you copy configurations from other build types, * then configure only the settings you want to change. This one copies the debug build * type, and then changes the manifest placeholder and application ID. */ create("staging") { initWith(getByName("debug")) manifestPlaceholders["hostName"] = "internal.example.com" applicationIdSuffix = ".debugStaging" } } }
Alla moda
android { defaultConfig { manifestPlaceholders = [hostName:"www.example.com"] ... } buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { applicationIdSuffix ".debug" debuggable true } /** * The `initWith` property lets you copy configurations from other build types, * then configure only the settings you want to change. This one copies the debug build * type, and then changes the manifest placeholder and application ID. */ staging { initWith debug manifestPlaceholders = [hostName:"internal.example.com"] applicationIdSuffix ".debugStaging" } } }
Nota:quando apporti modifiche a un file di configurazione di compilazione, Android Studio richiede di sincronizzare il progetto con la nuova configurazione. Per sincronizzare il progetto, fai clic su Sincronizza ora nella barra di notifica che viene visualizzata quando apporti una modifica o fai clic su Sincronizza progetto
nella barra degli strumenti. Se Android Studio rileva errori nella configurazione, viene visualizzata la finestra Messaggi che descrive il problema.
Per scoprire di più su tutte le proprietà che puoi configurare con i tipi di build, leggi il riferimento
BuildType.
Configura le versioni prodotto
La creazione di versioni prodotto è simile alla creazione di tipi di build. Aggiungi le versioni prodotto al blocco productFlavors nella configurazione di compilazione e includi le impostazioni che preferisci.
Le versioni prodotto supportano le stesse proprietà di
defaultConfig, perché defaultConfig
appartiene effettivamente alla classe
ProductFlavor. Ciò significa che puoi fornire la configurazione di base per tutte le versioni nel blocco defaultConfig e ogni versione può modificare uno qualsiasi di questi valori predefiniti, ad esempio applicationId. Per scoprire di più sull'ID applicazione, leggi Imposta l'ID applicazione.
Nota:devi comunque specificare un nome di pacchetto utilizzando l'attributo package nel file manifest main/. Devi anche utilizzare questo nome di pacchetto nel codice sorgente per fare riferimento alla classe R o per risolvere qualsiasi registrazione di attività o servizio relativa. In questo modo, puoi utilizzare applicationId per assegnare a ogni versione prodotto un ID univoco per il pacchetto e la distribuzione senza dover modificare il codice sorgente.
Tutte le versioni devono appartenere a una dimensione versioni denominata, ovvero un gruppo di versioni prodotto. Devi assegnare tutte le versioni a una dimensione versioni, altrimenti riceverai il seguente errore di build.
Error: All flavors must now belong to a named flavor dimension. The flavor 'flavor_name' is not assigned to a flavor dimension.
Se un determinato modulo specifica una sola dimensione versioni, il plug-in Android per Gradle assegna automaticamente tutte le versioni del modulo a quella dimensione.
Il seguente esempio di codice crea una dimensione versioni denominata "version" e aggiunge
le versioni prodotto "demo" e "full". Queste versioni forniscono i propri
applicationIdSuffix e
versionNameSuffix:
Kotlin
android { ... defaultConfig {...} buildTypes { getByName("debug"){...} getByName("release"){...} } // Specifies one flavor dimension. flavorDimensions += "version" productFlavors { create("demo") { // Assigns this product flavor to the "version" flavor dimension. // If you are using only one dimension, this property is optional, // and the plugin automatically assigns all the module's flavors to // that dimension. dimension = "version" applicationIdSuffix = ".demo" versionNameSuffix = "-demo" } create("full") { dimension = "version" applicationIdSuffix = ".full" versionNameSuffix = "-full" } } }
Alla moda
android { ... defaultConfig {...} buildTypes { debug{...} release{...} } // Specifies one flavor dimension. flavorDimensions "version" productFlavors { demo { // Assigns this product flavor to the "version" flavor dimension. // If you are using only one dimension, this property is optional, // and the plugin automatically assigns all the module's flavors to // that dimension. dimension "version" applicationIdSuffix ".demo" versionNameSuffix "-demo" } full { dimension "version" applicationIdSuffix ".full" versionNameSuffix "-full" } } }
Nota:se hai un'app legacy (creata prima di agosto 2021) che distribuisci utilizzando gli APK su Google Play, per distribuirla utilizzando il supporto di più APK in Google Play, assegna lo stesso valore applicationId a tutte le varianti e assegna a ogni variante un versionCode diverso. Per distribuire
diverse varianti della tua app come app separate in Google Play, devi assegnare un
applicationId diverso a ogni variante.
Dopo aver creato e configurato le versioni prodotto, fai clic su Sincronizza ora nella barra di notifica. Al termine della sincronizzazione, Gradle crea automaticamente varianti di compilazione in base ai tipi di compilazione e alle versioni prodotto e le denomina in base a <product-flavor><Build-Type>. Ad esempio, se hai creato le versioni prodotto "demo" e "full" e hai mantenuto i tipi di compilazione predefiniti "debug" e "release", Gradle crea le seguenti varianti di compilazione:
-
demoDebug -
demoRelease -
fullDebug -
fullRelease
Per selezionare la variante di compilazione da creare ed eseguire, vai a Build > Seleziona variante di compilazione e seleziona una variante di compilazione dal menu. Per iniziare a personalizzare ogni variante di compilazione con le proprie funzionalità e risorse, devi creare e gestire i set di risorse, come descritto in questa pagina.
Modifica l'ID applicazione per le varianti di compilazione
Quando crei un APK o un AAB per la tua app, gli strumenti di build la contrassegnano con l'ID applicazione definito nel blocco defaultConfig del file build.gradle.kts, come mostrato nell'esempio seguente. Tuttavia, se vuoi creare versioni diverse della tua app da visualizzare come schede separate sul Google Play Store, ad esempio una versione "senza costi" e una "pro", devi creare varianti di compilazione separate, ciascuna con un ID applicazione diverso.
In questo caso, definisci ogni variante di compilazione come una versione prodotto separata. Per ogni flavor
all'interno del blocco productFlavors, puoi ridefinire la proprietà
applicationId oppure aggiungere un segmento all'ID applicazione predefinito
utilizzando applicationIdSuffix, come mostrato di seguito:
Kotlin
android { defaultConfig { applicationId = "com.example.myapp" } productFlavors { create("free") { applicationIdSuffix = ".free" } create("pro") { applicationIdSuffix = ".pro" } } }
Alla moda
android { defaultConfig { applicationId "com.example.myapp" } productFlavors { free { applicationIdSuffix ".free" } pro { applicationIdSuffix ".pro" } } }
In questo modo, l'ID applicazione per la versione prodotto "senza costi" è "com.example.myapp.free".
Puoi anche utilizzare applicationIdSuffix per aggiungere un segmento in base al tuo tipo di build, come mostrato di seguito:
Kotlin
android { ... buildTypes { getByName("debug") { applicationIdSuffix = ".debug" } } }
Alla moda
android { ... buildTypes { debug { applicationIdSuffix ".debug" } } }
Poiché Gradle applica la configurazione del tipo di compilazione dopo la versione prodotto, l'ID applicazione per la variante di compilazione "free debug" è "com.example.myapp.free.debug". Questo è utile quando vuoi avere sia la build di debug sia quella di release sullo stesso dispositivo, perché non possono esistere due app con lo stesso ID applicazione.
Se hai un'app legacy (creata prima di agosto 2021) che distribuisci utilizzando APK su Google Play e vuoi utilizzare la stessa scheda dell'app per distribuire più APK, ciascuno dei quali ha come target una configurazione dispositivo diversa, ad esempio il livello API, devi utilizzare lo stesso ID applicazione per ogni variante di compilazione, ma assegnare a ogni APK un versionCode diverso. Per maggiori informazioni, leggi la pagina Supporto di più APK. La pubblicazione con gli AAB non è interessata, in quanto utilizza un singolo artefatto che utilizza un singolo codice di versione e un singolo ID applicazione per impostazione predefinita.
Suggerimento: se devi fare riferimento all'ID applicazione nel file manifest, puoi utilizzare il segnaposto ${applicationId} in qualsiasi attributo manifest. Durante una build, Gradle sostituisce questo tag con l'ID applicazione effettivo. Per saperne di più, consulta Inserisci le variabili di build nel manifest.
Combina più versioni prodotto con le dimensioni versioni
In alcuni casi, potresti voler combinare le configurazioni di più versioni prodotto. Ad esempio, potresti voler creare configurazioni diverse per le versioni prodotto "completa" e "demo" in base al livello API. A questo scopo, il plug-in Android per Gradle ti consente di creare più gruppi di versioni prodotto come dimensioni versioni.
Durante la creazione dell'app, Gradle combina una configurazione della versione prodotto di ogni dimensione versioni definita, insieme a una configurazione del tipo di compilazione, per creare la variante di compilazione finale. Gradle non combina le versioni prodotto che appartengono alla stessa dimensione versioni.
Il seguente esempio di codice utilizza la proprietà
flavorDimensions per creare una dimensione versioni "mode" per raggruppare le versioni prodotto "full" e "demo" e una dimensione versioni "api" per raggruppare le configurazioni delle versioni prodotto in base al livello API:
Kotlin
android { ... buildTypes { getByName("debug") {...} getByName("release") {...} } // Specifies the flavor dimensions you want to use. The order in which you // list the dimensions determines their priority, from highest to lowest, // when Gradle merges variant sources and configurations. You must assign // each product flavor you configure to one of the flavor dimensions. flavorDimensions += listOf("api", "mode") productFlavors { create("demo") { // Assigns this product flavor to the "mode" flavor dimension. dimension = "mode" ... } create("full") { dimension = "mode" ... } // Configurations in the "api" product flavors override those in "mode" // flavors and the defaultConfig block. Gradle determines the priority // between flavor dimensions based on the order in which they appear next // to the flavorDimensions property, with the first dimension having a higher // priority than the second, and so on. create("minApi24") { dimension = "api" minSdk = 24 // To ensure the target device receives the version of the app with // the highest compatible API level, assign version codes in increasing // value with API level. versionCode = 30000 + (android.defaultConfig.versionCode ?: 0) versionNameSuffix = "-minApi24" ... } create("minApi23") { dimension = "api" minSdk = 23 versionCode = 20000 + (android.defaultConfig.versionCode ?: 0) versionNameSuffix = "-minApi23" ... } create("minApi21") { dimension = "api" minSdk = 21 versionCode = 10000 + (android.defaultConfig.versionCode ?: 0) versionNameSuffix = "-minApi21" ... } } } ...
Alla moda
android { ... buildTypes { debug {...} release {...} } // Specifies the flavor dimensions you want to use. The order in which you // list the dimensions determines their priority, from highest to lowest, // when Gradle merges variant sources and configurations. You must assign // each product flavor you configure to one of the flavor dimensions. flavorDimensions "api", "mode" productFlavors { demo { // Assigns this product flavor to the "mode" flavor dimension. dimension "mode" ... } full { dimension "mode" ... } // Configurations in the "api" product flavors override those in "mode" // flavors and the defaultConfig block. Gradle determines the priority // between flavor dimensions based on the order in which they appear next // to the flavorDimensions property, with the first dimension having a higher // priority than the second, and so on. minApi24 { dimension "api" minSdkVersion 24 // To ensure the target device receives the version of the app with // the highest compatible API level, assign version codes in increasing // value with API level. versionCode 30000 + android.defaultConfig.versionCode versionNameSuffix "-minApi24" ... } minApi23 { dimension "api" minSdkVersion 23 versionCode 20000 + android.defaultConfig.versionCode versionNameSuffix "-minApi23" ... } minApi21 { dimension "api" minSdkVersion 21 versionCode 10000 + android.defaultConfig.versionCode versionNameSuffix "-minApi21" ... } } } ...
Il numero di varianti di compilazione create da Gradle è uguale al prodotto del numero di versioni in ogni dimensione versioni e del numero di tipi di compilazione configurati. Quando Gradle assegna un nome a ogni variante di compilazione o agli artefatti corrispondenti, le versioni prodotto appartenenti alla dimensione versioni con priorità più alta vengono visualizzate per prime, seguite da quelle delle dimensioni con priorità più bassa, seguite dal tipo di build.
Utilizzando la configurazione di compilazione precedente come esempio, Gradle crea un totale di 12 varianti di compilazione con il seguente schema di denominazione:
- Variante di compilazione:
[minApi24, minApi23, minApi21][Demo, Full][Debug, Release] - APK corrispondente:
app-[minApi24, minApi23, minApi21]-[demo, full]-[debug, release].apk - Ad esempio,
- Variante di compilazione:
minApi24DemoDebug - APK corrispondente:
app-minApi24-demo-debug.apk
Oltre alle directory dei set di risorse che puoi creare per ogni singola versione prodotto e variante di compilazione, puoi anche creare directory dei set di risorse per ogni combinazione di versioni prodotto. Ad esempio, puoi creare
e aggiungere origini Java alla directory src/demoMinApi24/java/
e Gradle utilizza queste origini solo quando crea una variante che combina
queste due versioni prodotto.
I set di risorse creati per le combinazioni di versioni prodotto hanno una priorità più alta rispetto ai set di risorse appartenenti a ogni singola versione prodotto. Per scoprire di più sui set di risorse e su come Gradle unisce le risorse, leggi la sezione su come creare set di risorse.
Filtrare le varianti
Gradle crea una variante di compilazione per ogni possibile combinazione di versioni prodotto e tipi di compilazione configurati. Tuttavia, potrebbero esserci alcune varianti di compilazione che non ti servono o che non hanno senso nel contesto del tuo progetto. Per rimuovere determinate configurazioni delle varianti di compilazione, crea un filtro delle varianti nel file build.gradle.kts a livello di modulo.
Utilizzando come esempio la configurazione di compilazione della sezione precedente, supponiamo che tu preveda di supportare solo i livelli API 23 e superiori per la versione demo dell'app. Puoi utilizzare il blocco
variantFilter per filtrare tutte le configurazioni delle varianti di compilazione che combinano le versioni prodotto "minApi21" e "demo":
Kotlin
android { ... buildTypes {...} flavorDimensions += listOf("api", "mode") productFlavors { create("demo") {...} create("full") {...} create("minApi24") {...} create("minApi23") {...} create("minApi21") {...} } } androidComponents { beforeVariants { variantBuilder -> // To check for a certain build type, use variantBuilder.buildType == "<buildType>" if (variantBuilder.productFlavors.containsAll(listOf("api" to "minApi21", "mode" to "demo"))) { // Gradle ignores any variants that satisfy the conditions above. variantBuilder.enable = false } } } ...
Alla moda
android { ... buildTypes {...} flavorDimensions "api", "mode" productFlavors { demo {...} full {...} minApi24 {...} minApi23 {...} minApi21 {...} } variantFilter { variant -> def names = variant.flavors*.name // To check for a certain build type, use variant.buildType.name == "<buildType>" if (names.contains("minApi21") && names.contains("demo")) { // Gradle ignores any variants that satisfy the conditions above. setIgnore(true) } } } ...
Dopo aver aggiunto un filtro delle varianti alla configurazione di compilazione e aver fatto clic su Sincronizza ora nella barra di notifica, Gradle ignora tutte le varianti di compilazione che soddisfano le condizioni specificate. Le varianti di compilazione non vengono più visualizzate nel menu quando fai clic su Compila > Seleziona variante di compilazione dalla barra dei menu o su Varianti di compilazione
nella barra della finestra degli strumenti.
Crea set di risorse
Per impostazione predefinita, Android Studio crea il set di risorse main/ e le directory per tutto ciò che vuoi condividere tra tutte le varianti di compilazione. Tuttavia, puoi creare nuovi set di risorse per controllare esattamente quali file Gradle compila e pacchettizza per tipi di compilazione, versioni prodotto, combinazioni di versioni prodotto (quando utilizzi le dimensioni versioni) e varianti di compilazione specifici.
Ad esempio, puoi definire la funzionalità di base nel set di risorse main/ e utilizzare i set di risorse delle versioni prodotto per modificare il branding della tua app per clienti diversi oppure includere autorizzazioni speciali e funzionalità di logging solo per le varianti di compilazione che utilizzano il tipo di build di debug.
Gradle prevede che i file e le directory del set di risorse siano organizzati in un certo modo, simile al set di risorse main/. Ad esempio, Gradle
si aspetta che i file di classe Kotlin o Java specifici per il tipo di build "debug" si trovino
nelle directory src/debug/kotlin/ o src/debug/java/.
Il plug-in Android per Gradle fornisce un'attività Gradle utile che mostra come organizzare i file per ciascuno dei tipi di compilazione, delle versioni prodotto e delle varianti di compilazione. Ad esempio, il seguente esempio dell'output dell'attività descrive dove Gradle prevede di trovare determinati file per il tipo di build "debug":
------------------------------------------------------------ Project :app ------------------------------------------------------------ ... debug ---- Compile configuration: debugCompile build.gradle name: android.sourceSets.debug Java sources: [app/src/debug/java] Kotlin sources: [app/src/debug/kotlin, app/src/debug/java] Manifest file: app/src/debug/AndroidManifest.xml Android resources: [app/src/debug/res] Assets: [app/src/debug/assets] AIDL sources: [app/src/debug/aidl] RenderScript sources: [app/src/debug/rs] JNI sources: [app/src/debug/jni] JNI libraries: [app/src/debug/jniLibs] Java-style resources: [app/src/debug/resources]
Per visualizzare questo output, procedi nel seguente modo:
- Fai clic su Gradle nella barra della finestra degli strumenti.
Vai a MyApplication > Tasks > android e fai doppio clic su sourceSets.
Per visualizzare la cartella Attività, devi consentire a Gradle di creare l'elenco di attività durante la sincronizzazione. Per farlo, segui questi passaggi:
- Fai clic su File > Impostazioni > Sperimentale (Android Studio > Impostazioni > Sperimentale su macOS).
- Deseleziona Non creare l'elenco di attività Gradle durante la sincronizzazione di Gradle.
- Dopo che Gradle ha eseguito l'attività, si apre la finestra Esegui per visualizzare l'output.
Nota: l'output dell'attività mostra anche come organizzare i set di risorse per i file che vuoi utilizzare per eseguire i test per la tua app, ad esempio i set di risorse di test test/ e androidTest/.
Quando crei una nuova variante di compilazione, Android Studio non crea le directory dei set di risorse, ma ti offre alcune opzioni per aiutarti. Ad esempio, per creare solo la directory java/ per il tipo di build "debug":
- Apri il riquadro Progetto e seleziona la visualizzazione Progetto dal menu nella parte superiore del riquadro.
- Vai all'app
MyProject/app/src/. - Fai clic con il tasto destro del mouse sulla directory
srce seleziona Nuovo > Directory. - Dal menu in Set di risorse Gradle, seleziona full/java.
- Premi Invio.
Android Studio crea una directory del set di risorse per il tipo di build di debug e poi crea la directory java/ al suo interno. In alternativa, Android Studio può creare le directory per te quando aggiungi un nuovo file al progetto per una variante di compilazione specifica.
Ad esempio, per creare un file XML di valori per il tipo di build "debug":
- Nel riquadro Progetto, fai clic con il tasto destro del mouse sulla directory
srce seleziona Nuovo > XML > File XML di valori. - Inserisci il nome del file XML o mantieni il nome predefinito.
- Dal menu accanto a Set di risorse di destinazione, seleziona debug.
- Fai clic su Fine.
Poiché il tipo di build "debug" è stato specificato come set di risorse di destinazione, Android Studio crea automaticamente le directory necessarie quando crea il file XML. La struttura di directory risultante è simile alla figura 1.
Figura 1. Nuove directory del set di risorse per il tipo di build "debug".
I set di risorse attivi hanno un indicatore verde nella loro icona per mostrare che sono attivi. Il set di risorse debug ha il suffisso [main] per indicare che verrà unito al set di risorse main.
Utilizzando la stessa procedura, puoi anche creare directory dei set di risorse per le versioni prodotto, ad esempio src/demo/, e le varianti di compilazione, ad esempio src/demoDebug/. Inoltre, puoi creare set di risorse di test che hanno come target varianti di compilazione specifiche, ad esempio src/androidTestDemoDebug/. Per scoprire di più, consulta la sezione relativa ai set di risorse di test.
Modifica le configurazioni predefinite del set di risorse
Se hai origini che non sono organizzate nella struttura dei file del set di risorse predefinito prevista da Gradle, come descritto nella sezione precedente sulla creazione di set di risorse, puoi utilizzare il blocco
sourceSets per modificare la posizione in cui Gradle cerca i file per ogni componente di un set di risorse.
Il blocco sourceSets deve trovarsi nel blocco android. Non è necessario spostare i file di origine, ma devi solo fornire a Gradle i percorsi, relativi al file build.gradle.kts a livello di modulo, in cui Gradle può trovare i file per ogni componente del set di risorse. Per scoprire quali componenti puoi configurare e se puoi mapparli a più file o directory, consulta il Riferimento API del plug-in Android per Gradle.
Il seguente esempio di codice mappa le origini dalla directory app/other/ a determinati componenti del set di risorse main e modifica la directory principale del set di risorse androidTest:
Kotlin
android { ... // Encapsulates configurations for the main source set. sourceSets.getByName("main") { // Changes the directory for Java sources. The default directory is // 'src/main/java'. java.setSrcDirs(listOf("other/java")) // If you list multiple directories, Gradle uses all of them to collect // sources. Because Gradle gives these directories equal priority, if // you define the same resource in more than one directory, you receive an // error when merging resources. The default directory is 'src/main/res'. res.setSrcDirs(listOf("other/res1", "other/res2")) // Note: Avoid specifying a directory that is a parent to one // or more other directories you specify. For example, avoid the following: // res.srcDirs = ['other/res1', 'other/res1/layouts', 'other/res1/strings'] // Specify either only the root 'other/res1' directory or only the // nested 'other/res1/layouts' and 'other/res1/strings' directories. // For each source set, you can specify only one Android manifest. // By default, Android Studio creates a manifest for your main source // set in the src/main/ directory. manifest.srcFile("other/AndroidManifest.xml") ... } // Create additional blocks to configure other source sets. sourceSets.getByName("androidTest") { // If all the files for a source set are located under a single root // directory, you can specify that directory using the setRoot property. // When gathering sources for the source set, Gradle looks only in locations // relative to the root directory you specify. For example, after applying the // configuration below for the androidTest source set, Gradle looks for Java // sources only in the src/tests/java/ directory. setRoot("src/tests") ... } } ...
Alla moda
android { ... sourceSets { // Encapsulates configurations for the main source set. main { // Changes the directory for Java sources. The default directory is // 'src/main/java'. java.srcDirs = ['other/java'] // If you list multiple directories, Gradle uses all of them to collect // sources. Because Gradle gives these directories equal priority, if // you define the same resource in more than one directory, you receive an // error when merging resources. The default directory is 'src/main/res'. res.srcDirs = ['other/res1', 'other/res2'] // Note: Avoid specifying a directory that is a parent to one // or more other directories you specify. For example, avoid the following: // res.srcDirs = ['other/res1', 'other/res1/layouts', 'other/res1/strings'] // Specify either only the root 'other/res1' directory or only the // nested 'other/res1/layouts' and 'other/res1/strings' directories. // For each source set, you can specify only one Android manifest. // By default, Android Studio creates a manifest for your main source // set in the src/main/ directory. manifest.srcFile 'other/AndroidManifest.xml' ... } // Create additional blocks to configure other source sets. androidTest { // If all the files for a source set are located under a single root // directory, you can specify that directory using the setRoot property. // When gathering sources for the source set, Gradle looks only in locations // relative to the root directory you specify. For example, after applying the // configuration below for the androidTest source set, Gradle looks for Java // sources only in the src/tests/java/ directory. setRoot 'src/tests' ... } } } ...
Tieni presente che una directory di origine può appartenere a un solo set di risorse. Ad esempio, non puoi condividere le stesse origini di test con i set di risorse test e androidTest. Questo perché Android Studio crea moduli IntelliJ separati per ogni set di risorse e non può supportare radici di contenuti duplicate tra i set di risorse.
Crea con i set di risorse
Puoi utilizzare le directory dei set di risorse per contenere il codice e le risorse che vuoi pacchettizzare solo con determinate configurazioni. Ad esempio, se stai creando la variante di compilazione "demoDebug", che è il prodotto incrociato di una versione prodotto "demo" e di un tipo di build "debug", Gradle esamina queste directory e assegna loro la seguente priorità:
-
src/demoDebug/(set di risorse della variante di compilazione) -
src/debug/(set di risorse del tipo di build) -
src/demo/(set di risorse della versione prodotto) -
src/main/(set di risorse principale)
I set di risorse creati per le combinazioni di versioni prodotto devono includere tutte le dimensioni versioni. Ad esempio, il set di risorse della variante di compilazione deve essere la combinazione del tipo di compilazione e di tutte le dimensioni versioni. L'unione di codice e risorse che coinvolgono cartelle che coprono più dimensioni versioni, ma non tutte, non è supportata.
Se combini più versioni prodotto, la priorità tra le versioni prodotto è determinata dalla dimensione versioni a cui appartengono. Quando elenchi le dimensioni versioni con la proprietà
android.flavorDimensions, le versioni prodotto vengono ordinate in base alle dimensioni dichiarate, con le dimensioni precedenti che hanno la precedenza su quelle successive. Inoltre, i set di risorse creati per le combinazioni di versioni prodotto hanno una priorità maggiore rispetto ai set di risorse che appartengono a una singola versione prodotto.
L'ordine di priorità determina quale set di risorse ha una priorità più alta quando Gradle combina codice e risorse. Poiché la directory del set di risorse demoDebug/ probabilmente contiene file specifici per quella variante di build, se demoDebug/ include un file definito anche in debug/, Gradle utilizza il file nel set di risorse demoDebug/. Analogamente, Gradle assegna ai file nei set di risorse del tipo di build e della versione prodotto una priorità più alta rispetto agli stessi file in main/.
Gradle considera questo ordine di priorità quando applica le seguenti regole di build:
- Tutto il codice sorgente nelle directory
kotlin/ojava/viene compilato insieme per generare un singolo output.Nota:per una determinata variante di compilazione, Gradle genera un errore di compilazione se rileva due o più directory di set di risorse che hanno definito la stessa classe Kotlin o Java. Ad esempio, quando crei un'app di debug, non puoi definire sia
src/debug/Utility.ktsiasrc/main/Utility.kt, perché Gradle esamina entrambe queste directory durante il processo di build e genera un errore "classe duplicata". Se vuoi versioni diverse diUtility.ktper diversi tipi di build, ogni tipo di build deve definire la propria versione del file e non includerla nel set di risorsemain/. - I manifest vengono uniti in un unico manifest. La priorità viene assegnata nello stesso ordine dell'elenco nell'esempio precedente. Ad esempio, le impostazioni del manifest per un tipo di build sostituiscono le impostazioni del manifest per una versione prodotto. Per saperne di più, consulta l'articolo sull'unione dei manifest.
- I file nelle directory
values/vengono uniti. Se due file hanno lo stesso nome, ad esempio due filestrings.xml, la priorità viene assegnata nello stesso ordine dell'elenco nell'esempio precedente. Ad esempio, i valori definiti in un file nel set di risorse del tipo di build sostituiscono i valori definiti nello stesso file in una versione prodotto. - Le risorse nelle directory
res/easset/vengono pacchettizzate insieme. Se sono presenti risorse con lo stesso nome definite in due o più set di risorse, la priorità viene assegnata nello stesso ordine dell'elenco nell'esempio precedente. - Gradle assegna alle risorse e ai manifest inclusi nelle dipendenze dei moduli della libreria la priorità più bassa durante la creazione dell'app.
Dichiarazione di dipendenze
Per configurare una dipendenza per una variante di compilazione o un set di risorse di test specifico, aggiungi il nome della variante di compilazione o del set di risorse di test prima della parola chiave Implementation, come mostrato nell'esempio seguente:
Kotlin
dependencies { // Adds the local "mylibrary" module as a dependency to the "free" flavor. "freeImplementation"(project(":mylibrary")) // Adds a remote binary dependency only for local tests. testImplementation("junit:junit:4.12") // Adds a remote binary dependency only for the instrumented test APK. androidTestImplementation("com.android.support.test.espresso:espresso-core:3.6.1") }
Alla moda
dependencies { // Adds the local "mylibrary" module as a dependency to the "free" flavor. freeImplementation project(":mylibrary") // Adds a remote binary dependency only for local tests. testImplementation 'junit:junit:4.12' // Adds a remote binary dependency only for the instrumented test APK. androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.6.1' }
Per saperne di più sulla configurazione delle dipendenze, consulta Aggiungi dipendenze di build.
Utilizza la gestione delle dipendenze basata sulle varianti
Il plug-in Android per Gradle 3.0.0 e versioni successive include un nuovo meccanismo di dipendenza che abbina automaticamente le varianti quando si utilizza una libreria. Ad esempio, la variante debug di un'app utilizza automaticamente la variante debug di una libreria. Funziona anche quando si utilizzano
le versioni: la variante freeDebug di un'app utilizzerà la variante freeDebug
di una libreria.
Affinché il plug-in possa abbinare con precisione le varianti, devi fornire i fallback corrispondenti, come descritto nella sezione seguente, per i casi in cui non è possibile un abbinamento diretto.
Ad esempio, supponiamo che la tua app configuri un tipo di build denominato "staging", ma una delle sue dipendenze della libreria no. Quando il plug-in tenta di creare la versione "staging" della tua app, non saprà quale versione della libreria utilizzare e verrà visualizzato un messaggio di errore simile al seguente:
Error:Failed to resolve: Could not resolve project :mylibrary.
Required by:
project :app
Risolvi gli errori di build relativi alla corrispondenza delle varianti
Il plug-in include elementi DSL per aiutarti a controllare il modo in cui Gradle risolve le situazioni in cui non è possibile una corrispondenza diretta delle varianti tra un'app e una dipendenza.
Di seguito è riportato un elenco di problemi relativi alla corrispondenza delle dipendenze sensibili alle varianti e come risolverli utilizzando le proprietà DSL:
La tua app include un tipo di build che non è presente in una dipendenza della libreria.
Ad esempio, la tua app include un tipo di build "staging", ma una dipendenza include solo i tipi di build "debug" e "release".
Tieni presente che non si verifica alcun problema quando una dipendenza della libreria include un tipo di build che la tua app non include. Questo perché il plug-in non richiede mai quel tipo di build dalla dipendenza.
Utilizza
matchingFallbacksper specificare corrispondenze alternative per un determinato tipo di build, come mostrato qui:Kotlin
// In the app's build.gradle.kts file. android { buildTypes { getByName("debug") {} getByName("release") {} create("staging") { // Specifies a sorted list of fallback build types that the // plugin can try to use when a dependency does not include a // "staging" build type. You may specify as many fallbacks as you // like, and the plugin selects the first build type that's // available in the dependency. matchingFallbacks += listOf("debug", "qa", "release") } } }
Alla moda
// In the app's build.gradle file. android { buildTypes { debug {} release {} staging { // Specifies a sorted list of fallback build types that the // plugin can try to use when a dependency does not include a // "staging" build type. You may specify as many fallbacks as you // like, and the plugin selects the first build type that's // available in the dependency. matchingFallbacks = ['debug', 'qa', 'release'] } } }
Per una determinata dimensione versioni presente sia nell'app sia nella relativa dipendenza dalla libreria, l'app include versioni non presenti nella libreria.
Ad esempio, sia la tua app sia le sue dipendenze della libreria includono una dimensione versioni "tier". Tuttavia, la dimensione "tier" nell'app include i flavor "free" e "paid", ma una dipendenza include solo i flavor "demo" e "paid" per la stessa dimensione.
Tieni presente che per una determinata dimensione versioni esistente sia nell'app sia nelle relative dipendenze di libreria, non si verifica alcun problema quando una libreria include una versione prodotto non inclusa nell'app. Questo perché il plug-in non richiede mai questa versione dalla dipendenza.
Utilizza
matchingFallbacksper specificare corrispondenze alternative per la versione prodotto "senza costi " dell'app, come mostrato qui:Kotlin
// In the app's build.gradle.kts file. android { defaultConfig{ // Don't configure matchingFallbacks in the defaultConfig block. // Instead, specify fallbacks for a given product flavor in the // productFlavors block, as shown below. } flavorDimensions += "tier" productFlavors { create("paid") { dimension = "tier" // Because the dependency already includes a "paid" flavor in its // "tier" dimension, you don't need to provide a list of fallbacks // for the "paid" flavor. } create("free") { dimension = "tier" // Specifies a sorted list of fallback flavors that the plugin // can try to use when a dependency's matching dimension does // not include a "free" flavor. Specify as many // fallbacks as you like; the plugin selects the first flavor // that's available in the dependency's "tier" dimension. matchingFallbacks += listOf("demo", "trial") } } }
Alla moda
// In the app's build.gradle file. android { defaultConfig{ // Don't configure matchingFallbacks in the defaultConfig block. // Instead, specify fallbacks for a given product flavor in the // productFlavors block, as shown below. } flavorDimensions 'tier' productFlavors { paid { dimension 'tier' // Because the dependency already includes a "paid" flavor in its // "tier" dimension, you don't need to provide a list of fallbacks // for the "paid" flavor. } free { dimension 'tier' // Specifies a sorted list of fallback flavors that the plugin // can try to use when a dependency's matching dimension does // not include a "free" flavor. Specify as many // fallbacks as you like; the plugin selects the first flavor // that's available in the dependency's "tier" dimension. matchingFallbacks = ['demo', 'trial'] } } }
Una dipendenza della libreria include una dimensione versioni non presente nella tua app.
Ad esempio, una dipendenza della libreria include versioni per una dimensione "minApi", ma la tua app include versioni solo per la dimensione "tier". Quando vuoi creare la versione "freeDebug" della tua app, il plug-in non sa se utilizzare la versione "minApi23Debug" o "minApi18Debug" della dipendenza.
Tieni presente che non si verifica alcun problema se la tua app include una dimensione versioni che non è presente in una dipendenza della libreria. Questo perché il plug-in corrisponde solo alle versioni delle dimensioni che esistono nella dipendenza. Ad esempio, se una dipendenza non include una dimensione per le ABI, la versione "freeX86Debug" della tua app utilizzerà la versione "freeDebug" della dipendenza.
Utilizza
missingDimensionStrategynel bloccodefaultConfigper specificare la versione predefinita che il plug-in deve selezionare da ogni dimensione mancante, come mostrato nell'esempio seguente. Puoi anche eseguire l'override delle selezioni nel bloccoproductFlavors, in modo che ogni flavor possa specificare una strategia di corrispondenza diversa per una dimensione mancante.Kotlin
// In the app's build.gradle.kts file. android { defaultConfig{ // Specifies a sorted list of flavors that the plugin can try to use from // a given dimension. This tells the plugin to select the "minApi18" flavor // when encountering a dependency that includes a "minApi" dimension. // You can include additional flavor names to provide a // sorted list of fallbacks for the dimension. missingDimensionStrategy("minApi", "minApi18", "minApi23") // Specify a missingDimensionStrategy property for each // dimension that exists in a local dependency but not in your app. missingDimensionStrategy("abi", "x86", "arm64") } flavorDimensions += "tier" productFlavors { create("free") { dimension = "tier" // You can override the default selection at the product flavor // level by configuring another missingDimensionStrategy property // for the "minApi" dimension. missingDimensionStrategy("minApi", "minApi23", "minApi18") } create("paid") {} } }
Alla moda
// In the app's build.gradle file. android { defaultConfig{ // Specifies a sorted list of flavors that the plugin can try to use from // a given dimension. This tells the plugin to select the "minApi18" flavor // when encountering a dependency that includes a "minApi" dimension. // You can include additional flavor names to provide a // sorted list of fallbacks for the dimension. missingDimensionStrategy 'minApi', 'minApi18', 'minApi23' // Specify a missingDimensionStrategy property for each // dimension that exists in a local dependency but not in your app. missingDimensionStrategy 'abi', 'x86', 'arm64' } flavorDimensions 'tier' productFlavors { free { dimension 'tier' // You can override the default selection at the product flavor // level by configuring another missingDimensionStrategy property // for the 'minApi' dimension. missingDimensionStrategy 'minApi', 'minApi23', 'minApi18' } paid {} } }
Per saperne di più, consulta matchingFallbacks
e missingDimensionStrategy
nel riferimento DSL del plug-in Android per Gradle.
Configura le impostazioni di firma
Gradle non firma l'APK o l'AAB della build di release, a meno che non definisci esplicitamente una configurazione di firma per questa build. Se non hai ancora una chiave di firma, genera una chiave di caricamento e un keystore utilizzando Android Studio.
Per configurare manualmente le configurazioni di firma per il tipo di build di release utilizzando le configurazioni di build di Gradle:
- Crea un archivio chiavi. Un keystore è un file binario che contiene un insieme di chiavi private. Devi conservare il keystore in un luogo sicuro.
- Crea una chiave privata. Una chiave privata viene utilizzata per firmare l'app per la distribuzione e non viene mai inclusa nell'app né divulgata a terze parti non autorizzate.
-
Aggiungi la configurazione di firma al file
build.gradle.ktsa livello di modulo:Kotlin
... android { ... defaultConfig {...} signingConfigs { create("release") { storeFile = file("myreleasekey.keystore") storePassword = "password" keyAlias = "MyReleaseKey" keyPassword = "password" } } buildTypes { getByName("release") { ... signingConfig = signingConfigs.getByName("release") } } }
Alla moda
... android { ... defaultConfig {...} signingConfigs { release { storeFile file("myreleasekey.keystore") storePassword "password" keyAlias "MyReleaseKey" keyPassword "password" } } buildTypes { release { ... signingConfig signingConfigs.release } } }
Nota:l'inclusione delle password per la chiave di rilascio e il keystore all'interno del file di build non è una buona pratica di sicurezza. Configura invece il file di build in modo da ottenere queste password dalle variabili di ambiente o fai in modo che il processo di build ti chieda di inserirle.
Per ottenere queste password dalle variabili di ambiente:
Kotlin
storePassword = System.getenv("KSTOREPWD") keyPassword = System.getenv("KEYPWD")
Alla moda
storePassword System.getenv("KSTOREPWD") keyPassword System.getenv("KEYPWD")
In alternativa, puoi caricare il keystore da un file di proprietà locale. Per motivi di sicurezza, non aggiungere questo file al controllo del codice sorgente. Configuralo invece localmente per ogni sviluppatore. Per scoprire di più, leggi Rimuovi le informazioni di firma dai file di build.
Dopo aver completato questa procedura, puoi distribuire la tua app e pubblicarla su Google Play.
Avviso:conserva l'archivio chiavi e la chiave privata in un luogo sicuro e assicurati di avere backup sicuri. Se utilizzi la firma dell'app di Google Play e perdi la chiave di caricamento, puoi richiedere una reimpostazione tramite Play Console. Se pubblichi un'app senza la firma dell'app di Google Play (per le app create prima di agosto 2021) e perdi la chiave di firma dell'app, non potrai pubblicare aggiornamenti per l'app, poiché devi sempre firmare tutte le versioni dell'app con la stessa chiave.
Firma delle app per Wear OS
Quando pubblichi app per Wear OS, sia l'APK per smartwatch sia l'APK per smartphone facoltativo devono essere firmati con la stessa chiave. Per maggiori informazioni sulla pacchettizzazione e sulla firma delle app per Wear OS, consulta la pagina Pacchettizzare e distribuire app Wear.