Build-Varianten konfigurieren

Auf dieser Seite erfahren Sie, wie Sie Build-Varianten konfigurieren können, um verschiedene Versionen Ihrer Anwendung aus einem einzelnen Projekt zu erstellen. Außerdem erfahren Sie, wie Sie Ihre Abhängigkeiten und Signaturkonfigurationen ordnungsgemäß verwalten.

Jede Build-Variante stellt eine andere Version Ihrer Anwendung dar, die Sie erstellen können. Vielleicht möchten Sie beispielsweise eine kostenlose Version Ihrer App mit einer begrenzten Anzahl an Inhalten und eine weitere kostenpflichtige Version mit mehr Inhalten erstellen. Du kannst auch verschiedene Versionen deiner App erstellen, die je nach API-Level oder anderen Gerätevarianten auf unterschiedliche Geräte ausgerichtet sind.

Build-Varianten sind das Ergebnis von Gradle, bei dem ein bestimmter Regelsatz verwendet wird, um Einstellungen, Code und Ressourcen zu kombinieren, die in Ihren Build-Typen und Produktvarianten konfiguriert sind. Obwohl Sie Build-Varianten nicht direkt konfigurieren, konfigurieren Sie die Build-Typen und Produktvarianten, aus denen sie bestehen.

In einer Demoversion können beispielsweise bestimmte Funktionen und Geräteanforderungen angegeben werden, z. B. benutzerdefinierter Quellcode, Ressourcen und Mindest-API-Levels. Beim Debug-Build-Typ werden hingegen andere Build- und Paketeinstellungen angewendet, z. B. Optionen zur Fehlerbehebung und Signaturschlüssel. Die Build-Variante, die diese beiden Varianten kombiniert, ist die „demoDebug“-Version Ihrer App. Sie umfasst eine Kombination aus den Konfigurationen und Ressourcen, die in der Produktvariante „Demo“, dem Build-Typ „Debug“ und der main/-Quellgruppe enthalten sind.

Build-Typen konfigurieren

Sie können Build-Typen im Block android der Datei build.gradle.kts auf Modulebene erstellen und konfigurieren. Wenn Sie ein neues Modul erstellen, erstellt Android Studio automatisch die Debug- und Release-Build-Typen. Obwohl der Build-Typ zur Fehlerbehebung nicht in der Build-Konfigurationsdatei angezeigt wird, wird er von 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 Schlüsselspeicher konfigurieren.

Sie können den Build-Typ zur Fehlerbehebung in Ihre Konfiguration aufnehmen, wenn Sie bestimmte Einstellungen hinzufügen oder ändern möchten. Im folgenden Beispiel wird ein applicationIdSuffix für den Build-Typ zur Fehlerbehebung angegeben und der Build-Typ „Staging“ wird konfiguriert, der mithilfe der Einstellungen des Build-Typs „Debug“ 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"
        }
    }
}

Groovig

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. Klicken Sie zum Synchronisieren Ihres Projekts 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 bei der Konfiguration feststellt, wird im Fenster Nachrichten eine Beschreibung des Problems angezeigt.

Weitere Informationen zu allen Attributen, die Sie mit Build-Typen konfigurieren können, finden Sie in der Referenz zu BuildType.

Produktvarianten konfigurieren

Das Erstellen von Produktvarianten ähnelt dem Erstellen von Build-Typen. Fügen Sie dem productFlavors-Block in der Build-Konfiguration Produktvarianten hinzu und geben Sie die gewünschten Einstellungen an. Die Produktvarianten unterstützen dieselben Attribute wie defaultConfig, da defaultConfig zur Klasse ProductFlavor gehört. Das bedeutet, dass Sie die Basiskonfiguration für alle Flavors im defaultConfig-Block bereitstellen können und jeder Flavor jede dieser Standardwerte, z. B. applicationId, ändern kann. Weitere Informationen zur Anwendungs-ID finden Sie unter Anwendungs-ID festlegen.

Hinweis: Du musst weiterhin einen Paketnamen mithilfe des Attributs package in der Manifestdatei main/ angeben. Sie müssen diesen Paketnamen auch in Ihrem Quellcode verwenden, um auf die Klasse R zu verweisen oder um eine relative Aktivität oder Dienstregistrierung aufzulösen. So können Sie applicationId verwenden, um jeder Produktsorte eine eindeutige ID für die Verpackung und den Vertrieb zu geben, ohne den Quellcode ändern zu müssen.

Alle Geschmacksrichtungen müssen zu einer benannten Geschmacksdimension gehören, die eine Gruppe von Produktaromen ist. Sie müssen alle Geschmacksrichtungen einer Flavor-Dimension zuweisen, da Sie andernfalls den folgenden Build-Fehler erhalten.

  Error: All flavors must now belong to a named flavor dimension.
  The flavor 'flavor_name' is not assigned to a flavor dimension.

Wenn in einem bestimmten Modul nur eine Flavor-Dimension angegeben ist, weist das Android-Gradle-Plug-in dieser Dimension automatisch alle Flavor-Varianten des Moduls zu.

Im folgenden Codebeispiel wird eine Flavor-Dimension namens „version“ erstellt und die Produktvarianten „demo“ und „full“ hinzugefügt. Für diese Geschmacksrichtungen haben wir 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"
        }
    }
}

Groovig

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 du eine Legacy-App hast, die vor August 2021 erstellt wurde und die du über APKs bei Google Play vertreibst, musst du allen Varianten denselben applicationId-Wert zuweisen und jeder Variante einen anderen versionCode-Wert zuweisen. Wenn du verschiedene Varianten deiner App als separate Apps bei Google Play vertreiben möchtest, musst du jeder Variante eine eigene 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, die auf deinen Build-Typen und Produktvarianten basieren, 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

Rufen Sie Build > Build-Variante auswählen auf und wählen Sie eine Build-Variante aus dem Menü aus, um festzulegen, welche Build-Variante erstellt und ausgeführt werden soll. Damit Sie jede Build-Variante mit eigenen Features und Ressourcen anpassen können, 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 Anwendung 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 angezeigt werden, z. B. eine kostenlose und eine Pro-Version, müssen Sie separate Build-Varianten erstellen, die jeweils eine andere Anwendungs-ID haben.

Definieren Sie in diesem Fall jede Build-Variante als eine eigene Produktvariante. Für jede Flavor innerhalb des productFlavors-Blocks 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"
        }
    }
}

Groovig

android {
    defaultConfig {
        applicationId "com.example.myapp"
    }
    productFlavors {
        free {
            applicationIdSuffix ".free"
        }
        pro {
            applicationIdSuffix ".pro"
        }
    }
}

Die Anwendungs-ID für die Produktsorte „kostenlos“ lautet dann „com.example.myapp.free“.

Sie können auch applicationIdSuffix verwenden, um ein Segment basierend auf Ihrem Build-Typ wie hier gezeigt anzuhängen:

Kotlin

android {
    ...
    buildTypes {
        getByName("debug") {
            applicationIdSuffix = ".debug"
        }
    }
}

Groovig

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

Da Gradle die Build-Typkonfiguration nach der Produkt-Flavor anwendet, lautet die Anwendungs-ID für die Build-Variante "free debug" (kostenlose Fehlerbehebung) "com.example.myapp.free.debug". Das ist nützlich, wenn die Debug- und die Release-Version auf demselben Gerät erstellt werden sollen, da keine zwei Apps dieselbe Anwendungs-ID haben dürfen.

Wenn Sie eine vor August 2021 erstellte Legacy-App über APKs bei Google Play vertreiben und denselben App-Eintrag für mehrere APKs verwenden möchten, die jeweils auf eine andere Gerätekonfiguration wie das API-Level ausgerichtet sind, müssen Sie für jede Build-Variante dieselbe App-ID verwenden, aber jedem APK eine andere versionCode zuweisen. Weitere Informationen finden Sie unter Unterstützung mehrerer APKs. Die Veröffentlichung mit AABs ist nicht betroffen, da ein einzelnes Artefakt verwendet wird, das standardmäßig einen einzigen Versionscode und eine Anwendungs-ID verwendet.

Tipp:Wenn du in der Manifestdatei auf die Anwendungs-ID verweisen musst, kannst du in einem beliebigen Manifestattribut den Platzhalter ${applicationId} 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 Geschmacksdimensionen kombinieren

In manchen Fällen möchten Sie möglicherweise Konfigurationen aus mehreren Produktvarianten kombinieren. Sie können beispielsweise verschiedene Konfigurationen für die Produktvarianten „Full“ und „Demo“ erstellen, die auf dem API-Level basieren. Dazu können Sie mit dem Android-Gradle-Plug-in mehrere Gruppen von Produktvarianten als Flavor-Dimensionen erstellen.

Beim Erstellen Ihrer App kombiniert Gradle eine Produkt-Flavor-Konfiguration aus jeder von Ihnen definierten Flavor-Dimension mit einer Build-Typ-Konfiguration, um die endgültige Build-Variante zu erstellen. Gradle kombiniert keine Produktvarianten, die zur selben Flavor-Dimension gehören.

Im folgenden Codebeispiel wird die Eigenschaft flavorDimensions verwendet, um die Flavor-Dimension „mode“ zu erstellen, um die Produktvarianten „full“ und „demo“ zu gruppieren, und eine Flavordimension „api“, um Produkt-Flavor-Konfigurationen basierend auf dem API-Level 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"
      ...
    }
  }
}
...

Groovig

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 Build-Varianten entspricht dem Produkt aus der Anzahl der Geschmacksrichtungen in jeder Flavor-Dimension und der Anzahl der von Ihnen konfigurierten Build-Typen. Wenn Gradle jede Build-Variante oder entsprechende Artefakte benennt, werden zuerst die Produktvarianten angezeigt, die zu Flavor-Dimensionen mit höherer Priorität gehören, gefolgt von denjenigen von Dimensionen mit niedrigerer Priorität, gefolgt vom Build-Typ.

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

  • Build-Variante: [minApi24, minApi23, minApi21][Demo, Full][Debug, Release]
  • Zugehörige APK: app-[minApi24, minApi23, minApi21]-[demo, full]-[debug, release].apk
  • Beispiel:
    Build-Variante: minApi24DemoDebug
    Entsprechendes APK: app-minApi24-demo-debug.apk

Neben den Quellsatzverzeichnissen, die Sie für jede einzelne Produkt-Flavor und Build-Variante erstellen können, können Sie auch Quellsatz-Verzeichnisse für jede Kombination von Produktvarianten erstellen. Sie können beispielsweise Java-Quellen erstellen und dem Verzeichnis src/demoMinApi24/java/ hinzufügen. Gradle verwendet diese Quellen dann nur, wenn eine Variante erstellt wird, die diese beiden Produktvarianten kombiniert.

Quellsätze, die Sie für Produktvarianten erstellen, haben eine höhere Priorität als Quellsätze, die zu den einzelnen Produktvarianten gehören. Weitere Informationen zu Quellsätzen und dazu, wie Gradle Ressourcen zusammenführt, findest du 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 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 in der Datei build.gradle.kts auf Modulebene einen Variantenfilter.

Wenn Sie die Build-Konfiguration aus dem vorherigen Abschnitt als Beispiel verwenden, gehen wir davon aus, dass Sie in der Demoversion der App nur API-Level 23 und höher unterstützen möchten. Mit dem Block variantFilter können Sie alle Konfigurationen der Build-Varianten herausfiltern, die die Produktvarianten „minApi21“ und „demo“ kombinieren:

Kotlin

android {
  ...
  buildTypes {...}

  flavorDimensions += listOf("api", "mode")
  productFlavors {
    create("demo") {...}
    create("full") {...}
    create("minApi24") {...}
    create("minApi23") {...}
    create("minApi21") {...}
  }
}

androidComponents {
    beforeVariants { variantBuilder ->
        // To check for a certain build type, use variantBuilder.buildType == "<buildType>"
        if (variantBuilder.productFlavors.containsAll(listOf("api" to "minApi21", "mode" to "demo"))) {
            // Gradle ignores any variants that satisfy the conditions above.
            variantBuilder.enable = false
        }
    }
}
...

Groovig

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 Sync Now (Jetzt synchronisieren) geklickt haben, ignoriert Gradle alle Build-Varianten, die die von Ihnen angegebenen Bedingungen erfüllen. Die Build-Varianten werden nicht mehr im Menü angezeigt, wenn Sie in der Menüleiste auf Build > Build-Variante auswählen oder in der Symbolleiste des Fensters auf Varianten erstellen klicken.

Quellsätze erstellen

In Android Studio werden standardmäßig der Quellsatz main/ und die Verzeichnisse für alles erstellt, was Sie für Ihre Build-Varianten freigeben möchten. Sie können jedoch neue Quellsätze erstellen und so genau steuern, welche Dateien Gradle für bestimmte Build-Typen, Produktvarianten, Kombinationen von Produktvarianten (bei Verwendung von Flavor-Dimensionen) und Build-Varianten kompiliert und kompiliert.

Beispielsweise können Sie grundlegende Funktionen im Quellsatz main/ definieren und Quellsätze der Produktvarianten verwenden, um das Branding Ihrer App für verschiedene Clients zu ändern, oder spezielle Berechtigungen und Logging-Funktionen nur für Build-Varianten hinzufügen, die den Build-Typ „Debug“ verwenden.

Gradle erwartet, dass Quelldateien und ‐verzeichnisse auf eine bestimmte Weise organisiert sind, ähnlich wie beim main/-Quellsatz. Gradle erwartet beispielsweise, dass sich Kotlin- oder Java-Klassendateien für Ihren Build-Typ „Debug“ im Verzeichnis src/debug/kotlin/ oder src/debug/java/ befinden.

Das Android-Gradle-Plug-in bietet eine nützliche Gradle-Aufgabe, mit der Sie Ihre Dateien für jeden Ihrer Build-Typen, Produktvarianten und Build-Varianten organisieren können. Im folgenden Beispiel aus der Aufgabenausgabe sehen Sie beispielsweise, wo Gradle bestimmte Dateien für den Build-Typ „debug“ findet:

------------------------------------------------------------
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 Leiste des Toolfensters auf Gradle.
  2. Gehen Sie zu MyApplication > Tasks > android und klicken Sie doppelt auf sourceSets.

    Damit der Ordner Tasks angezeigt wird, müssen Sie Gradle erlauben, die Aufgabenliste während der Synchronisierung zu erstellen. Das funktioniert so:

    1. Klicken Sie auf Datei > Einstellungen > Experimentell (Android Studio > Einstellungen > Experimentell unter macOS).
    2. Heben Sie die Auswahl der Option Do not build Gradle Aufgabenliste während der Gradle-Synchronisierung auf.
  3. Nachdem Gradle die Aufgabe ausgeführt hat, wird das Fenster Ausführen geöffnet, in dem die Ausgabe angezeigt wird.

Hinweis: Die Aufgabenausgabe zeigt auch, wie Sie Quellsätze für Dateien organisieren, die Sie zum Ausführen von Tests für Ihre Anwendung verwenden möchten, z. B. die Testquellengruppen test/ und androidTest/.

Wenn Sie eine neue Build-Variante erstellen, werden die Quellsatz-Verzeichnisse von Android Studio nicht automatisch erstellt. Ihnen werden jedoch einige Optionen zur Verfügung gestellt. So erstellen Sie beispielsweise nur das Verzeichnis java/ für den Build-Typ „debug“:

  1. Öffnen Sie den Bereich Projekt und wählen Sie im Menü oben 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 Source Sets (Gradle-Quellsätze) die Option full/java aus.
  5. Drücken Sie die Eingabetaste.

Android Studio erstellt ein Quellsatzverzeichnis für den Build-Typ zur Fehlerbehebung und darin das Verzeichnis java/. 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.

So erstellen Sie beispielsweise eine Werte-XML-Datei für den Build-Typ „Debug“:

  1. Klicken Sie im Bereich Projekt mit der rechten Maustaste auf das Verzeichnis src und wählen Sie Neu > XML > XML-Datei für Werte aus.
  2. Geben Sie den Namen der XML-Datei ein oder behalten Sie den Standardnamen bei.
  3. Wählen Sie im Menü neben Zielquellengruppe die Option Debug aus.
  4. Klicken Sie auf Fertig.

Da der Build-Typ „debug“ als Zielquellsatz angegeben wurde, erstellt Android Studio beim Erstellen der XML-Datei automatisch die erforderlichen Verzeichnisse. Die resultierende Verzeichnisstruktur sieht in Abbildung 1 aus.

Abbildung 1: Neue Quellsatzverzeichnisse für den Build-Typ „debug“.

Aktive Quellensätze sind durch einen grünen Indikator im Symbol gekennzeichnet. Dem Quellsatz debug wird das Suffix [main] angehängt, um anzuzeigen, dass er mit dem Quellsatz main zusammengeführt wird.

Mit demselben Verfahren können Sie auch Quellsatz-Verzeichnisse für Produktvarianten (z. B. src/demo/) und Build-Varianten wie src/demoDebug/ erstellen. Darüber hinaus können Sie Testquellensätze erstellen, die auf bestimmte Build-Varianten ausgerichtet sind, z. B. src/androidTestDemoDebug/. Weitere Informationen finden Sie unter Quellensätze testen.

Standardkonfigurationen für Quellsätze ändern

Wenn Quellen nicht in der von Gradle erwarteten Standarddateistruktur für Quelldateien organisiert sind, wie im vorherigen Abschnitt zum Erstellen von Quellsätzen beschrieben, kannst du mit dem Block sourceSets ändern, wo Gradle nach Dateien für die einzelnen Komponenten eines Quellsatzes sucht.

Der sourceSets-Block muss im android-Block enthalten sein. Sie müssen die Quelldateien nicht verschieben. Sie müssen Gradle nur die Pfade für die Datei build.gradle.kts auf Modulebene zur Verfügung stellen. Dort findet Gradle Dateien für jede Komponentenkomponente des Quellsatzes. Informationen dazu, welche Komponenten Sie konfigurieren 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 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")
      ...
  }
}
...

Groovig

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 mit den Quellsätzen test und androidTest dieselben Testquellen teilen. Das liegt daran, dass Android Studio separate IntelliJ-Module für jeden Quellsatz erstellt und keine doppelten Inhaltsstämme in Quellsätzen unterstützt.

Mit Quellsätzen erstellen

Sie können Quellsatz-Verzeichnisse verwenden, um den Code und die Ressourcen zu enthalten, die nur mit bestimmten Konfigurationen verpackt werden sollen. Wenn Sie beispielsweise die Build-Variante „demoDebug“ erstellen, die das Kreuzprodukt aus einer „Demo“-Produkt-Flavor und dem Build-Typ „Debug“ ist, sieht sich Gradle diese Verzeichnisse an und gibt ihnen die folgende Priorität:

  1. src/demoDebug/ (Variantenquellsatz erstellen)
  2. src/debug/ (Quellsatz des Build-Typs)
  3. src/demo/ (Quellensatz für Produktsorten)
  4. src/main/ (Hauptquellsatz)

Quellsätze, die für Kombinationen von Produktsorten erstellt werden, müssen alle Geschmacksdimensionen enthalten. Der Quellsatz der Build-Varianten muss beispielsweise die Kombination aus Build-Typ und allen Flavor-Dimensionen sein. Das Zusammenführen von Code und Ressourcen mit Ordnern, die mehrere, aber nicht alle Flavor-Dimensionen umfassen, wird nicht unterstützt.

Wenn Sie mehrere Produktaromen kombinieren, wird die Priorität zwischen den Produktgeschmacksrichtungen durch die Geschmacksdimension bestimmt, zu der sie gehören. Wenn Sie Geschmacksdimensionen mit der Eigenschaft android.flavorDimensions auflisten, haben Produktsorten, die zur ersten Geschmacksdimension gehören, eine höhere Priorität als Geschmacksrichtungen aus der zweiten Dimension usw. Außerdem haben Quellsätze, die Sie für Kombinationen von Produktsorten erstellen, eine höhere Priorität als Quellsätze, die zu einer einzelnen Produktsorte gehören.

Die Reihenfolge der Priorität bestimmt, welcher Quellsatz eine höhere Priorität hat, wenn Gradle Code und Ressourcen kombiniert. Da das demoDebug/-Quellsatzverzeichnis wahrscheinlich Dateien enthält, die für diese Build-Variante spezifisch sind, verwendet Gradle die Datei im demoDebug/-Quellsatz, wenn demoDebug/ eine Datei enthält, die ebenfalls in debug/ definiert ist. In ähnlicher Weise gibt Gradle Dateien im Build-Typ und in der Produkt-Flavor-Quelle eine höhere Priorität als dieselben Dateien in main/. Gradle berücksichtigt diese Prioritätsreihenfolge, wenn die folgenden Build-Regeln angewendet werden:

  • Der gesamte Quellcode in den Verzeichnissen kotlin/ oder java/ 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 Quellsatz-Verzeichnisse gefunden werden, die dieselbe Kotlin- oder Java-Klasse definiert haben. Wenn Sie beispielsweise eine Debug-App erstellen, können Sie nicht sowohl src/debug/Utility.kt als auch src/main/Utility.kt definieren, da Gradle während des Build-Prozesses beide Verzeichnisse prüft und den Fehler „Duplicate class“ ausgibt. Wenn Sie unterschiedliche Versionen von Utility.kt für unterschiedliche 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 gleichen Reihenfolge wie in der Liste im vorherigen Beispiel angegeben. Das heißt, die Manifesteinstellungen für einen Build-Typ überschreiben die Manifesteinstellungen für eine Produktsorte usw. Weitere Informationen finden Sie unter Zusammenführung von Manifesten.
  • Dateien in den Verzeichnissen values/ werden zusammengeführt. Wenn zwei Dateien denselben Namen haben, z. B. zwei strings.xml-Dateien, wird die Priorität in derselben Reihenfolge wie im vorherigen Beispiel zugewiesen. Das heißt, Werte, die in einer Datei im Build-Typ-Quellsatz definiert sind, überschreiben die Werte, die in derselben Datei in einer Produktsorte definiert sind usw.
  • Ressourcen in den Verzeichnissen res/ und asset/ werden zusammen verpackt. Wenn Ressourcen mit demselben Namen in zwei oder mehr Quellsätzen definiert sind, wird die Priorität in derselben Reihenfolge wie in der Liste im vorherigen Beispiel zugewiesen.
  • Gradle gibt Ressourcen und Manifesten, die in Bibliotheksmodulabhängigkeiten enthalten sind, beim Erstellen der Anwendung die niedrigste Priorität.

Abhängigkeiten deklarieren

Wenn Sie eine Abhängigkeit für eine bestimmte Build-Variante oder einen Testquellensatz konfigurieren möchten, stellen Sie den Namen der entsprechenden Build-Variante oder Testquelle vor das Keyword Implementation ein, wie im folgenden Beispiel gezeigt:

Kotlin

dependencies {
    // Adds the local "mylibrary" module as a dependency to the "free" flavor.
    "freeImplementation"(project(":mylibrary"))

    // Adds a remote binary dependency only for local tests.
    testImplementation("junit:junit:4.12")

    // Adds a remote binary dependency only for the instrumented test APK.
    androidTestImplementation("com.android.support.test.espresso:espresso-core:3.5.1")
}

Groovig

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

Weitere Informationen zum Konfigurieren von Abhängigkeiten finden Sie unter Build-Abhängigkeiten hinzufügen.

Variantenbasierte Abhängigkeitsverwaltung verwenden

Das Android-Gradle-Plug-in 3.0.0 und höher enthält einen neuen Abhängigkeitsmechanismus, der Varianten bei der Nutzung einer Bibliothek automatisch abgleicht. Das bedeutet, dass die debug-Variante einer App automatisch die debug-Variante einer Bibliothek verbraucht usw. Das funktioniert auch bei der Verwendung von Geschmacksrichtungen: Die freeDebug-Variante einer App nutzt die freeDebug-Variante einer Bibliothek.

Damit das Plug-in Varianten genau abgleichen kann, müssen Sie für Fälle, in denen keine direkte Zuordnung möglich ist, übereinstimmende Fallbacks bereitstellen. Dies wird im folgenden Abschnitt beschrieben.

Angenommen, in Ihrer Anwendung wird ein Build-Typ namens „staging“ konfiguriert, eine der Bibliotheksabhängigkeiten jedoch nicht. Wenn das Plug-in versucht, die Staging-Version Ihrer Anwendung zu erstellen, weiß es nicht, welche Version der Bibliothek verwendet werden soll, und es wird eine Fehlermeldung wie die folgende angezeigt:

Error:Failed to resolve: Could not resolve project :mylibrary.
Required by:
    project :app

Build-Fehler im Zusammenhang mit Variantenabgleich beheben

Das Plug-in enthält DSL-Elemente, mit denen Sie steuern können, wie Gradle Situationen löst, in denen ein direkter Variantenabgleich zwischen einer App und einer Abhängigkeit nicht möglich ist.

Im Folgenden finden Sie eine Liste von Problemen im Zusammenhang mit dem variantenbasierten Abhängigkeitsabgleich und deren Behebung mithilfe von DSL-Eigenschaften:

  • Deine App enthält einen Build-Typ, der in einer Bibliotheksabhängigkeit nicht enthalten ist.

    Ihre Anwendung enthält beispielsweise den Build-Typ „Staging“, aber eine Abhängigkeit umfasst nur die Build-Typen „Debug“ und „Release“.

    Wenn eine Bibliotheksabhängigkeit einen Build-Typ enthält, der in Ihrer Anwendung nicht enthalten ist, treten keine Probleme auf. Das liegt daran, dass das Plug-in nie den Build-Typ aus 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")
            }
        }
    }

    Groovig

    // 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 Anwendung als auch in ihrer Bibliotheksabhängigkeit vorhanden ist, enthält Ihre Anwendung Flavor-Varianten, die in der Bibliothek nicht vorhanden sind.

    Beispielsweise enthalten sowohl Ihre Anwendung als auch ihre Bibliotheksabhängigkeiten eine Flavor-Dimension „Tier“. Die Dimension „tier“ in der App enthält jedoch die Geschmacksrichtungen „kostenlos“ und „kostenpflichtige“, eine Abhängigkeit jedoch nur die Geschmacksrichtungen „demo“ und „bezahlt“ für dieselbe Dimension.

    Bei einer bestimmten Flavor-Dimension, die sowohl in der Anwendung als auch in ihren Bibliotheksabhängigkeiten vorhanden ist, treten keine Probleme auf, wenn eine Bibliothek eine Produktsorte enthält, die in Ihrer App nicht vorhanden ist. Das liegt daran, dass das Plug-in diesen Geschmack nie aus der Abhängigkeit anfordert.

    Verwende matchingFallbacks, um alternative Übereinstimmungen für die Produktvariante „kostenlos“ 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")
            }
        }
    }
    

    Groovig

    // 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 Flavors für eine „minApi“-Dimension, aber Ihre Anwendung enthält nur Flavors für die „tier“-Dimension. Wenn Sie die „freeDebug“-Version Ihrer Anwendung erstellen möchten, weiß das Plug-in nicht, ob die Version „minApi23Debug“ oder „minApi18Debug“ der Abhängigkeit verwendet werden soll.

    Beachten Sie, dass kein Problem auftritt, wenn Ihre Anwendung eine Flavor-Dimension enthält, die in einer Bibliotheksabhängigkeit nicht enthalten ist. Das liegt daran, dass das Plug-in Varianten nur der Dimensionen abgleicht, die in der Abhängigkeit vorhanden sind. Wenn eine Abhängigkeit beispielsweise keine Dimension für ABIs enthält, verwendet die „freeX86Debug“-Version Ihrer App die „freeDebug“-Version der Abhängigkeit.

    Verwenden Sie missingDimensionStrategy im defaultConfig-Block, um den Standard-Flavor für das Plug-in anzugeben, um aus jeder fehlenden Dimension auszuwählen, wie im folgenden Beispiel gezeigt. Sie können auch Ihre Auswahl im productFlavors-Block überschreiben, sodass für jede Sorte eine andere Abgleichstrategie 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") {}
        }
    }
    

    Groovig

    // 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.

Signatureinstellungen konfigurieren

Gradle signiert das APK oder AAB Ihres Release-Builds nur, wenn Sie explizit eine Signaturkonfiguration für diesen Build definieren. Wenn du noch keinen Signaturschlüssel hast, kannst du mit Android Studio einen Uploadschlüssel und einen Schlüsselspeicher generieren.

So konfigurieren Sie die Signaturkonfigurationen für Ihren Release-Build-Typ mithilfe von Gradle-Build-Konfigurationen manuell:

  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. Ein privater Schlüssel wird verwendet, um Ihre App für die Verteilung zu signieren. Er wird nie in der App enthalten sein oder für nicht autorisierte Dritte offengelegt.
  3. Fügen Sie die Signaturkonfiguration zur Datei build.gradle.kts auf Modulebene hinzu:

    Kotlin

    ...
    android {
        ...
        defaultConfig {...}
        signingConfigs {
            create("release") {
                storeFile = file("myreleasekey.keystore")
                storePassword = "password"
                keyAlias = "MyReleaseKey"
                keyPassword = "password"
            }
        }
        buildTypes {
            getByName("release") {
                ...
                signingConfig = signingConfigs.getByName("release")
            }
        }
    }

    Groovig

    ...
    android {
        ...
        defaultConfig {...}
        signingConfigs {
            release {
                storeFile file("myreleasekey.keystore")
                storePassword "password"
                keyAlias "MyReleaseKey"
                keyPassword "password"
            }
        }
        buildTypes {
            release {
                ...
                signingConfig signingConfigs.release
            }
        }
    }

Hinweis:Es ist keine gute Sicherheitsmaßnahme, die Passwörter für Ihren Releaseschlüssel und den Schlüsselspeicher in der Build-Datei zu speichern. Konfigurieren Sie stattdessen die Build-Datei so, dass diese Passwörter aus Umgebungsvariablen abgerufen werden, oder lassen Sie sich vom Build-Prozess zur Eingabe dieser Passwörter auffordern.

So erhalten Sie diese Passwörter aus Umgebungsvariablen:

Kotlin

storePassword = System.getenv("KSTOREPWD")
keyPassword = System.getenv("KEYPWD")

Groovig

storePassword System.getenv("KSTOREPWD")
keyPassword System.getenv("KEYPWD")

Alternativ können Sie den Schlüsselspeicher aus einer lokalen Eigenschaftsdatei 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 unter Signaturinformationen aus Build-Dateien entfernen.

Anschließend kannst du deine App vertreiben und bei Google Play veröffentlichen.

Warnung: Bewahren Sie Ihren Schlüsselspeicher und den privaten Schlüssel an einem sicheren Ort auf und speichern Sie entsprechende Sicherungen. Wenn Sie Play App Signing verwenden und Ihren Uploadschlüssel verlieren, können Sie über die Play Console ein Zurücksetzen beantragen. Wenn du eine App ohne Play App Signing veröffentlichst (für Apps, die vor August 2021 erstellt wurden) und deinen App-Signaturschlüssel verlieren, kannst du keine Updates für deine App veröffentlichen, da du immer alle Versionen deiner App mit demselben Schlüssel signieren musst.

Wear OS-Apps signieren

Bei der Veröffentlichung von Wear OS-Apps müssen das Smartwatch-APK und das optionale Smartphone-APK mit demselben Schlüssel signiert sein. Weitere Informationen zum Packen und Signieren von Wear OS-Apps findest du unter Wear-Apps verpacken und vertreiben.