Auf dieser Seite erfahren Sie, wie Sie Build-Varianten konfigurieren, um verschiedene Versionen Ihrer App aus einem einzelnen Projekt zu erstellen, und wie Sie Ihre Abhängigkeiten und Signaturkonfigurationen richtig verwalten.
Jede Build-Variante stellt eine andere Version Ihrer App dar, die Sie erstellen können. Sie können beispielsweise eine kostenlose Version Ihrer App mit einer begrenzten Anzahl von Inhalten und eine kostenpflichtige Version mit mehr Inhalten erstellen. Sie können auch verschiedene Versionen Ihrer App erstellen, die auf unterschiedliche Geräte ausgerichtet sind, basierend auf dem API-Level oder anderen Gerätevarianten.
Build-Varianten sind das Ergebnis davon, dass Gradle eine bestimmte Reihe von Regeln verwendet, um Einstellungen, Code und Ressourcen zu kombinieren, die in Ihren Build-Typen und Produktvarianten konfiguriert sind. Build-Varianten werden nicht direkt konfiguriert, aber die Build-Typen und Produktvarianten, aus denen sie bestehen.
Für eine Produktvariante vom Typ „Demo“ können beispielsweise bestimmte Funktionen und Geräteanforderungen wie benutzerdefinierter Quellcode, Ressourcen und Mindest-API-Levels angegeben werden, während für den Build-Typ „Debug“ andere Build- und Verpackungseinstellungen wie Debug-Optionen und Signaturschlüssel gelten. Die Build-Variante, 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“, im Build-Typ „debug“ und im Quellsatz main/
enthalten sind.
Build-Typen konfigurieren
Sie können Build-Typen im android
-Block der build.gradle.kts
-Datei auf Modulebene erstellen und konfigurieren. Wenn Sie ein neues Modul erstellen, werden in Android Studio automatisch die Build-Typen „Debug“ und „Release“ erstellt. Obwohl der Debug-Build-Typ nicht in der Build-Konfigurationsdatei angezeigt wird, konfiguriert Android Studio ihn mit debuggable
true
. So können Sie die App auf sicheren Android-Geräten debuggen und die App-Signierung mit einem generischen Debug-Keystore konfigurieren.
Sie können den Debug-Build-Typ zu Ihrer Konfiguration hinzufügen, wenn Sie bestimmte Einstellungen hinzufügen oder ändern möchten. Im folgenden Beispiel wird ein
applicationIdSuffix
für den Debug-Build-Typ angegeben und ein „Staging“-Build-Typ konfiguriert, der mit den Einstellungen des Debug-Build-Typs 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 angezeigt wird, wenn Sie eine Änderung vornehmen, auf Jetzt synchronisieren oder klicken Sie in der Symbolleiste auf Projekt synchronisieren . Wenn Android Studio Fehler in Ihrer Konfiguration erkennt, wird das Fenster Messages (Meldungen) angezeigt, in dem das Problem beschrieben wird.
Weitere Informationen zu allen Attributen, die Sie mit Build-Typen konfigurieren können, finden Sie in der
BuildType
-Referenz.
Produktvarianten konfigurieren
Das Erstellen von Produktvarianten ähnelt dem Erstellen von Build-Typen. 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 Eigenschaften wie defaultConfig
, da defaultConfig
zur Klasse
ProductFlavor
gehört. Das bedeutet, dass Sie die Basiskonfiguration für alle Produktvarianten im Block defaultConfig
angeben können. Jede Produktvariante kann dann beliebige dieser Standardwerte ändern, z. B. applicationId
. Weitere Informationen zur Anwendungs-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äts- oder Dienstregistrierungen aufzulösen. So können Sie applicationId
verwenden, um jeder Produktvariante eine eindeutige ID für die Verpackung und Verteilung zuzuweisen, ohne den Quellcode ändern zu müssen.
Alle Geschmacksrichtungen müssen zu einer benannten Geschmacksdimension gehören, die eine Gruppe von Produktgeschmacksrichtungen ist. Sie müssen allen Varianten eine Variantendimension zuweisen. Andernfalls erhalten Sie den folgenden Build-Fehler.
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-Plugin automatisch alle Flavors des Moduls dieser Dimension zu.
Im folgenden Codebeispiel wird eine Flavor-Dimension namens „version“ erstellt und die Produkt-Flavors „demo“ und „full“ werden hinzugefügt. Diese Varianten bieten 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 Legacy-App (erstellt vor August 2021) haben, die Sie über APKs bei Google Play vertreiben, müssen Sie allen Varianten denselben applicationId
-Wert zuweisen und jeder Variante eine andere versionCode
geben, um Ihre App über die Unterstützung für mehrere APKs bei Google Play zu vertreiben. Wenn Sie verschiedene Varianten Ihrer App als separate Apps bei Google Play vertreiben möchten, müssen Sie jeder Variante eine andere applicationId
zuweisen.
Nachdem Sie Ihre Produktvarianten erstellt und konfiguriert haben, klicken Sie in der Benachrichtigungsleiste auf Jetzt synchronisieren. Nach Abschluss der Synchronisierung erstellt Gradle automatisch Build-Varianten basierend auf Ihren Build-Typen und Produktvarianten und benennt sie gemäß <product-flavor><Build-Type>
. Wenn Sie beispielsweise die Produktvarianten „demo“ und „full“ erstellt und die Standard-Build-Typen „debug“ und „release“ beibehalten haben, erstellt Gradle die folgenden Build-Varianten:
-
demoDebug
-
demoRelease
-
fullDebug
-
fullRelease
Wenn Sie auswählen möchten, welche Build-Variante erstellt und ausgeführt werden soll, gehen Sie zu Build > Select Build Variant (Build > Build-Variante auswählen) und wählen Sie eine Build-Variante aus dem Menü aus. Wenn Sie jede Build-Variante mit eigenen Funktionen und Ressourcen anpassen möchten, müssen Sie Quellsätze erstellen und verwalten, wie auf dieser Seite beschrieben.
Anwendungs-ID für Build-Varianten ändern
Wenn Sie ein APK oder AAB für Ihre App erstellen, taggen die Build-Tools die App mit der Anwendungs-ID, die im defaultConfig
-Block 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 angezeigt werden, z. B. eine „kostenlose“ und eine „Pro“-Version, müssen Sie separate Build-Varianten erstellen, die jeweils eine andere Anwendungs-ID haben.
In diesem Fall definieren Sie jede Build-Variante als separate Produktvariante. Für jede Variante im productFlavors
-Block können Sie das Attribut applicationId
neu definieren oder stattdessen ein Segment an die Standard-Anwendungs-ID anhängen. Verwenden Sie dazu applicationIdSuffix
, 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" } } }
Die Anwendungs-ID für die Produktvariante „free“ lautet dann „com.example.myapp.free“.
Sie können auch applicationIdSuffix
verwenden, um ein Segment basierend auf Ihrem Build-Typ anzuhängen, wie hier gezeigt:
Kotlin
android { ... buildTypes { getByName("debug") { applicationIdSuffix = ".debug" } } }
Groovy
android { ... buildTypes { debug { applicationIdSuffix ".debug" } } }
Da Gradle die Build-Typ-Konfiguration nach dem Produkt-Flavor anwendet, lautet die Anwendungs-ID für die Build-Variante „free debug“ „com.example.myapp.free.debug“. Das ist nützlich, wenn Sie sowohl den Debug- 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 Legacy-App (erstellt vor August 2021) haben, die Sie über APKs bei Google Play vertreiben, und Sie dasselbe App-Angebot verwenden möchten, um mehrere APKs zu vertreiben, die jeweils auf eine andere Gerätekonfiguration wie die API-Ebene ausgerichtet sind, müssen Sie für jede Build-Variante dieselbe Anwendungs-ID verwenden, aber jedem APK eine andereversionCode
geben. Weitere Informationen finden Sie unter Unterstützung für mehrere APKs. Die Veröffentlichung mit AABs ist davon nicht betroffen, da standardmäßig ein einzelnes Artefakt mit einem einzelnen Versionscode und einer einzelnen Anwendungs-ID verwendet wird.
Tipp:Wenn Sie in Ihrer Manifestdatei auf die Anwendungs-ID verweisen müssen, 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 Build-Variablen 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 für die Produktvarianten „full“ und „demo“ unterschiedliche Konfigurationen erstellen, die auf der API-Ebene basieren. Dazu können Sie mit dem Android-Gradle-Plugin mehrere Gruppen von Produktvarianten als Variantendimensionen erstellen.
Beim Erstellen Ihrer App kombiniert Gradle eine Produktvariantenkonfiguration aus jeder von Ihnen definierten Variantendimension mit einer Build-Typ-Konfiguration, um die endgültige Build-Variante zu erstellen. Gradle kombiniert keine Produktvarianten, die zur selben Variantendimension gehören.
Im folgenden Codebeispiel wird die Eigenschaft
flavorDimensions
verwendet, um eine Dimension vom Typ „mode“ zu erstellen, mit der die Produktvarianten „full“ und „demo“ gruppiert werden, sowie eine Dimension vom Typ „api“, mit der Produktvariantenkonfigurationen basierend auf der API-Ebene gruppiert werden:
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 Build-Varianten, die Gradle erstellt, entspricht dem Produkt aus der Anzahl der Produktvarianten in jeder Produktvariantendimension und der Anzahl der von Ihnen konfigurierten Build-Typen. Wenn Gradle die einzelnen Build-Varianten oder entsprechenden Artefakte benennt, werden die Produktvarianten, die zu einer Flavor-Dimension mit höherer Priorität gehören, zuerst aufgeführt, gefolgt von denen aus Dimensionen mit niedrigerer Priorität und dann vom Build-Typ.
Anhand der vorherigen Build-Konfiguration erstellt Gradle insgesamt 12 Build-Varianten mit dem folgenden Namensschema:
- Build-Variante:
[minApi24, minApi23, minApi21][Demo, Full][Debug, Release]
- Entsprechendes APK:
app-[minApi24, minApi23, minApi21]-[demo, full]-[debug, release].apk
- Beispiel:
- Build-Variante:
minApi24DemoDebug
- Entsprechendes APK:
app-minApi24-demo-debug.apk
Zusätzlich zu den Quellsetverzeichnissen, die Sie für jede einzelne Produktvariante und Build-Variante erstellen können, können Sie auch Quellsetverzeichnisse 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, wenn eine Variante erstellt wird, die diese beiden Produktvarianten kombiniert.
Quellgruppen, die Sie für Produktvariantenkombinationen erstellen, haben eine höhere Priorität als Quellgruppen, die zu den einzelnen Produktvarianten gehören. Weitere Informationen zu Quellsets und dazu, wie Gradle Ressourcen zusammenführt, finden Sie im Abschnitt zum Erstellen von Quellsets.
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 Build-Varianten geben, die Sie nicht benötigen oder die im Kontext Ihres Projekts nicht sinnvoll sind. Wenn Sie bestimmte Build-Variantenkonfigurationen 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-Level 23 und höher unterstützen. Sie können den
variantFilter
-Block verwenden, um alle Build-Variantenkonfigurationen herauszufiltern, 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 Variant-Filter hinzugefügt und in der Benachrichtigungsleiste auf Sync Now (Jetzt synchronisieren) geklickt haben, ignoriert Gradle alle Build-Varianten, die den von Ihnen angegebenen Bedingungen entsprechen. Die Build-Varianten werden nicht mehr im Menü angezeigt, wenn Sie in der Menüleiste auf Build > Select Build Variant (Build > Build-Variante auswählen) oder in der Toolfensterleiste auf Build Variants klicken.
Quellsätze erstellen
Standardmäßig erstellt Android Studio das main/
-Quellset und Verzeichnisse für alle Elemente, die Sie für alle Ihre Build-Varianten freigeben möchten. Sie können jedoch neue Quellsätze erstellen, um genau festzulegen, welche Dateien Gradle für bestimmte Build-Typen, Produktvarianten, Kombinationen von Produktvarianten (bei Verwendung von Flavor-Dimensionen) und Build-Varianten kompiliert und verpackt.
Sie können beispielsweise grundlegende Funktionen im Quellset main/
definieren und Quellsets für Produktvarianten verwenden, um das Branding Ihrer App für verschiedene Clients zu ändern oder spezielle Berechtigungen und Protokollierungsfunktionen nur für Build-Varianten einzuschließen, die den Debug-Build-Typ verwenden.
Gradle erwartet, dass Quellsetdateien und ‑verzeichnisse auf bestimmte Weise organisiert sind, ähnlich wie das Quellset main/
. Gradle erwartet beispielsweise, dass sich Kotlin- oder Java-Klassendateien, die für Ihren Debug-Build-Typ spezifisch sind, in den Verzeichnissen src/debug/kotlin/
oder src/debug/java/
befinden.
Das Android-Gradle-Plug-in bietet eine nützliche Gradle-Aufgabe, mit der Sie sehen können, wie Sie Ihre Dateien für die einzelnen Build-Typen, Produktvarianten und Build-Varianten organisieren. Das folgende Beispiel aus der Aufgabenausgabe beschreibt, 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 Toolfensterleiste auf Gradle.
Gehen Sie zu MyApplication > Tasks > 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 File > Settings > Experimental (Android Studio > Settings > Experimental auf macOS).
- Deaktivieren Sie die Option Do not build Gradle task list during Gradle sync (Gradle-Aufgabenliste während der Gradle-Synchronisierung nicht erstellen).
- Nachdem Gradle die Aufgabe ausgeführt hat, wird das Fenster Ausführen geöffnet, um die Ausgabe anzuzeigen.
Hinweis:In der Ausgabe des Tasks wird auch gezeigt, wie Sie Quellsätze für Dateien organisieren, die Sie zum Ausführen von Tests für Ihre App verwenden möchten, z. B. die test/
- und androidTest/
-Testquellsätze.
Wenn Sie eine neue Build-Variante erstellen, werden die Quellsetverzeichnisse nicht automatisch erstellt. Android Studio bietet Ihnen jedoch einige Optionen, die Ihnen dabei helfen. Wenn Sie beispielsweise nur das Verzeichnis java/
für den Build-Typ „debug“ erstellen möchten:
- Öffnen Sie den Bereich Projekt und wählen Sie im Menü oben im Bereich 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 Source Sets (Gradle-Quellsätze) die Option full/java aus.
- Drücken Sie die Eingabetaste.
In Android Studio wird ein Quellsatzverzeichnis für den Debug-Build-Typ erstellt und dann das Verzeichnis java/
darin. Alternativ kann Android Studio die Verzeichnisse für Sie erstellen, wenn Sie Ihrem Projekt eine neue Datei für eine bestimmte Build-Variante hinzufügen.
Wenn Sie beispielsweise eine XML-Datei mit Werten für den Build-Typ „debug“ erstellen möchten, gehen Sie so vor:
- Klicken Sie im Bereich Project (Projekt) mit der rechten Maustaste auf das Verzeichnis
src
und wählen Sie New (Neu) > XML > Values XML File (XML-Datei für Werte) aus. - Geben Sie einen Namen für die XML-Datei ein oder behalten Sie den Standardnamen bei.
- Wählen Sie im Menü neben Zielquellen-Set die Option debug aus.
- Klicken Sie auf Fertig.
Da der Build-Typ „debug“ als Ziel-Quellgruppe angegeben wurde, erstellt Android Studio die erforderlichen Verzeichnisse automatisch, wenn die XML-Datei erstellt wird. Die resultierende Verzeichnisstruktur ist in Abbildung 1 dargestellt.

Abbildung 1: Neue Quellsetverzeichnisse für den Build-Typ „debug“.
Aktive Quellsets haben einen grünen Indikator in ihrem Symbol, um anzuzeigen, dass sie aktiv sind. Dem debug
-Quellsatz wird [main]
angehängt, um anzugeben, dass er in den main
-Quellsatz zusammengeführt wird.
Mit demselben Verfahren können Sie auch Quellsetverzeichnisse für Produktvarianten wie src/demo/
und Build-Varianten wie src/demoDebug/
erstellen. Außerdem können Sie Test-Quellsets erstellen, die auf bestimmte Build-Varianten wie src/androidTestDemoDebug/
ausgerichtet sind. Weitere Informationen zum Testen von Quellsätzen
Standardkonfigurationen für Quellsets ändern
Wenn Sie Quellen haben, die nicht in der Standardstruktur der Quellsetdatei organisiert sind, die Gradle erwartet, wie im vorherigen Abschnitt zum Erstellen von Quellsets beschrieben, können Sie den Block
sourceSets
verwenden, um zu ändern, wo Gradle nach Dateien für jede Komponente eines Quellsets 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 Quellsetkomponente 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 Quellsets main
zugeordnet und das Stammverzeichnis des Quellsets androidTest
wird 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 Quellsets test
und androidTest
freigeben. Das liegt daran, dass Android Studio separate IntelliJ-Module für jedes Quellset erstellt und keine doppelten Inhaltsstammverzeichnisse in Quellsets unterstützt.
Mit Quellsätzen entwickeln
Mit Quellsetverzeichnissen können Sie den Code und die Ressourcen enthalten, die nur mit bestimmten Konfigurationen verpackt werden sollen. Wenn Sie beispielsweise die Build-Variante „demoDebug“ erstellen, die das Kreuzprodukt eines Produkt-Flavors „demo“ und eines Build-Typs „debug“ ist, berücksichtigt Gradle die folgenden Verzeichnisse und weist ihnen die folgende Priorität zu:
-
src/demoDebug/
(Quellsatz für Build-Variante) -
src/debug/
(Build-Typ-Quellset) -
src/demo/
(Quellset für Produktvarianten) -
src/main/
(Hauptquellgruppe)
Quellsets, die für Kombinationen von Produktvarianten erstellt werden, müssen alle Variantendimensionen enthalten. Der Quellsatz für die Build-Variante muss beispielsweise die Kombination aus dem Build-Typ und allen Flavor-Dimensionen sein. Das Zusammenführen von Code und Ressourcen, die Ordner mit mehreren, aber nicht allen Flavor-Dimensionen umfassen, wird nicht unterstützt.
Wenn Sie mehrere Produktvarianten kombinieren, wird die Priorität zwischen den Produktvarianten durch die Dimension „Geschmacksrichtung“ bestimmt, zu der sie gehören. Wenn Sie Geschmacksrichtungen mit der Property
android.flavorDimensions
auflisten, haben Produktgeschmacksrichtungen, die zur ersten aufgeführten Geschmacksrichtung gehören, eine höhere Priorität als die der zweiten Geschmacksrichtung usw. Außerdem haben Quellsätze, die Sie für Kombinationen von Produktvarianten erstellen, eine höhere Priorität als Quellsätze, die zu einer einzelnen Produktvariante gehören.
Die Prioritätsreihenfolge bestimmt, welche Quellgruppe eine höhere Priorität hat, wenn Gradle Code und Ressourcen kombiniert. Da das Quellsetverzeichnis demoDebug/
wahrscheinlich Dateien enthält, die für diese Build-Variante spezifisch sind, verwendet Gradle die Datei im Quellset demoDebug/
, wenn demoDebug/
eine Datei enthält, die auch in debug/
definiert ist. Entsprechend haben Dateien in den Quellsets für Build-Typ und Produktvariante in Gradle eine höhere Priorität als dieselben Dateien in main/
.
Gradle berücksichtigt diese Prioritätsreihenfolge beim Anwenden der folgenden Build-Regeln:
- Der gesamte Quellcode in den Verzeichnissen
kotlin/
oderjava/
wird zusammen kompiliert, um eine einzelne Ausgabe zu generieren.Hinweis:Für eine bestimmte Build-Variante gibt Gradle einen Build-Fehler aus, wenn zwei oder mehr Quellverzeichnisse dieselbe Kotlin- oder Java-Klasse definiert haben. Wenn Sie beispielsweise eine Debug-App erstellen, können Sie nicht sowohl
src/debug/Utility.kt
als auchsrc/main/Utility.kt
definieren, da Gradle während des Build-Prozesses beide Verzeichnisse berücksichtigt und einen Fehler vom Typ „duplicate class“ (doppelte Klasse) ausgibt. Wenn Sie verschiedene Versionen vonUtility.kt
für verschiedene Build-Typen verwenden möchten, muss für jeden Build-Typ eine eigene Version der Datei definiert werden. Die Datei darf nicht im Quellsatzmain/
enthalten sein. - Manifeste werden zu einem einzigen Manifest zusammengeführt. Die Priorität wird in derselben Reihenfolge wie in der Liste im vorherigen Beispiel vergeben. Das bedeutet, dass Manifesteinstellungen für einen Build-Typ die Manifesteinstellungen für einen Produkt-Flavor überschreiben usw. Weitere Informationen zum Zusammenführen von Manifesten
- Dateien in den Verzeichnissen
values/
werden zusammengeführt. Wenn zwei Dateien denselben Namen haben, z. B. zweistrings.xml
-Dateien, wird die Priorität in derselben Reihenfolge wie in der Liste im vorherigen Beispiel vergeben. Das bedeutet, dass Werte, die in einer Datei im Quellsatz des Build-Typs definiert sind, die Werte überschreiben, die in derselben Datei in einem Produkt-Flavor definiert sind. - Ressourcen in den Verzeichnissen
res/
undasset/
werden zusammen verpackt. Wenn in zwei oder mehr Quellsets Ressourcen mit demselben Namen definiert sind, wird die Priorität in derselben Reihenfolge wie in der Liste im vorherigen Beispiel festgelegt. - Gradle weist Ressourcen und Manifesten, 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 Build-Variante oder Test-Quellgruppe konfigurieren möchten, stellen Sie dem Namen der Build-Variante oder Test-Quellgruppe das Keyword Implementation
voran, 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.
Variantensensitive Abhängigkeitsverwaltung verwenden
Das Android-Gradle-Plug-in 3.0.0 und höher enthält einen neuen Abhängigkeitsmechanismus, der Varianten beim Verwenden einer Bibliothek automatisch abgleicht. Das bedeutet, dass die debug
-Variante einer App automatisch die debug
-Variante einer Bibliothek nutzt usw. Das funktioniert auch bei der Verwendung von Produktvarianten: Die freeDebug
-Variante einer App verwendet die freeDebug
-Variante einer Bibliothek.
Damit das Plug-in Varianten genau zuordnen kann, müssen Sie passende Fallbacks angeben, wie im folgenden Abschnitt beschrieben. Das ist für Fälle erforderlich, in denen eine direkte Übereinstimmung nicht möglich ist.
Angenommen, in Ihrer App ist ein Build-Typ namens „staging“ konfiguriert, in einer der zugehörigen Bibliotheksabhängigkeiten jedoch nicht. Wenn das Plug-in versucht, die „Staging“-Version Ihrer App zu erstellen, weiß es nicht, welche Version der Bibliothek verwendet werden soll, und Sie erhalten eine Fehlermeldung ähnlich der folgenden:
Error:Failed to resolve: Could not resolve project :mylibrary. Required by: project :app
Build-Fehler im Zusammenhang mit dem Abgleich von Varianten beheben
Das Plug-in enthält DSL-Elemente, mit denen Sie steuern können, wie Gradle Situationen auflöst, in denen ein direkter Variantenabgleich zwischen einer App und einer Abhängigkeit nicht möglich ist.
Im Folgenden finden Sie eine Liste der Probleme im Zusammenhang mit dem variantenbewussten Abgleich von Abhängigkeiten und wie Sie sie mit DSL-Attributen beheben können:Ihre App enthält einen Build-Typ, der in einer Bibliotheksabhängigkeit nicht vorhanden ist.
Ihre App enthält beispielsweise den Build-Typ „staging“, eine Abhängigkeit jedoch nur die Build-Typen „debug“ und „release“.
Es gibt kein Problem, wenn eine Bibliotheksabhängigkeit einen Buildtyp enthält, den Ihre App nicht hat. Das liegt daran, dass das Plug-in diesen Build-Typ nie von der Abhängigkeit anfordert.
Verwenden Sie
matchingFallbacks
, um alternative Übereinstimmungen für einen bestimmten Build-Typ 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 Flavor-Dimension, die sowohl in der App als auch in der Bibliotheksabhängigkeit vorhanden ist, enthält Ihre App Flavors, die in der Bibliothek nicht vorhanden sind.
Sowohl Ihre App als auch ihre Bibliotheksabhängigkeiten enthalten beispielsweise eine „Tier“-Flavor-Dimension. Die Dimension „Tier“ in der App enthält jedoch die Varianten „Kostenlos“ und „Kostenpflichtig“, während eine Abhängigkeit nur die Varianten „Demo“ und „Kostenpflichtig“ für dieselbe Dimension enthält.
Wenn eine bestimmte Flavour-Dimension sowohl in der App als auch in den Bibliotheksabhängigkeiten vorhanden ist, gibt es kein Problem, wenn eine Bibliothek einen Produkt-Flavor enthält, den Ihre App nicht enthält. Das liegt daran, dass das Plug-in diesen Flavor nie von der Abhängigkeit anfordert.
Verwenden Sie
matchingFallbacks
, um alternative Übereinstimmungen für die Produktvariante „free“ 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 Flavor-Dimension, die Ihre App nicht enthält.
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 Flavor-Dimension enthält, die eine Bibliotheksabhängigkeit nicht enthält. Das liegt daran, dass das Plug-in nur Varianten der Dimensionen abgleicht, die in der Abhängigkeit vorhanden sind. Wenn eine Abhängigkeit beispielsweise keine Dimension für ABIs enthält, würde die Version „freeX86Debug“ Ihrer App die Version „freeDebug“ der Abhängigkeit verwenden.
Verwenden Sie
missingDimensionStrategy
im BlockdefaultConfig
, um den Standard-Flavor für das Plug-in anzugeben, aus dem für jede fehlende Dimension ausgewählt werden soll, wie im folgenden Beispiel gezeigt. Sie können Ihre Auswahl auch improductFlavors
-Block ü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 das Android-Gradle-Plug-in unter matchingFallbacks
und missingDimensionStrategy
.
Signierungseinstellungen konfigurieren
Gradle signiert die APK oder das AAB Ihres Release-Builds nur, wenn Sie explizit eine Signaturkonfiguration für diesen Build definieren. Wenn Sie noch keinen Signaturschlüssel haben, generieren Sie mit Android Studio einen Uploadschlüssel und einen Keystore.
So konfigurieren Sie die Signierungskonfigurationen für Ihren Release-Build-Typ manuell mit Gradle-Build-Konfigurationen:
- Erstellen Sie einen Schlüsselspeicher. Ein Schlüsselspeicher ist eine Binärdatei, die eine Reihe privater Schlüssel enthält. Bewahren Sie Ihren Schlüsselspeicher an einem sicheren Ort auf.
- Erstellen Sie einen privaten Schlüssel. Ein privater Schlüssel wird verwendet, um Ihre App für den Vertrieb zu signieren. 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 keine gute Sicherheitspraxis, die Passwörter für Ihren Release-Schlüssel und Ihren Keystore in die Build-Datei aufzunehmen. Konfigurieren Sie stattdessen die Build-Datei so, dass diese Passwörter aus Umgebungsvariablen abgerufen werden oder Sie während des Build-Prozesses zur Eingabe dieser Passwörter aufgefordert werden.
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 Keystore aus einer lokalen Properties-Datei laden. Aus Sicherheitsgründen sollten Sie diese Datei nicht der Quellcodeverwaltung hinzufügen. Richten Sie sie stattdessen lokal für jeden Entwickler ein. Weitere Informationen finden Sie unter Signaturinformationen aus Build-Dateien entfernen.
Nachdem Sie diesen Prozess abgeschlossen haben, können Sie Ihre App verteilen und bei Google Play veröffentlichen.
Warnung:Bewahren Sie Ihren Keystore und Ihren 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 anfordern, dass er zurückgesetzt wird. Wenn Sie eine App ohne die Play App-Signatur veröffentlichen (für Apps, die vor August 2021 erstellt wurden) und Ihren 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 werden. Weitere Informationen zum Verpacken und Signieren von Wear OS-Apps findest du unter Wear-Apps im Paket anbieten und vertreiben.