Auf dieser Seite erfahren Sie, wie Sie Buildvarianten konfigurieren, um aus einem einzigen Projekt verschiedene Versionen Ihrer App zu erstellen, und wie Sie Ihre Abhängigkeiten und Signaturkonfigurationen richtig verwalten.
Jede Buildvariante steht für eine andere Version Ihrer App, die Sie erstellen können. Sie können beispielsweise eine kostenlose Version Ihrer App mit begrenzten Inhalten und eine kostenpflichtige Version mit mehr Inhalten erstellen. Sie können auch verschiedene Versionen Ihrer App erstellen, die auf verschiedene Geräte ausgerichtet sind, je nach API-Level oder anderen Gerätevarianten.
Buildvarianten entstehen, wenn Gradle mithilfe einer bestimmten Reihe von Regeln Einstellungen, Code und Ressourcen kombiniert, die in Ihren Buildtypen und Produktvarianten konfiguriert sind. Sie konfigurieren Build-Varianten zwar nicht direkt, aber die Build-Typen und Produktvarianten, aus denen sie bestehen.
So können Sie beispielsweise für einen Produktvariantentyp vom Typ „Demo“ bestimmte Funktionen und Geräteanforderungen festlegen, z. B. benutzerdefinierten Quellcode, Ressourcen und minimale API-Ebenen, während für den Buildtyp „debug“ (Fehlerbehebung) andere Build- und Verpackungseinstellungen wie Debug-Optionen und Signaturschlüssel gelten. Die Buildvariante, die diese beiden kombiniert, ist die „demoDebug“-Version Ihrer App. Sie enthält eine Kombination aus den Konfigurationen und Ressourcen, die im Produkt-Flavor „demo“, dem Buildtyp „debug“ und dem main/
-Quellsatz enthalten sind.
Buildtypen konfigurieren
Sie können Buildtypen im Block android
der build.gradle.kts
-Datei auf Modulebene erstellen und konfigurieren. Wenn Sie ein neues Modul erstellen, werden in Android Studio automatisch die Buildtypen „Debug“ und „Release“ erstellt. Der Debug-Buildtyp wird zwar nicht in der Build-Konfigurationsdatei angezeigt, aber in Android Studio mit debuggable
true
konfiguriert. So können Sie die App auf sicheren Android-Geräten debuggen und die App-Signatur mit einem generischen Debug-Schlüsselspeicher konfigurieren.
Sie können der Konfiguration den Buildtyp „Debug“ hinzufügen, wenn Sie bestimmte Einstellungen hinzufügen oder ändern möchten. Im folgenden Beispiel wird ein
applicationIdSuffix
für den Debug-Buildtyp angegeben und ein Buildtyp vom Typ „Staging“ konfiguriert, der mit den Einstellungen aus dem Debug-Buildtyp initialisiert wird:
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" } } }
Groovy
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" } } }
Hinweis:Wenn Sie Änderungen an einer Build-Konfigurationsdatei vornehmen, müssen Sie Ihr Projekt in Android Studio mit der neuen Konfiguration synchronisieren. Wenn Sie Ihr Projekt synchronisieren möchten, klicken Sie in der Benachrichtigungsleiste, die nach einer Änderung angezeigt wird, auf Jetzt synchronisieren oder in der Symbolleiste auf Projekt synchronisieren . Wenn Android Studio Fehler in Ihrer Konfiguration erkennt, wird das Fenster Nachrichten mit einer Beschreibung des Problems angezeigt.
Weitere Informationen zu allen Properties, die Sie mit Buildtypen konfigurieren können, finden Sie in der
BuildType
-Referenz.
Produktvarianten konfigurieren
Das Erstellen von Produktvarianten ähnelt dem Erstellen von Buildtypen. Fügen Sie dem Block productFlavors
in Ihrer Build-Konfiguration Produktvarianten hinzu und geben Sie die gewünschten Einstellungen an.
Die Produktvarianten unterstützen dieselben Properties wie defaultConfig
, da defaultConfig
zur Klasse
ProductFlavor
gehört. Das bedeutet, dass Sie die Basiskonfiguration für alle Varianten im Block defaultConfig
angeben können und jede Variante diese Standardwerte ändern kann, z. B. applicationId
. Weitere Informationen zur App-ID
Hinweis:Sie müssen weiterhin einen Paketnamen mit dem Attribut package
in der Manifestdatei main/
angeben. Sie müssen diesen Paketnamen auch in Ihrem Quellcode verwenden, um auf die R
-Klasse zu verweisen oder relative Aktivitäten oder Dienstregistrierungen aufzulösen. So können Sie mit applicationId
jeder Produktvariante eine eindeutige ID für die Verpackung und den Vertrieb zuweisen, ohne den Quellcode ändern zu müssen.
Alle Geschmacksrichtungen müssen zu einer benannten Geschmacksdimension gehören, also einer Gruppe von Produktgeschmacksrichtungen. Sie müssen allen Varianten eine Variantendimension zuweisen. Andernfalls wird der folgende Buildfehler angezeigt.
Error: All flavors must now belong to a named flavor dimension. The flavor 'flavor_name' is not assigned to a flavor dimension.
Wenn für ein bestimmtes Modul nur eine Flavor-Dimension angegeben ist, weist das Android Gradle-Plug-in dieser Dimension automatisch alle Flavors des Moduls zu.
Im folgenden Codebeispiel wird eine Variante mit dem Namen „version“ erstellt und die Produktvarianten „demo“ und „full“ hinzugefügt. Diese Varianten haben eigene
applicationIdSuffix
und 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" } } }
Groovy
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" } } }
Hinweis:Wenn Sie eine ältere App (vor August 2021 erstellt) haben, die Sie über APKs bei Google Play vertreiben, und Ihre App mit der Unterstützung für mehrere APKs bei Google Play vertreiben möchten, weisen Sie allen Varianten denselben applicationId
-Wert und jeder Variante einen anderen versionCode
zu. Wenn Sie unterschiedliche Varianten Ihrer App als separate Apps bei Google Play anbieten möchten, müssen Sie jeder Variante eine andere applicationId
zuweisen.
Nachdem Sie die Produktvarianten erstellt und konfiguriert haben, klicken Sie in der Benachrichtigungsleiste auf Jetzt synchronisieren. Nach Abschluss der Synchronisierung erstellt Gradle automatisch Buildvarianten basierend auf Ihren Buildtypen und Produktvarianten und benennt sie gemäß <product-flavor><Build-Type>
. Wenn Sie beispielsweise die Produktvarianten „demo“ und „full“ erstellt und die Standard-Buildtypen „debug“ und „release“ beibehalten haben, erstellt Gradle die folgenden Buildvarianten:
-
demoDebug
-
demoRelease
-
fullDebug
-
fullRelease
Wenn Sie auswählen möchten, welche Buildvariante erstellt und ausgeführt werden soll, klicken Sie auf Build > Buildvariante auswählen und wählen Sie im Menü eine Buildvariante aus. Wenn Sie jede Buildvariante mit eigenen Funktionen und Ressourcen anpassen möchten, müssen Sie Quell-Sets erstellen und verwalten, wie auf dieser Seite beschrieben.
Anwendungs-ID für Buildvarianten ändern
Wenn Sie ein APK oder AAB für Ihre App erstellen, taggen die Build-Tools die App mit der Anwendungs-ID, die im Block defaultConfig
der Datei build.gradle.kts
definiert ist, wie im folgenden Beispiel gezeigt. Wenn Sie jedoch verschiedene Versionen Ihrer App erstellen möchten, die als separate Einträge im Google Play Store erscheinen, z. B. eine kostenlose und eine Pro-Version, müssen Sie separate Buildvarianten mit jeweils einer anderen Anwendungs-ID erstellen.
Definieren Sie in diesem Fall jede Buildvariante als separate Produktvariante. Sie können die Property applicationId
für jede Variante innerhalb des productFlavors
-Blocks neu definieren oder stattdessen mit applicationIdSuffix
ein Segment an die Standard-App-ID anhängen, wie hier gezeigt:
Kotlin
android { defaultConfig { applicationId = "com.example.myapp" } productFlavors { create("free") { applicationIdSuffix = ".free" } create("pro") { applicationIdSuffix = ".pro" } } }
Groovy
android { defaultConfig { applicationId "com.example.myapp" } productFlavors { free { applicationIdSuffix ".free" } pro { applicationIdSuffix ".pro" } } }
So lautet die Anwendungs-ID für die kostenlose Produktvariante „com.beispiel.meineapp.kostenlos“.
Mit applicationIdSuffix
können Sie auch ein Segment anhängen, das auf Ihrem Build-Typ basiert. Hier ein Beispiel:
Kotlin
android { ... buildTypes { getByName("debug") { applicationIdSuffix = ".debug" } } }
Groovy
android { ... buildTypes { debug { applicationIdSuffix ".debug" } } }
Da Gradle die Buildtypkonfiguration nach der Produktvariante anwendet, lautet die Anwendungs-ID für die Buildvariante „free debug“ „com.example.myapp.free.debug“. Das ist nützlich, wenn Sie sowohl den Debug-Build als auch den Release-Build auf demselben Gerät haben möchten, da keine zwei Apps dieselbe Anwendungs-ID haben können.
Wenn Sie eine ältere App (vor August 2021 erstellt) haben, die Sie über APKs bei Google Play vertreiben, und mit demselben App-Eintrag mehrere APKs bereitstellen möchten, die jeweils auf eine andere Gerätekonfiguration ausgerichtet sind, z. B. auf die API-Ebene, müssen Sie für jede Buildvariante dieselbe Anwendungs-ID verwenden, aber jedem APK eine andereversionCode
zuweisen. Weitere Informationen finden Sie unter Unterstützung für mehrere APKs. Die Veröffentlichung mit AABs ist davon nicht betroffen, da dafür ein einzelnes Artefakt verwendet wird, das standardmäßig einen einzelnen Versionscode und eine einzelne Anwendungs-ID verwendet.
Tipp:Wenn Sie in Ihrer Manifestdatei auf die Anwendungs-ID verweisen möchten, können Sie den Platzhalter ${applicationId}
in einem beliebigen Manifestattribut verwenden. Während eines Builds ersetzt Gradle dieses Tag durch die tatsächliche Anwendungs-ID. Weitere Informationen finden Sie unter Buildvariablen in das Manifest einfügen.
Mehrere Produktvarianten mit Variantendimensionen kombinieren
In einigen Fällen möchten Sie möglicherweise Konfigurationen aus mehreren Produktvarianten kombinieren. Beispielsweise können Sie unterschiedliche Konfigurationen für die Produktvarianten „Vollständig“ und „Demo“ erstellen, die auf API-Ebene basieren. Dazu können Sie mit dem Android Gradle-Plug-in mehrere Gruppen von Produktvarianten als Variantendimensionen erstellen.
Beim Erstellen Ihrer App kombiniert Gradle eine Produktvariantenkonfiguration aus jeder von Ihnen definierten Variantendimension mit einer Buildtypkonfiguration, um die endgültige Buildvariante zu erstellen. Gradle kombiniert keine Produktvarianten, die derselben Variantendimension angehören.
Im folgenden Codebeispiel wird die Property
flavorDimensions
verwendet, um eine Variante „Modus“ zu erstellen, um die Produktvarianten „Vollständig“ und „Demo“ zu gruppieren, und eine Variante „api“, um Konfigurationen von Produktvarianten basierend auf der API-Ebene zu gruppieren:
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" ... } } } ...
Groovy
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" ... } } } ...
Die Anzahl der von Gradle erstellten Buildvarianten entspricht dem Produkt aus der Anzahl der Flavors in jeder Flavor-Dimension und der Anzahl der konfigurierten Buildtypen. Wenn Gradle die einzelnen Buildvarianten oder entsprechenden Artefakte benennt, werden zuerst Produktvarianten mit einer höheren Prioritätsdimension angezeigt, gefolgt von denen mit niedrigeren Prioritätsdimensionen und dann vom Buildtyp.
Anhand der vorherigen Build-Konfiguration erstellt Gradle insgesamt zwölf Buildvarianten mit dem folgenden Benennungsschema:
- Build-Variante:
[minApi24, minApi23, minApi21][Demo, Full][Debug, Release]
- Entsprechendes APK:
app-[minApi24, minApi23, minApi21]-[demo, full]-[debug, release].apk
- Beispiel:
- Buildvariante:
minApi24DemoDebug
- Entsprechendes APK:
app-minApi24-demo-debug.apk
Neben den Verzeichnissen für Quellsets, die Sie für jede einzelne Produktvariante und Buildvariante erstellen können, können Sie auch Verzeichnisse für Quellsets für jede Kombination von Produktvarianten erstellen. Sie können beispielsweise Java-Quellen im Verzeichnis src/demoMinApi24/java/
erstellen und hinzufügen. Gradle verwendet diese Quellen nur beim Erstellen einer Variante, die diese beiden Produktvarianten kombiniert.
Quellgruppen, die Sie für Kombinationen von Produktvarianten erstellen, haben eine höhere Priorität als Quellgruppen, die zu den einzelnen Produktvarianten gehören. Weitere Informationen zu Quellsätzen und zum Zusammenführen von Ressourcen mit Gradle finden Sie im Abschnitt zum Erstellen von Quellsätzen.
Varianten filtern
Gradle erstellt eine Build-Variante für jede mögliche Kombination der von Ihnen konfigurierten Produktvarianten und Build-Typen. Es kann jedoch bestimmte Buildvarianten geben, die Sie nicht benötigen oder die im Kontext Ihres Projekts keinen Sinn ergeben. Wenn Sie bestimmte Konfigurationen von Buildvarianten entfernen möchten, erstellen Sie einen Variantenfilter in der build.gradle.kts
-Datei auf Modulebene.
Angenommen, Sie möchten für die Demoversion der App nur API-Ebenen 23 und höher unterstützen. Mit dem Block
variantFilter
können Sie alle Konfigurationen für Buildvarianten herausfiltern, die die Produktvarianten „minApi21“ und „demo“ kombinieren:
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 } } } ...
Groovy
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) } } } ...
Nachdem Sie Ihrer Build-Konfiguration einen Variantenfilter hinzugefügt und in der Benachrichtigungsleiste auf Jetzt synchronisieren geklickt haben, ignoriert Gradle alle Build-Varianten, die die von Ihnen angegebenen Bedingungen erfüllen. Die Buildvarianten werden nicht mehr im Menü angezeigt, wenn Sie in der Menüleiste auf Build > Buildvariante auswählen oder in der Toolfensterleiste auf Buildvarianten klicken.
Quellsätze erstellen
Standardmäßig erstellt Android Studio das main/
Source Set und die Verzeichnisse für alle Elemente, die Sie für alle Buildvarianten freigeben möchten. Sie können jedoch neue Quellsätze erstellen, um genau zu steuern, welche Dateien Gradle für bestimmte Buildtypen, Produktvarianten, Kombinationen von Produktvarianten (bei Verwendung von Variantendimensionen) und Buildvarianten kompiliert und verpackt.
Sie können beispielsweise grundlegende Funktionen im main/
-Quellsatz definieren und Quellsätze für Produktvarianten verwenden, um das Branding Ihrer App für verschiedene Kunden zu ändern. Sie können auch spezielle Berechtigungen und Protokollierungsfunktionen nur für Buildvarianten einschließen, die den Debug-Buildtyp verwenden.
Gradle erwartet, dass Quelldateien und ‑verzeichnisse ähnlich wie das main/
-Quellset organisiert sind. Beispielsweise erwartet Gradle, dass sich Kotlin- oder Java-Klassendateien, die für den Buildtyp „debug“ spezifisch sind, in den Verzeichnissen src/debug/kotlin/
oder src/debug/java/
befinden.
Das Android Gradle-Plug-in bietet eine nützliche Gradle-Aufgabe, die Ihnen zeigt, wie Sie Ihre Dateien für jeden Ihrer Build-Typen, Produktvarianten und Build-Varianten organisieren. Im folgenden Beispiel aus der Aufgabenausgabe wird beispielsweise beschrieben, wo Gradle bestimmte Dateien für den Build-Typ „debug“ erwartet:
------------------------------------------------------------ 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]
So rufen Sie diese Ausgabe auf:
- Klicken Sie in der Symbolleiste des Tool-Fensters auf Gradle.
Gehen Sie zu Meine Anwendung > Aufgaben > android und doppelklicken Sie auf sourceSets.
Damit der Ordner Tasks angezeigt wird, muss Gradle die Aufgabenliste während der Synchronisierung erstellen. Führen Sie dazu die folgenden Schritte aus:
- Klicken Sie auf Datei > Einstellungen > Experimentell (Android Studio > Einstellungen > Experimentell unter macOS).
- Heben Sie die Auswahl der Option Gradle-Aufgabenliste während der Gradle-Synchronisierung nicht erstellen auf.
- Nachdem Gradle die Aufgabe ausgeführt hat, wird das Fenster Ausführen geöffnet, in dem die Ausgabe angezeigt wird.
Hinweis:In der Aufgabenausgabe wird auch gezeigt, wie Sie Quellsätze für Dateien organisieren, mit denen Sie Tests für Ihre App ausführen möchten, z. B. die Testquellensätzetest/
und androidTest/
.
Wenn Sie eine neue Build-Variante erstellen, erstellt Android Studio die Verzeichnisse für das Quellset nicht für Sie. Es bietet Ihnen jedoch einige Optionen, die Ihnen dabei helfen können. Wenn Sie beispielsweise nur das Verzeichnis java/
für den Buildtyp „debug“ erstellen möchten, geben Sie Folgendes ein:
- Öffnen Sie den Bereich Projekt und wählen Sie oben im Bereich im Menü die Ansicht Projekt aus.
- Zu
MyProject/app/src/
navigieren - Klicken Sie mit der rechten Maustaste auf das Verzeichnis
src
und wählen Sie Neu > Verzeichnis aus. - Wählen Sie im Menü unter Gradle-Quellsätze die Option full/java aus.
- Drücken Sie die Eingabetaste.
Android Studio erstellt ein Source-Set-Verzeichnis für Ihren Debug-Buildtyp und dann das Verzeichnis java/
darin. Alternativ können Sie die Verzeichnisse auch in Android Studio erstellen, wenn Sie Ihrem Projekt eine neue Datei für eine bestimmte Build-Variante hinzufügen.
So erstellen Sie beispielsweise eine Werte-XML-Datei für den Buildtyp „debug“:
- Klicken Sie im Bereich Projekt mit der rechten Maustaste auf das Verzeichnis
src
und wählen Sie Neu > XML > Values XML-Datei aus. - Geben Sie den Namen für die XML-Datei ein oder belassen Sie den Standardnamen.
- Wählen Sie im Menü neben Zielquellen-Set die Option debug aus.
- Klicken Sie auf Fertig.
Da der Buildtyp „debug“ als Zielquellensatz angegeben wurde, erstellt Android Studio beim Erstellen der XML-Datei automatisch die erforderlichen Verzeichnisse. Die resultierende Verzeichnisstruktur sieht dann so aus wie in Abbildung 1.
Aktive Quellengruppen sind durch ein grünes Symbol gekennzeichnet. Das Quellset debug
hat das Suffix [main]
, um anzugeben, dass es mit dem Quellset main
zusammengeführt wird.
Mit demselben Verfahren können Sie auch Verzeichnisse für Quellsätze für Produktvarianten wie src/demo/
erstellen und Varianten wie src/demoDebug/
erstellen. Außerdem können Sie Testquellensätze erstellen, die auf bestimmte Buildvarianten ausgerichtet sind, z. B. src/androidTestDemoDebug/
. Weitere Informationen finden Sie unter Quellsätze testen.
Standardkonfigurationen für Quellgruppen ändern
Wenn Ihre Quellen nicht in der von Gradle erwarteten Standarddateistruktur des Quellsatzes organisiert sind, wie im vorherigen Abschnitt zum Erstellen von Quellsätzen beschrieben, können Sie mit dem Block
sourceSets
ändern, wo Gradle nach Dateien für die einzelnen Komponenten eines Quellsatzes sucht.
Der Block sourceSets
muss sich im Block android
befinden. Sie müssen die Quelldateien nicht verschieben. Sie müssen Gradle nur den Pfad oder die Pfade relativ zur build.gradle.kts
-Datei auf Modulebene angeben, unter denen Gradle Dateien für jede Komponente des Quellsatzes finden kann. Informationen dazu, welche Komponenten Sie konfigurieren können und ob Sie sie mehreren Dateien oder Verzeichnissen zuordnen können, finden Sie in der API-Referenz für das Android Gradle-Plug-in.
Im folgenden Codebeispiel werden Quellen aus dem Verzeichnis app/other/
bestimmten Komponenten des Quellsatzes main
zugeordnet und das Stammverzeichnis des Quellsatzes androidTest
geändert:
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") ... } } ...
Groovy
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' ... } } } ...
Ein Quellverzeichnis kann nur zu einem Quellsatz gehören. Sie können beispielsweise nicht dieselben Testquellen für die Quellsätze test
und androidTest
freigeben. Das liegt daran, dass Android Studio für jedes Quellset separate IntelliJ-Module erstellt und keine doppelten Inhaltsknoten in Quellsets unterstützt.
Mit Quellsätzen erstellen
Sie können Verzeichnisse für Quellsätze verwenden, um den Code und die Ressourcen zu enthalten, die nur mit bestimmten Konfigurationen gepackt werden sollen. Wenn Sie beispielsweise die Buildvariante „demoDebug“ erstellen, die das Kreuzprodukt aus einem „demo“-Produkt-Flavor und dem Buildtyp „debug“ ist, prüft Gradle diese Verzeichnisse und ordnet ihnen die folgende Priorität zu:
-
src/demoDebug/
(Build-Variante – Quellsatz) -
src/debug/
(Build-Typ-Quellsatz) -
src/demo/
(Quellsatz für Produktvariante) -
src/main/
(Hauptquellensatz)
In Quellgruppen, die für Kombinationen von Produktvarianten erstellt wurden, müssen alle Variantendimensionen enthalten sein. Das Quellset für die Buildvariante muss beispielsweise eine Kombination aus dem Buildtyp und allen Flavor-Dimensionen sein. Das Zusammenführen von Code und Ressourcen mit Ordnern, die mehrere, aber nicht alle Variantendimensionen abdecken, wird nicht unterstützt.
Wenn Sie mehrere Geschmacksrichtungen kombinieren, wird die Priorität der Geschmacksrichtungen durch die Geschmacksdimension bestimmt, zu der sie gehören. Wenn Sie Geschmacksdimensionen mit der Property
android.flavorDimensions
angeben, haben Produktvarianten, die zur ersten Geschmacksdimension gehören, eine höhere Priorität als diejenigen, die zur zweiten Geschmacksdimension gehören, und so weiter. Außerdem haben Quellgruppen, die Sie für Kombinationen von Produktvarianten erstellen, eine höhere Priorität als Quellgruppen, die zu einer einzelnen Produktvariante gehören.
Die Prioritätsreihenfolge bestimmt, welche Quellgruppe beim Kombinieren von Code und Ressourcen eine höhere Priorität hat. Da das Verzeichnis „demoDebug/
“ wahrscheinlich Dateien enthält, die für diese Buildvariante spezifisch sind, verwendet Gradle die Datei im Quellsatz „demoDebug/
“, wenn „demoDebug/
“ eine Datei enthält, die auch in „debug/
“ definiert ist. Ebenso ordnet Gradle Dateien in den Build-Typen und Produktvarianten-Quelldateien eine höhere Priorität zu als denselben Dateien in main/
.
Gradle berücksichtigt diese Prioritätsreihenfolge, wenn die folgenden Build-Regeln angewendet werden:
- Der gesamte Quellcode in den Verzeichnissen
kotlin/
oderjava/
wird zusammen kompiliert, um eine einzelne Ausgabe zu generieren.Hinweis:Für eine bestimmte Buildvariante löst Gradle einen Buildfehler aus, wenn zwei oder mehr Verzeichnisse mit Quellsätzen gefunden werden, in denen dieselbe Kotlin- oder Java-Klasse definiert ist. Wenn Sie beispielsweise eine Debug-App erstellen, können Sie weder
src/debug/Utility.kt
nochsrc/main/Utility.kt
definieren, da Gradle während des Build-Prozesses beide Verzeichnisse überprüft und einen Fehler vom Typ „Duplizierte Klasse“ auslöst. Wenn Sie unterschiedliche Versionen vonUtility.kt
für verschiedene Buildtypen benötigen, muss für jeden Buildtyp eine eigene Version der Datei definiert werden. Sie darf nicht in dermain/
-Quellgruppe enthalten sein. - Manifeste werden zu einem einzigen Manifest zusammengeführt. Die Priorität wird in der Reihenfolge der Liste im vorherigen Beispiel vergeben. Das heißt, Manifesteinstellungen für einen Buildtyp überschreiben die Manifesteinstellungen für einen Produktvariantentyp usw. Weitere Informationen finden Sie unter Manifeste zusammenführen.
- Dateien in den
values/
-Verzeichnissen werden zusammengeführt. Wenn zwei Dateien denselben Namen haben, z. B. zweistrings.xml
-Dateien, wird die Priorität in der Reihenfolge wie in der Liste im vorherigen Beispiel vergeben. Das heißt, Werte, die in einer Datei im Quellsatz des Buildtyps definiert sind, überschreiben die Werte, die in derselben Datei in einer Produktvariante definiert sind. - Ressourcen in den Verzeichnissen
res/
undasset/
werden zusammen verpackt. Wenn in zwei oder mehr Quellsätzen Ressourcen mit demselben Namen definiert sind, wird die Priorität in der Reihenfolge der Liste im vorherigen Beispiel vergeben. - Gradle ordnet Ressourcen und Manifeste, die in Bibliotheksmodulabhängigkeiten enthalten sind, beim Erstellen der App die niedrigste Priorität zu.
Abhängigkeiten deklarieren
Wenn Sie eine Abhängigkeit für eine bestimmte Buildvariante oder ein bestimmtes Test-Quellset konfigurieren möchten, fügen Sie den Namen der Buildvariante oder des Test-Quellsets vor das Keyword Implementation
ein, wie im folgenden Beispiel gezeigt:
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") }
Groovy
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' }
Weitere Informationen zum Konfigurieren von Abhängigkeiten finden Sie unter Build-Abhängigkeiten hinzufügen.
Variantenspezifische Abhängigkeitsverwaltung verwenden
Das Android Gradle-Plug-in 3.0.0 und höher enthält einen neuen Abhängigkeitsmechanismus, der beim Verwenden einer Bibliothek automatisch Varianten abgleicht. Das bedeutet, dass die debug
-Variante einer App automatisch die debug
-Variante einer Bibliothek nutzt usw. Das funktioniert auch bei der Verwendung von Varianten: Die freeDebug
-Variante einer App verwendet die freeDebug
-Variante einer Bibliothek.
Damit das Plug-in Varianten korrekt abgleichen kann, müssen Sie wie im folgenden Abschnitt beschrieben entsprechende Fallbacks angeben, falls keine direkte Übereinstimmung möglich ist.
Angenommen, Sie konfigurieren in Ihrer App einen Build-Typ namens „Staging“, aber eine ihrer Bibliotheksabhängigkeiten nicht. Wenn das Plug-in versucht, die Staging-Version Ihrer App zu erstellen, weiß es nicht, welche Version der Bibliothek verwendet werden soll. Sie erhalten dann eine Fehlermeldung ähnlich der folgenden:
Error:Failed to resolve: Could not resolve project :mylibrary. Required by: project :app
Build-Fehler im Zusammenhang mit der Variantenabgleichung beheben
Das Plug-in enthält DSL-Elemente, mit denen Sie steuern können, wie Gradle Situationen löst, in denen eine direkte Übereinstimmung zwischen einer App und einer Abhängigkeit nicht möglich ist.
Im Folgenden finden Sie eine Liste von Problemen im Zusammenhang mit der variantenspezifischen Abhängigkeitsabgleichung und wie Sie diese mithilfe von DSL-Properties beheben können:Ihre App enthält einen Build-Typ, den eine Bibliothekabhängigkeit nicht hat.
Ihre App enthält beispielsweise den Buildtyp „Staging“, eine Abhängigkeit jedoch nur die Buildtypen „Debug“ und „Release“.
Es liegt kein Problem vor, wenn eine Bibliothek abhängig von einem Buildtyp ist, den Ihre App nicht hat. Das liegt daran, dass das Plug-in diesen Buildtyp nie von der Abhängigkeit anfordert.
Verwenden Sie
matchingFallbacks
, um alternative Übereinstimmungen für einen bestimmten Buildtyp anzugeben, wie hier gezeigt: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") } } }
Groovy
// 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'] } } }
Für eine bestimmte Variante, die sowohl in der App als auch in der Bibliotheksabhängigkeit vorhanden ist, enthält Ihre App Varianten, die in der Bibliothek nicht vorhanden sind.
Beispiel: Sowohl Ihre App als auch ihre Bibliotheksabhängigkeiten enthalten die Variante „Tier“. Die Dimension „Stufen“ in der App enthält jedoch die Varianten „kostenlos“ und „kostenpflichtig“, während eine Abhängigkeit für dieselbe Dimension nur die Varianten „Demo“ und „kostenpflichtig“ enthält.
Hinweis: Bei einer bestimmten Variante, die sowohl in der App als auch in den Bibliotheksabhängigkeiten vorhanden ist, liegt kein Problem vor, wenn eine Bibliothek eine Produktvariante enthält, die in Ihrer App nicht vorhanden ist. Das liegt daran, dass das Plug-in diese Variante nie von der Abhängigkeit anfordert.
Verwenden Sie
matchingFallbacks
, um alternative Übereinstimmungen für die „kostenlose“ Produktvariante der App anzugeben, wie hier gezeigt: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") } } }
Groovy
// 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'] } } }
Eine Bibliotheksabhängigkeit enthält eine Variante, die Ihre App nicht hat.
Eine Bibliotheksabhängigkeit enthält beispielsweise Varianten für die Dimension „minApi“, Ihre App jedoch nur Varianten für die Dimension „Tier“. Wenn Sie die Version „freeDebug“ Ihrer App erstellen möchten, weiß das Plug-in nicht, ob die Version „minApi23Debug“ oder „minApi18Debug“ der Abhängigkeit verwendet werden soll.
Es gibt kein Problem, wenn Ihre App eine Variante enthält, die eine Bibliothekabhängigkeit nicht hat. Das liegt daran, dass das Plug-in nur die Varianten der Dimensionen abgleicht, die in der Abhängigkeit vorhanden sind. Wenn eine Abhängigkeit beispielsweise keine Dimension für ABIs enthält, wird in der Version „freeX86Debug“ Ihrer App die Version „freeDebug“ der Abhängigkeit verwendet.
Verwenden Sie
missingDimensionStrategy
im BlockdefaultConfig
, um den Standard-Flavor für das Plug-in anzugeben, der aus jeder fehlenden Dimension ausgewählt werden soll, wie im folgenden Beispiel gezeigt. Sie können Ihre Auswahl auch im BlockproductFlavors
überschreiben, sodass für jede Variante eine andere Abgleichsstrategie für eine fehlende Dimension angegeben werden kann.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") {} } }
Groovy
// 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 {} } }
Weitere Informationen finden Sie in der DSL-Referenz für Android-Gradle-Plug-ins unter matchingFallbacks
und missingDimensionStrategy
.
Signatureinstellungen konfigurieren
Gradle signiert das APK oder AAB Ihres Release-Builds nur, wenn Sie explizit eine Signaturkonfiguration für diesen Build definieren. Wenn Sie noch keinen Signaturschlüssel haben, generieren Sie einen Uploadschlüssel und einen Keystore mit Android Studio.
So konfigurieren Sie die Signaturkonfigurationen für Ihren Release-Buildtyp manuell mit Gradle-Buildkonfigurationen:
- Erstellen Sie einen Schlüsselspeicher. Ein Schlüsselspeicher ist eine Binärdatei, die eine Reihe privater Schlüssel enthält. Sie müssen den Schlüsselspeicher an einem sicheren Ort aufbewahren.
- Erstellen Sie einen privaten Schlüssel. Mit einem privaten Schlüssel wird Ihre App für den Vertrieb signiert. Er ist niemals in der App enthalten und wird nicht an unbefugte Dritte weitergegeben.
-
Fügen Sie der Datei
build.gradle.kts
auf Modulebene die Signaturkonfiguration hinzu:Kotlin
... android { ... defaultConfig {...} signingConfigs { create("release") { storeFile = file("myreleasekey.keystore") storePassword = "password" keyAlias = "MyReleaseKey" keyPassword = "password" } } buildTypes { getByName("release") { ... signingConfig = signingConfigs.getByName("release") } } }
Groovy
... android { ... defaultConfig {...} signingConfigs { release { storeFile file("myreleasekey.keystore") storePassword "password" keyAlias "MyReleaseKey" keyPassword "password" } } buildTypes { release { ... signingConfig signingConfigs.release } } }
Hinweis:Es ist nicht empfehlenswert, die Passwörter für den Release-Schlüssel und den Schlüsselspeicher in die Build-Datei aufzunehmen. Konfigurieren Sie stattdessen die Build-Datei so, dass diese Passwörter aus Umgebungsvariablen abgerufen werden, oder lassen Sie sich während des Build-Prozesses nach diesen Passwörtern fragen.
So rufen Sie diese Passwörter aus Umgebungsvariablen ab:
Kotlin
storePassword = System.getenv("KSTOREPWD") keyPassword = System.getenv("KEYPWD")
Groovy
storePassword System.getenv("KSTOREPWD") keyPassword System.getenv("KEYPWD")
Alternativ können Sie den Schlüsselspeicher aus einer lokalen Eigenschaftendatei laden. Fügen Sie diese Datei aus Sicherheitsgründen nicht der Versionskontrolle hinzu. Richten Sie es stattdessen lokal für jeden Entwickler ein. Weitere Informationen finden Sie im Hilfeartikel Unterzeichnungsinformationen aus Ihren Build-Dateien entfernen.
Danach können Sie Ihre App vertreiben und bei Google Play veröffentlichen.
Warnung:Bewahren Sie den Schlüsselspeicher und den privaten Schlüssel an einem sicheren Ort auf und sorgen Sie für sichere Back-ups. Wenn Sie die Play App-Signatur verwenden und Ihren Uploadschlüssel verlieren, können Sie über die Play Console einen Zurücksetzungsvorgang anfordern. Wenn Sie eine App ohne Play App-Signatur veröffentlichen (für Apps, die vor August 2021 erstellt wurden) und den App-Signaturschlüssel verlieren, können Sie keine Updates für Ihre App veröffentlichen, da Sie immer alle Versionen Ihrer App mit demselben Schlüssel signieren müssen.
Wear OS-Apps signieren
Beim Veröffentlichen von Wear OS-Apps müssen sowohl das Smartwatch-APK als auch das optionale Smartphone-APK mit demselben Schlüssel signiert sein. Weitere Informationen zum Paketieren und Signieren von Wear OS-Apps finden Sie unter Wear OS-Apps im Paket anbieten und vertreiben.