Build Variant — was ist build type und product flavor in Android

Autor: IT Sectr Veröffentlicht: 2026-05-30 Lesezeit: 9 Min.

Ein Build Variant in der Android-Entwicklung ist eine Kombination aus einem build type und einem product flavor, die bestimmt, wie eine APK oder AAB erstellt wird: mit welchen Parametern, Ressourcen und Code. Jede Build-Variante stellt eine separate Gradle-Konfiguration mit eigener applicationId, Signierschlüsseln und eingebundenen Abhängigkeiten dar. Laut Google Android Developers, 2025 reduziert die richtige Konfiguration von Build Variants die Build-Zeit um bis zu 40%, indem unnötige Ressourcen für jede Variante ausgeschlossen werden. Das Build-Varianten-System ist die Grundlage des Konfigurationsmanagements in modernen Android-Projekten.

Wichtige Erkenntnisse

  • Build Variant — Kombination aus einem Build Type und einem Product Flavor.
  • Build Type definiert den Build-Modus: Debug oder Release.
  • Product Flavor definiert die App-Version: Free, Paid, Demo, Enterprise.
  • Gradle generiert automatisch Aufgaben für jeden Build Variant, einschließlich Install und Assemble.
  • Ressourcen und Code können für jede Variante über entsprechende Source Sets überschrieben werden.

Was ist ein Build Variant?

Build Variant ist das Ergebnis der Kombination eines Build Type mit einem Product Flavor. Wenn im Projekt keine Product Flavors definiert sind, stimmt der Build Variant mit dem Build Type überein. Gradle generiert automatisch den vollständigen Satz von Varianten als kartesisches Produkt aller FlavorDimensions, Product Flavors und Build Types. Zum Beispiel werden für die Flavors Free/Paid und die Typen Debug/Release 4 Varianten erstellt: FreeDebug, FreeRelease, PaidDebug, PaidRelease.

Jeder Build Variant erhält seinen eigenen Namen im Format <Flavor><Type> mit dem Flavor in Großbuchstaben. Gradle generiert separate Aufgaben für diese Variante: assembleFreeDebug, installFreeDebug, bundleFreeRelease. In Android Studio ist das Umschalten zwischen Varianten über das Build Variants-Panel (View → Tool Windows → Build Variants) verfügbar. Die Auswahl einer Variante beeinflusst, welcher Code kompiliert wird, welche Ressourcen eingebunden werden und welche APK/AAB erzeugt wird.

Das Build Variants-System löst drei Hauptaufgaben: Trennung von Konfigurationen für verschiedene Umgebungen (Dev/Staging/Production), Erstellung mehrerer Versionen einer App (Free/Paid) und A/B-Testing von Builds. Ohne Build Variants müssten Entwickler manuell Flags und Konfigurationen umschalten, was zu menschlichen Fehlern führt. Laut einer Studie von Gradle Inc., 2024 reduziert die Einführung von Build Variants Build-Fehler um 60% in Projekten mit drei oder mehr Deployment-Umgebungen.

Wie Gradle Varianten generiert

AGP (Android Gradle Plugin) berechnet alle Kombinationen in der Konfigurationsphase. Wenn ein Projekt zwei Dimensionen mit zwei bzw. drei Flavors hat, erstellt Gradle 2 × 2 × 3 = 12 Kombinationen, multipliziert mit der Anzahl der Build Types (normalerweise 2). Jede Kombination erhält einen eindeutigen Namen und eine Reihe von Aufgaben. AGP fügt automatisch ein Source Set für jede Variante hinzu: src/freeDebug/, src/paidRelease/, sowie die generalisierten src/free/ und src/debug/. Priorität beim Lesen von Ressourcen: Variant → Flavor → Type → Main.

groovy
// Beispiel: 4 Build Variants
// flavorDimensions "version", "server"
// version: demo, prod
// server: mock, live
// buildTypes: debug, release
// Gesamt: 2 × 2 × 2 = 8 Varianten

android {
    flavorDimensions "version", "server"

    productFlavors {
        demo { dimension "version" }
        prod { dimension "version" }
        mock { dimension "server" }
        live { dimension "server" }
    }
}

Build Type und Product Flavor: Unterschiede

Build Type definiert, wie die Anwendung gebaut wird — mit oder ohne Debug-Informationen, mit oder ohne Optimierung, mit welcher Signierung. Product Flavor definiert, was gebaut wird — welche Version des Produkts. Build Type ist ein Build-Mechanismus (Debug, Release, Staging). Product Flavor ist eine Produktvariante (Free, Paid, Enterprise, Demo). Beide Konzepte sind orthogonal: Jeder Build Type kann auf jeden Product Flavor angewendet werden.

Standard-Build Types umfassen Debug (debuggable=true, minification=false, signing=debug.keystore) und Release (debuggable=false, minification=true, signing=production.keystore). Der Standard-Product Flavor ist einer, unbenannt (effektiv das Main Source Set). Entwickler können eigene Build Types (z.B. „Staging“ mit debuggable=true und minification=true) und beliebig viele Product Flavors hinzufügen. Ein weiterer Unterschied ist, dass Build Types nicht in Dimensionen gruppiert werden können, Product Flavors jedoch schon.

Der wichtigste praktische Unterschied: defaultConfig in build.gradle gilt für alle Variants, kann aber in productFlavors und buildTypes überschrieben werden. Ein zu einem buildType hinzugefügtes BuildConfigField ist in allen Flavors dieses Typs sichtbar, während ein zu einem productFlavor hinzugefügtes in allen Typen dieses Flavors sichtbar ist. Wenn ein Feld in beiden definiert ist, hat buildType Priorität (es wird zuletzt in der Kette angewendet).

Vergleichstabelle

EigenschaftBuild TypeProduct Flavor
ZweckWie bauenWas bauen
Beispieledebug, release, stagingfree, paid, demo, enterprise
Standarddebug + releaseeiner (main)
Source Setsrc/debug/, src/release/src/free/, src/paid/
DimensionenneinflavorDimensions
Anwendungsreihenfolgenach Flavor, überschreibtnach defaultConfig
BuildConfigFieldüberschreibt Flavorüberschreibt defaultConfig

Konfiguration von Build Variants in build.gradle

Konfigurationspriorität

Die Konfiguration von Build Variants erfolgt im android-Block der build.gradle-Datei auf Modulebene. Zuerst werden buildTypes mit ihren Parametern deklariert, dann flavorDimensions und productFlavors. Gradle erstellt automatisch Varianten basierend auf diesen Deklarationen. Jede Variante erbt den defaultConfig des Moduls und überschreibt bestimmte Felder. Die Deklarationsreihenfolge beeinflusst die Priorität: buildTypes werden nach productFlavors angewendet.

Um auf einen bestimmten Build Variant in Gradle-Skripten zuzugreifen, verwenden Sie android.applicationVariants (für App-Module) oder android.libraryVariants (für Bibliotheksmodule). Dies ist eine Sammlung, die durchlaufen werden kann, um die Konfiguration jeder Variante zur Konfigurationslaufzeit zu ändern. Beispielsweise können Sie programmatisch buildConfigField für alle Varianten hinzufügen, die das Wort „Demo“ enthalten.

Android Gradle Plugin 8.x hat Unterstützung für onVariants hinzugefügt — eine sauberere API zum Konfigurieren von Varianten über Lambdas. Die alte API (variantOutput, variantFilter) ist als veraltet markiert. Es wird empfohlen, onVariants zusammen mit onEach für Bibliotheksmodule zu verwenden. Die Migration von variantOutput zu onVariants ist ein empfohlener Schritt beim Upgrade von AGP 7.x auf 8.x.

groovy
android {
    buildTypes {
        debug {
            debuggable true
            minification false
            signingConfig signingConfigs.debug
        }
        release {
            debuggable false
            minification true
            proguardFiles "proguard-rules.pro"
            signingConfig signingConfigs.release
        }
        staging {
            debuggable true
            minification true
            versionNameSuffix "-staging"
        }
    }

    flavorDimensions "tier", "region"

    productFlavors {
        free { dimension "tier" }
        paid { dimension "tier" }
        us { dimension "region" }
        eu { dimension "region" }
    }
}

android.onVariants { variant ->
    if (variant.name.contains("Demo")) {
        variant.setEnabled(false)
    }
}

Source Sets und Ressourcenüberschreibung

Jeder Build Variant erhält seine eigene Hierarchie von Source Sets — Verzeichnisse mit Quellcode, Ressourcen und Manifest. Ein Source Set befindet sich unter src/<variantName>/ (z.B. src/freeDebug/) und kann java/, res/, AndroidManifest.xml, assets/ enthalten. Wenn eine Datei im Source Set der Variante existiert, überschreibt sie die gleichnamige Datei aus dem Haupt-Source Set (src/main/). Bei Ressourcen findet eine Zusammenführung statt, kein Ersatz — das System führt Ressourcen aus allen aktiven Source Sets zusammen und gibt variantenspezifischen Ressourcen Priorität.

Die Source Sets für einen Build Variant werden in einer Kette aufgebaut: src/main/src/flavor/src/type/src/flavorType/. Zum Beispiel wird für paidRelease zuerst main angewendet, dann paid, dann release, dann paidRelease. Jedes nachfolgende Source Set überschreibt das vorherige. Das bedeutet, dass src/release/res/values/strings.xml dieselben Strings aus src/paid/ überschreibt, aber src/paidRelease/res/ hat noch höhere Priorität.

Die Verwendung von Source Sets für Varianten ist der empfohlene Weg, Ressourcen anzupassen. Anstatt BuildConfig.FLAVOR im Code zu überprüfen und die Logik zu verzweigen, können Sie einfach verschiedene Dateien in verschiedene Source Sets legen. Zum Beispiel kommen Icons für Free- und Paid-Versionen in src/free/res/ bzw. src/paid/res/, und das AndroidManifest mit unterschiedlichen Berechtigungen in src/free/AndroidManifest.xml und src/paid/AndroidManifest.xml. Dies ist sauberer, schneller (Ressourcen werden kompiliert, nicht zur Laufzeit geprüft) und sicherer (Sie können nicht versehentlich kostenpflichtige Funktionen aufgrund eines Code-Fehlers in die kostenlose Version einbauen).

Build Variant in Multi-Modul-Projekten

In Multi-Modul-Projekten kann jedes Modul (Bibliothek) seine eigenen Build Variants haben. AGP synchronisiert Varianten automatisch: Wenn das App-Modul paidRelease baut, werden alle abhängigen Bibliotheken ebenfalls in ihren paidRelease-entsprechenden Varianten gebaut. Ein Problem entsteht, wenn eine Bibliothek keine Product Flavors hat, das App-Modul jedoch schon — dann wird die Bibliothek einmal gebaut (Release oder Debug, je nach Typ).

Für Bibliotheksmodule stimmt der Build Variant standardmäßig mit dem Build Type des App-Moduls überein, da Bibliotheken keine Product Flavors haben. Wenn eine Bibliothek sich an den Flavor des App-Moduls anpassen muss, müssen dieselben flavorDimensions und productFlavors in der Bibliothek deklariert werden. AGP gleicht Flavors durch exakte Namensübereinstimmung ab. Gradle empfiehlt, Flavors über die Build-Konfiguration im Root-Projekt mit subprojects oder Convention Plugins zu synchronisieren.

Ab AGP 8.1 können Bibliotheken multiple Variants veröffentlichen — alle Bibliotheksvarianten gleichzeitig in einem Maven-Repository veröffentlichen. Dies löst das Problem, wenn das App-Modul einen kostenpflichtigen Flavor verwendet, die Bibliothek aber nur für Free veröffentlicht ist. Multiple Variants Publishing (MVP) ermöglicht es dem abhängigen Projekt, die benötigte Variante automatisch auszuwählen. Um MVP zu aktivieren, fügen Sie publishing { multipleVariants { ... } } zur build.gradle der Bibliothek hinzu.

Filtern und Deaktivieren von Varianten

Dynamisches Filtern über CI/CD

Manchmal ist es notwendig, einige Build Variants zu deaktivieren — zum Beispiel, wenn die Kombination mockRelease keinen Sinn ergibt (Mock-Server sollte nicht in Produktion gehen). Gradle stellt variantFilter zur Verfügung — einen DSL-Block, in dem Sie die Eigenschaften jeder Variante überprüfen und sie über setIgnore(true) deaktivieren können. VariantFilter wird in der Konfigurationsphase vor der Aufgabenerstellung angewendet, sodass eine deaktivierte Variante keine Assemble- und Install-Aufgaben generiert.

Filtern ist auch nützlich, um Builds zu beschleunigen. Wenn ein Projekt 8 Varianten hat, ein Entwickler aber nur an einer arbeitet, durchlaufen die restlichen 7 Varianten trotzdem die Konfiguration. Bei Verwendung von variantFilter erstellen deaktivierte Varianten keine Aufgaben, was die Konfigurationszeit bei Projekten mit 6+ Flavor-Dimensionen um 30-50% reduziert. In CI/CD können Sie Varianten dynamisch über Kommandozeilenparameter -PbuildOnly=paidRelease filtern.

groovy
android {
    variantFilter { variant ->
        // Mock für Release und Demo für Production deaktivieren
        def names = variant.flavors*.name
        def isMock = names.contains("mock")
        def isDemo = names.contains("demo")
        def isRelease = variant.buildType.name == "release"

        if ((isMock && isRelease) || (isDemo && !isMock)) {
            variant.setIgnore(true)
        }
    }
}

// Dynamisches Filtern über Parameter
if (project.hasProperty("buildOnly")) {
    def target = project.property("buildOnly")
    android.variantFilter { variant ->
        variant.setIgnore(variant.name != target)
    }
}

Häufig gestellte Fragen

Wie viele Build Variants können erstellt werden?

Es gibt keine Grenze, aber Gradle erstellt das kartesische Produkt aller Flavors und Typen. Wenn Sie 3 Dimensionen mit jeweils 3 Flavors und 3 Build Types haben, erhalten Sie 27 Varianten. Zu viele Varianten verlangsamen die Konfiguration. Es wird empfohlen, nicht mehr als 10–12 Varianten in einem Modul zu haben.

Wozu werden flavorDimensions benötigt?

flavorDimensions gruppieren Product Flavors in unabhängige Achsen. Zum Beispiel die Dimension „Tier“ (Free, Paid) und die Dimension „Region“ (US, EU). Ohne Dimensionen gehören alle Flavors zu einer Achse, und Gradle wählt nur einen Flavor aus allen aus (Sie können Free+US und Paid+EU nicht als separate Varianten haben).

Wie überschreibt man applicationId für eine Variante?

Geben Sie im productFlavor- oder buildType-Block applicationId an. Zum Beispiel für die kostenlose Version: free { applicationId „com.example.app.free“ }. Verwenden Sie im Manifest ${applicationId} — Gradle setzt den Wert automatisch ein. Dadurch können beide Varianten auf einem Gerät installiert werden.

Kann man Build Variants in iOS verwenden?

In iOS ist das Äquivalent zu Build Variants die Kombination aus Scheme + Configuration. Xcode Schemes werden über Debug/Release-Konfigurationen mit verschiedenen Parametern eingerichtet. Für mehrere Versionen (Free/Paid) werden Build Configurations und Preprocessor Macros verwendet. In Android ist das Konzept formalisierter und in Gradle integriert.

Beeinflusst der Build Variant die APK-Größe?

Ja, jede Variante kann eine andere APK-Größe haben. Debug-Builds enthalten Debug-Informationen, SDK und nicht unterstützte Ressourcen. Release-Builds mit Minification und Resource Shrinking erzeugen die minimale Größe. Der Product Flavor beeinflusst ebenfalls die Größe: Eine kostenlose Version ohne kostenpflichtige Bibliotheken ist um die Größe dieser Bibliotheken kleiner als die kostenpflichtige Version.

Zusammenfassung

  • Build Variant — Kombination aus einem Build Type und einem Product Flavor, die die Build-Konfiguration definiert.
  • Build Type steuert den Kompilierungsmodus (Debug/Release/Staging), während Product Flavor die Produktversion (Free/Paid) steuert.
  • Source Sets ermöglichen das Überschreiben von Code, Ressourcen und Manifest für jede Build-Variante.
  • VariantFilter deaktiviert unnötige Kombinationen und beschleunigt die Gradle-Konfiguration um 30–50%.
  • Multi-Modul-Projekte erfordern Flavor-Synchronisation über alle Module oder Multiple Variants Publishing.
  • BuildConfigField und Source Sets sind zwei saubere Möglichkeiten, das Verhalten zwischen Varianten anzupassen.
  • Empfehlung: Erstellen Sie nicht mehr als 10–12 Varianten in einem Projekt; gruppieren Sie Dimensionen sinnvoll.

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch