Build Variant — wat is het, build type en product flavor in Android

Auteur: IT Sectr Gepubliceerd: 2026-05-30 Leestijd: 9 min

Build Variant in Android-ontwikkeling is een combinatie van build type en product flavor die bepaalt hoe APK of AAB wordt gebouwd: met welke parameters, bronnen en code. Elke compilatievariant is een aparte Gradle-configuratie met eigen applicationId, ondertekeningssleutels en opgenomen afhankelijkheden. Volgens Google Android Developers, 2025 vermindert correcte configuratie van Build Variants de compilatietijd met 40% door overbodige bronnen voor elke variant uit te sluiten. Het systeem van compilatievarianten vormt de basis van configuratiebeheer in moderne Android-projecten.

Belangrijkste punten

  • Build Variant — combinatie van één Build Type en één Product Flavor.
  • Build Type bepaalt de compilatiemodus: debug (foutopsporing) of release (uitgave).
  • Product Flavor definieert de versie van de app: free, paid, demo, enterprise.
  • Gradle genereert automatisch taken voor elke Build Variant, inclusief install en assemble.
  • Bronnen en code kunnen voor elke variant worden overschreven via bijbehorende source sets.

Wat is Build Variant?

Build Variant — is het resultaat van de combinatie van één Build Type en één Product Flavor. Als er geen Product Flavor in het project is gedefinieerd, valt Build Variant samen met Build Type. Gradle genereert automatisch de volledige set varianten als het cartesisch product van alle FlavorDimensions, Product Flavors en Build Types. Voor flavor free/paid en typen debug/release worden bijvoorbeeld 8 varianten aangemaakt: freeDebug, freeRelease, paidDebug, paidRelease.

Elke Build Variant krijgt een eigen naam in het formaat <Flavor><Type> met flavor in hoofdletters. Voor deze variant genereert Gradle afzonderlijke taken: assembleFreeDebug, installFreeDebug, bundleFreeRelease. In Android Studio is schakelen tussen varianten beschikbaar via het paneel Build Variants (View → Tool Windows → Build Variants). De keuze van variant beïnvloedt welke code wordt gecompileerd, welke bronnen worden opgenomen en welke APK/AAB wordt gemaakt.

Het Build Variants-systeem lost drie belangrijke taken op: scheiding van configuraties voor verschillende omgevingen (dev/staging/production), maken van meerdere versies van de app (free/paid) en A/B-testen van builds. Zonder Build Variants zouden ontwikkelaars handmatig vlaggen en configuraties moeten schakelen, wat leidt tot menselijke fouten. Volgens onderzoek van Gradle Inc., 2024 vermindert implementatie van Build Variants het aantal compilatiefouten met 60% in projecten met drie of meer implementatieomgevingen.

Hoe genereert Gradle varianten

AGP (Android Gradle Plugin) berekent alle combinaties in de configuratiefase. Als het project twee dimensies heeft met respectievelijk twee en drie flavor, maakt Gradle 2 × 2 × 3 = 12 combinaties, vermenigvuldigd met het aantal Build Types (meestal 2). Elke combinatie krijgt een unieke naam en set taken. AGP voegt automatisch een source set toe voor elke variant: src/freeDebug/, src/paidRelease/, en ook de gegeneraliseerde src/free/ en src/debug/. Prioriteit van bronnen lezen: variant → flavor → type → main.

groovy
// Voorbeeld: 4 Build Variants
// flavorDimensions "version", "server"
// version: demo, prod
// server: mock, live
// buildTypes: debug, release
// Totaal: 2 × 2 × 2 = 8 varianten

android {
    flavorDimensions "version", "server"

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

Build Type en Product Flavor: verschillen

Build Type bepaalt hoe de app wordt gecompileerd — met foutopsporingsinformatie of zonder, met optimalisatie of zonder, met welke ondertekening. Product Flavor bepaalt wat wordt gecompileerd — welke versie van het product. Build Type — is het compilatiemechanisme (debug, release, staging). Product Flavor — is de productvariant (free, paid, enterprise, demo). Beide concepten zijn orthogonaal: elke Build Type kan op elke Product Flavor worden toegepast.

Build Type standaard omvat debug (debuggable=true, minification=false, signing=debug.keystore) en release (debuggable=false, minification=true, signing=production.keystore). Product Flavor standaard is er één, zonder naam (feitelijk main source set). De ontwikkelaar kan eigen Build Types (bijv. „staging” met debuggable=true en minification=true) en Product Flavors in elk aantal toevoegen. Het verschil zit ook in het feit dat Build Type niet in dimensies kan worden gegroepeerd, maar Product Flavor wel.

Het belangrijkste praktische verschil: defaultConfig in build.gradle is van toepassing op alle Variants, maar kan worden overschreven in productFlavors en buildTypes. BuildConfigField toegevoegd in buildType is zichtbaar in alle flavor van dit type, en toegevoegd in productFlavor — in alle typen van deze flavor. Als het veld zowel daar als hier is gedefinieerd — heeft buildType prioriteit (wordt als laatste in de keten toegepast).

Vergelijkingstabel

EigenschapBuild TypeProduct Flavor
DoelHoe compilerenWat compileren
Voorbeeldendebug, release, stagingfree, paid, demo, enterprise
Standaarddebug + releaseéén (main)
Source Setsrc/debug/, src/release/src/free/, src/paid/
DimensiesneeflavorDimensions
Toepassingna flavor, overschrijftna defaultConfig
BuildConfigFieldoverschrijft flavoroverschrijft defaultConfig

Build Variants configureren in build.gradle

Prioriteit van configuraties

Het configureren van Build Variants gebeurt in het android-blok van het build.gradle-bestand op moduleniveau. Eerst worden buildTypes met hun parameters gedeclareerd, daarna flavorDimensions en productFlavors. Gradle maakt automatisch varianten op basis van deze declaraties. Elke variant erft defaultConfig van de module en overschrijft specifieke velden. De declaratievolgorde beïnvloedt de prioriteit: buildTypes worden toegepast na productFlavors.

Voor toegang tot een specifieke Build Variant in Gradle-scripts wordt android.applicationVariants (voor app-module) of android.libraryVariants (voor bibliotheekmodule) gebruikt. Dit is een collectie waarover kan worden geïtereerd en de configuratie van elke variant kan worden gewijzigd tijdens de configuratiefase. Zo kan bijvoorbeeld programmatisch buildConfigField worden toegevoegd aan alle varianten die het woord „demo” bevatten.

Android Gradle Plugin 8.x heeft ondersteuning toegevoegd voor onVariants — een schonere API voor het configureren van varianten via lambda's. De oude API (variantOutput, variantFilter) is gemarkeerd als verouderd. Het wordt aanbevolen om onVariants samen met onEach te gebruiken voor bibliotheekmodules. Migratie van variantOutput naar onVariants — aanbevolen stap bij bijwerken van AGP van 7.x naar 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 en bronnen overschrijven

Elke Build Variant krijgt eigen hiërarchie van source sets — mappen met broncode, bronnen en manifest. Source set bevindt zich in src/<variantName>/ (bijv. src/freeDebug/) en kan java/, res/, AndroidManifest.xml, assets/ bevatten. Als een bestand bestaat in source set van de variant, overschrijft het het bestand met dezelfde naam uit de hoofd-source set (src/main/). Voor bronnen werkt samenvoegen, niet vervangen — het systeem combineert bronnen uit alle actieve source sets en geeft prioriteit aan variantspecifieke.

Source sets voor Build Variant worden in een keten gebouwd: src/main/src/flavor/src/type/src/flavorType/. Bijvoorbeeld, voor paidRelease wordt eerst main toegepast, dan paid, dan release, dan paidRelease. Elke volgende source set overschrijft de vorige. Dit betekent dat src/release/res/values/strings.xml dezelfde strings uit src/paid/ overschrijft, maar src/paid/release/res/ is nog prioriteitrijker.

Source sets gebruiken voor varianten — de aanbevolen manier om bronnen aan te passen. In plaats van BuildConfig.FLAVOR in code te controleren en logica te vertakken, kunnen verschillende bestanden eenvoudig in verschillende source sets worden geplaatst. Pictogrammen voor free- en paid-versies worden bijvoorbeeld respectievelijk in src/free/res/ en src/paid/res/ geplaatst, en AndroidManifest met verschillende machtigingen — in src/free/AndroidManifest.xml en src/paid/AndroidManifest.xml. Dit is schoner, sneller (bronnen worden gecompileerd, niet gecontroleerd in runtime) en veiliger (men kan niet per ongeluk betaalde functionaliteit in de gratis versie inschakelen door een bug in de code).

Build Variant in multi-module projecten

In multi-module projecten kan elke module (bibliotheek) eigen Build Variants hebben. AGP synchroniseert automatisch varianten: als de app-module paidRelease compileert, worden alle afhankelijke bibliotheken ook gecompileerd in hun varianten die overeenkomen met paidRelease. Het probleem ontstaat wanneer de bibliotheek geen product flavors heeft, maar de app-module wel — dan wordt de bibliotheek eenmalig gecompileerd (release of debug afhankelijk van het type).

Voor bibliotheekmodules valt Build Variant standaard samen met Build Type van de app-module, omdat bibliotheken geen product flavors hebben. Als de bibliotheek moet aanpassen aan flavor van de app-module, moeten dezelfde flavorDimensions en productFlavors in de bibliotheek worden gedeclareerd. AGP matcht flavor op volledige naamovereenkomst. Gradle raadt aan om flavors te synchroniseren via de build-configuratie in het root-project met subprojects of Convention Plugins.

Vanaf AGP 8.1 kunnen bibliotheken multiple variants publiceren — alle varianten van de bibliotheek tegelijkertijd in een maven-repository publiceren. Dit lost het probleem op wanneer de app-module paid flavor gebruikt, maar de bibliotheek alleen voor free is gepubliceerd. Multiple variants publishing (MVP) stelt het afhankelijke project in staat automatisch de benodigde variant te selecteren. Om MVP in te schakelen, moet publishing { multipleVariants { ... } } worden toegevoegd aan build.gradle van de bibliotheek.

Filteren en uitschakelen van varianten

Dynamisch filteren via CI/CD

Soms is het nodig om een deel van Build Variants uit te schakelen — bijvoorbeeld als de combinatie mockRelease geen zin heeft (mock-server mag niet in productie komen). Gradle biedt variantFilter — een DSL-blok waarin de eigenschappen van elke variant kunnen worden gecontroleerd en uitgeschakeld via setIgnore(true). VariantFilter wordt toegepast in de configuratiefase, vóór het aanmaken van taken, dus een uitgeschakelde variant genereert geen assemble- en install-taken.

Filteren is ook nuttig om compilatie te versnellen. Als het project 8 varianten heeft en de ontwikkelaar werkt slechts aan één, doorlopen de overige 7 varianten toch de configuratie (configuration phase). Bij gebruik van variantFilter creëren uitgeschakelde varianten geen taken, wat de configuratietijd met 30-50% vermindert voor projecten met 6+ flavordimensies. In CI/CD kunnen varianten dynamisch worden gefilterd via commandoregelparameters -PbuildOnly=paidRelease.

groovy
android {
    variantFilter { variant ->
        // Zet mock uit voor release en demo voor productie
        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)
        }
    }
}

// Dynamisch filteren via parameters
if (project.hasProperty("buildOnly")) {
    def target = project.property("buildOnly")
    android.variantFilter { variant ->
        variant.setIgnore(variant.name != target)
    }
}

Veelgestelde vragen

Hoeveel Build Variants kunnen worden aangemaakt?

Er zijn geen beperkingen, maar Gradle maakt het cartesisch product van alle flavors en typen. Als je 3 dimensies met 3 flavors en 3 build types hebt — krijg je 27 varianten. Te veel varianten vertragen de configuratie. Aanbevolen wordt niet meer dan 10-12 varianten in één module.

Waar zijn flavorDimensions voor nodig?

flavorDimensions groeperen Product Flavors in onafhankelijke assen. Bijvoorbeeld, dimensie „tier” (free, paid) en „region” (us, eu). Zonder dimensies behoren alle flavors tot één as en Gradle selecteert slechts één flavor uit alle (men kan free+us en paid+eu niet als aparte varianten hebben).

Hoe overschrijf ik applicationId voor een variant?

Specificeer in het productFlavor- of buildType-blok applicationId. Bijvoorbeeld voor de free-versie: free { applicationId "com.example.app.free" }. Gebruik in het manifest ${applicationId} — Gradle vult automatisch de waarde in. Dit maakt het mogelijk beide varianten op één apparaat te installeren.

Kunnen Build Variants worden gebruikt in iOS?

In iOS is het equivalent van Build Variants de combinatie Scheme + Configuration. Xcode Schemes worden geconfigureerd via Debug/Release-configuraties met verschillende parameters. Voor meerdere versies (free/paid) worden Build Configurations en Preprocessor Macros gebruikt. Op Android is het concept strenger geformaliseerd en ingebouwd in Gradle.

Beïnvloedt Build Variant de APK-grootte?

Ja, elke variant kan een andere APK-grootte hebben. Debug-builds bevatten foutopsporingsinformatie, SDK en niet-ondersteunde bronnen. Release-builds met minificatie en resource shrinking geven minimale grootte. Product Flavor heeft ook invloed: de free-versie zonder betaalde bibliotheken zal kleiner zijn dan de paid-versie met de grootte van deze bibliotheken.

Samenvatting

  • Build Variant — combinatie van één Build Type en één Product Flavor die de compilatieconfiguratie bepaalt.
  • Build Type beheert de compilatiemodus (debug/release/staging) en Product Flavor de productversie (free/paid).
  • Source sets maken het mogelijk code, bronnen en manifest voor elke compilatievariant te overschrijven.
  • VariantFilter schakelt onnodige combinaties uit en versnelt Gradle-configuratie met 30-50%.
  • Multi-module projecten vereisen synchronisatie van flavors via alle modules of multiple variants publishing.
  • BuildConfigField en source sets — twee schone manieren om gedrag tussen varianten aan te passen.
  • Aanbeveling: maak niet meer dan 10-12 varianten in één project, groepeer dimensies zinvol.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook