Build-Varianten konfigurieren

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 Build-Variante 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 sind das Ergebnis von Gradle, das 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. Für den Buildtyp „debug“ werden dagegen andere Build- und Verpackungseinstellungen angewendet, z. B. Debug-Optionen und Signaturschlüssel. Die Build-Variante, die diese beiden Komponenten kombiniert, ist die Version „demoDebug“ Ihrer Anwendung. Sie enthält eine Kombination aus den Konfigurationen und Ressourcen, die im Produkt-Flavor „Demo“, dem Build-Typ „Debug“ und dem Quellsatz main/ 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 kannst du Fehler in der App auf sicheren Android-Geräten beheben und die App-Signatur mit einem generischen Keystore für die Fehlerbehebung konfigurieren.

Sie können den Buildtyp „Fehlerbehebung“ Ihrer Konfiguration 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, muss Ihr Projekt in Android Studio mit der neuen Konfiguration synchronisiert werden. Klicken Sie zum Synchronisieren Ihres Projekts auf Jetzt synchronisieren in der Benachrichtigungsleiste, die angezeigt wird, wenn Sie eine Änderung vornehmen, oder klicken Sie 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.

Produktgeschmacksrichtungen 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: Du musst trotzdem noch einen Paketnamen mithilfe des Attributs package in der Manifestdatei main/ angeben. Sie müssen diesen Paketnamen auch in Ihrem Quellcode verwenden, um auf die R-Klasse zu verweisen oder um relative Aktivitäten oder Dienstregistrierungen aufzulösen. So kannst du mit applicationId jedem 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 einer Flavor-Dimension alle Geschmacksrichtungen 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-Plug-in dieser Dimension automatisch alle Varianten des Moduls zu.

Im folgenden Codebeispiel wird eine Flavor-Dimension mit dem Namen „version“ erstellt und die Produkt-Flavors „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 zu und geben Sie jeder Variante einen anderen versionCode-Wert. 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 Build-Varianten anhand Ihrer Build-Typen und Produkt-Varianten und benennt sie nach <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 Build-Variante mit ihren eigenen Features und Ressourcen anpassen möchten, müssen Sie Quellsätze 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. Für jede Variante im productFlavors-Block können Sie das Attribut applicationId neu definieren oder stattdessen ein Segment mit applicationIdSuffix an die Standardanwendungs-ID anhängen, wie hier gezeigt:

Kotlin

android {
    defaultConfig {
        applicationId = "com.example.myapp"
    }
    productFlavors {
        create("free") {
            applicationIdSuffix = ".free"
        }
        create("pro") {
            applicationIdSuffix = ".pro"
        }
    }
}

Cool

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"
        }
    }
}

Cool

android {
    ...
    buildTypes {
        debug {
            applicationIdSuffix ".debug"
        }
    }
}

Da Gradle die Buildtypkonfiguration nach dem Produkt-Flavor 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- 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 andere versionCode zuweisen. Weitere Informationen finden Sie unter Unterstützung für mehrere APKs. Die Veröffentlichung mit AABs ist davon nicht betroffen, da dabei ein einzelnes Artefakt mit einem einzelnen Versionscode und einer einzigen Anwendungs-ID verwendet wird.

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 Produkt-Flavor-Dimensionen als Flavor-Dimensionen 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 jede Build-Variante oder die entsprechenden Artefakte benennt, werden zuerst die Produkt-Varianten angezeigt, die zur Flavor-Dimension mit höherer Priorität gehören, gefolgt von denen aus Dimensionen mit niedrigerer Priorität und schließlich dem Build-Typ.

Am Beispiel der vorherigen Build-Konfiguration erstellt Gradle insgesamt 12 Build-Varianten mit folgendem Namensschema:

  • 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 dann nur, wenn eine Variante erstellt wird, 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 durch 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 Build-Variantenkonfigurationen entfernen möchten, erstellen Sie in der Datei build.gradle.kts auf Modulebene einen Variantenfilter.

Nehmen wir als Beispiel die Build-Konfiguration aus dem vorherigen Abschnitt an und nehmen wir an, Sie möchten nur API-Level 23 und höher für die Demoversion der App unterstützen. Mit dem Block variantFilter können Sie alle Build-Variantenkonfigurationen herausfiltern, die die Produkt-Varianten „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 festzulegen, 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:

  1. Klicken Sie in der Symbolleiste des Tool-Fensters auf Gradle.
  2. 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:

    1. Klicken Sie auf Datei > Einstellungen > Experimentell (Android Studio > Einstellungen > Experimentell unter macOS).
    2. Heben Sie die Auswahl der Option Gradle-Aufgabenliste während der Gradle-Synchronisierung nicht erstellen auf.
  3. 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:

  1. Öffnen Sie den Bereich Projekt und wählen Sie oben im Bereich im Menü die Ansicht Projekt aus.
  2. Zu MyProject/app/src/ navigieren
  3. Klicken Sie mit der rechten Maustaste auf das Verzeichnis src und wählen Sie Neu > Verzeichnis aus.
  4. Wählen Sie im Menü unter Gradle-Quellsätze die Option full/java aus.
  5. 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“:

  1. Klicken Sie im Bereich Projekt mit der rechten Maustaste auf das Verzeichnis src und wählen Sie Neu > XML > Values XML-Datei aus.
  2. Geben Sie den Namen für die XML-Datei ein oder behalten Sie den Standardnamen bei.
  3. Wählen Sie im Menü neben Zielquellen-Set die Option debug aus.
  4. 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 aus wie in Abbildung 1.

Abbildung 1. Neue Verzeichnisse für Quellsätze für den Buildtyp „debug“

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 des Quellsatzes ä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 dem bzw. 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")
      ...
  }
}
...

Cool

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'
      ...
    }
  }
}
...

Beachten Sie, dass ein Quellverzeichnis nur zu einem Quellsatz gehören kann. 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 Quellsatzverzeichnisse so verwenden, dass sie den Code und die Ressourcen enthalten, die nur mit bestimmten Konfigurationen gepackt werden sollen. Wenn Sie beispielsweise die Build-Variante „demoDebug“ erstellen, die das Kreuzprodukt einer Produkt-Variante „Demo“ und eines Build-Typs „debug“ ist, prüft Gradle diese Verzeichnisse und gibt ihnen die folgende Priorität:

  1. src/demoDebug/ (Build-Variante – Quellsatz)
  2. src/debug/ (Build-Typ-Quellsatz)
  3. src/demo/ (Menge der Geschmacksquelle des Produkts)
  4. src/main/ (Hauptquellensatz)

In Quellgruppen, die für Kombinationen von Produktvarianten erstellt wurden, müssen alle Variantendimensionen enthalten sein. Der Quellsatz der Build-Variante muss beispielsweise die Kombination aus dem Build-Typ und allen Flavor-Dimensionen sein. Das Zusammenführen von Code und Ressourcen mit Ordnern, die mehrere, aber nicht alle Flavor-Dimensionen 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 dem Attribut android.flavorDimensions auflisten, haben Produktsorten, die zur ersten von Ihnen aufgelisteten Geschmacksdimension gehören, eine höhere Priorität als die der zweiten Geschmacksdimension. 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 bei der Anwendung der folgenden Build-Regeln:

  • Der gesamte Quellcode in den Verzeichnissen kotlin/ oder java/ 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-Anwendung erstellen, können Sie nicht sowohl src/debug/Utility.kt als auch src/main/Utility.kt definieren, da Gradle diese Verzeichnisse während des Build-Prozesses prüft und einen Fehler vom Typ „Duplizierte Klasse“ ausgibt. Wenn Sie verschiedene Utility.kt-Versionen für verschiedene Build-Typen verwenden möchten, muss jeder Build-Typ eine eigene Version der Datei definieren und nicht in den main/-Quellsatz aufnehmen.

  • 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 Manifestzusammenführung.
  • Dateien in den values/-Verzeichnissen werden zusammengeführt. Wenn zwei Dateien denselben Namen haben, z. B. zwei strings.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, usw.
  • Ressourcen in den Verzeichnissen res/ und asset/ 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 dem Keyword Implementation den Namen der Buildvariante oder des Test-Quellsets vorangestellt hinzu, 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, Ihre Anwendung konfiguriert einen Build-Typ namens „Staging“, eine der 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. 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 dem Variantenabgleich beheben

Das Plug-in enthält DSL-Elemente, mit denen Sie steuern können, wie Gradle Situationen behebt, in denen eine direkte Variantenü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 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 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.

    Beachten Sie, dass für eine bestimmte Flavor-Dimension, die sowohl in der App als auch in ihren Bibliotheksabhängigkeiten vorhanden ist, kein Problem auftritt, wenn eine Bibliothek einen Produkt-Flavor enthält, den Ihre App nicht enthält. Das liegt daran, dass das Plug-in diese Variante nie von der Abhängigkeit anfordert.

    Verwende 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 Flavors für eine „minApi“-Dimension, Ihre Anwendung aber nur Flavors 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, verwendet die Version „freeX86Debug“ Ihrer App die Version „freeDebug“ der Abhängigkeit.

    Verwenden Sie missingDimensionStrategy im Block defaultConfig, 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 im Block productFlavors auch überschreiben, damit jede Variante eine andere Abgleichsstrategie für eine fehlende Dimension angeben 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 Android Gradle-Plug-in-DSL-Referenz unter matchingFallbacks und missingDimensionStrategy.

Signatureinstellungen konfigurieren

Gradle signiert nur dann das APK oder AAB Ihres Release-Builds, 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:

  1. Erstellen Sie einen Schlüsselspeicher. Ein Schlüsselspeicher ist eine Binärdatei, die eine Reihe privater Schlüssel enthält. Sie müssen Ihren Schlüsselspeicher an einem sicheren Ort aufbewahren.
  2. 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.
  3. 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 Versionsverwaltung 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

Wenn du Wear OS-Apps veröffentlichst, 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.