Build Variant ve vývoji pro Android je kombinací build type a product flavor, která určuje, jak bude sestaven APK nebo AAB: s jakými parametry, zdroji a kódem. Každá varianta sestavení představuje samostatnou konfiguraci Gradle s vlastním applicationId, podpisovými klíči a zahrnutými závislostmi. Podle Google Android Developers, 2025 správné nastavení Build Variants zkracuje dobu sestavení až o 40% díky vyloučení nepotřebných zdrojů pro každou variantu. Systém variant sestavení je základem správy konfigurace v moderních Android projektech.
Hlavní body
Build Variant — je výsledkem kombinace jednoho Build Type a jednoho Product Flavor. Pokud v projektu není definován Product Flavor, Build Variant se shoduje s Build Type. Gradle automaticky generuje úplnou sadu variant jako kartézský součin všech FlavorDimensions, Product Flavors a Build Types. Například pro flavor free/paid a typy debug/release bude vytvořeno 8 variant: freeDebug, freeRelease, paidDebug, paidRelease.
Každý Build Variant dostává vlastní název ve formátu <Flavor><Type> s flavor velkým písmenem. Pro tuto variantu Gradle generuje samostatné úkoly: assembleFreeDebug, installFreeDebug, bundleFreeRelease. V Android Studio je přepínání mezi variantami dostupné přes panel Build Variants (View → Tool Windows → Build Variants). Výběr varianty ovlivňuje, který kód je kompilován, které zdroje jsou zahrnuty a který APK/AAB je vytvořen.
Systém Build Variants řeší tři klíčové úkoly: oddělení konfigurací pro různá prostředí (dev/staging/production), vytvoření více verzí aplikace (free/paid) a A/B testování sestavení. Bez Build Variants by vývojáři museli ručně přepínat příznaky a konfigurace, což vede k chybám lidského faktoru. Podle výzkumu Gradle Inc., 2024 zavádění Build Variants snižuje počet chyb sestavení o 60% v projektech se třemi a více prostředími nasazení.
AGP (Android Gradle Plugin) vypočítá všechny kombinace ve fázi konfigurace. Pokud má projekt dvě dimenze se dvěma a třemi flavor, Gradle vytvoří 2 × 2 × 3 = 12 kombinací, vynásobených počtem Build Types (obvykle 2). Každá kombinace dostává jedinečný název a sadu úkolů. AGP automaticky přidává source set pro každou variantu: src/freeDebug/, src/paidRelease/, stejně jako zobecněné src/free/ a src/debug/. Priorita čtení zdrojů: variant → flavor → type → main.
// Příklad: 4 Build Variants
// flavorDimensions "version", "server"
// version: demo, prod
// server: mock, live
// buildTypes: debug, release
// Celkem: 2 × 2 × 2 = 8 variant
android {
flavorDimensions "version", "server"
productFlavors {
demo { dimension "version" }
prod { dimension "version" }
mock { dimension "server" }
live { dimension "server" }
}
}
Build Type určuje, jak se aplikace sestavuje — s ladicími informacemi nebo bez, s optimalizací nebo bez, s jakým podpisem. Product Flavor určuje, co se sestavuje — kterou verzi produktu. Build Type — je mechanismus sestavení (debug, release, staging). Product Flavor — je varianta produktu (free, paid, enterprise, demo). Oba pojmy jsou ortogonální: libovolný Build Type lze aplikovat na libovolný Product Flavor.
Build Type ve výchozím nastavení zahrnuje debug (debuggable=true, minification=false, signing=debug.keystore) a release (debuggable=false, minification=true, signing=production.keystore). Product Flavor je ve výchozím nastavení jeden, beze jména (ve skutečnosti main source set). Vývojář může přidávat vlastní Build Types (např. „staging“ s debuggable=true a minification=true) a Product Flavors v libovolném počtu. Rozdíl spočívá také v tom, že Build Type nelze seskupovat do dimenzí, zatímco Product Flavor ano.
Klíčový praktický rozdíl: defaultConfig v build.gradle se vztahuje na všechny Variants, ale může být přepsán v productFlavors a buildTypes. BuildConfigField přidaný v buildType je viditelný ve všech flavor tohoto typu, a přidaný v productFlavor — ve všech typech tohoto flavor. Pokud je pole definováno jak tam, tak tam — prioritu má buildType (aplikuje se jako poslední v řetězci).
| Vlastnost | Build Type | Product Flavor |
|---|---|---|
| Účel | Jak sestavit | Co sestavit |
| Příklady | debug, release, staging | free, paid, demo, enterprise |
| Výchozí | debug + release | jeden (main) |
| Source Set | src/debug/, src/release/ | src/free/, src/paid/ |
| Dimenze | ne | flavorDimensions |
| Aplikace | po flavor, přepisuje | po defaultConfig |
| BuildConfigField | přepisuje flavor | přepisuje defaultConfig |
Nastavení Build Variants se provádí v bloku android souboru build.gradle na úrovni modulu. Nejprve se deklarují buildTypes s jejich parametry, poté flavorDimensions a productFlavors. Gradle automaticky vytváří varianty na základě těchto deklarací. Každá varianta dědí defaultConfig modulu a přepisuje určená pole. Pořadí deklarace ovlivňuje prioritu: buildTypes se aplikují po productFlavors.
Pro přístup ke konkrétnímu Build Variant ve skriptech Gradle se používá android.applicationVariants (pro modul app) nebo android.libraryVariants (pro knihovní modul). Toto je kolekce, přes kterou lze iterovat a měnit konfiguraci každé varianty v čase konfigurace. Například lze programově přidat buildConfigField pro všechny varianty obsahující slovo „demo”.
Android Gradle Plugin 8.x přidal podporu pro onVariants — čistší API pro konfiguraci variant prostřednictvím lambd. Staré API (variantOutput, variantFilter) je označeno jako zastaralé. Doporučuje se používat onVariants spolu s onEach pro knihovní moduly. Migrace z variantOutput na onVariants — doporučený krok při aktualizaci AGP ze 7.x na 8.x.
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)
}
}
Každý Build Variant dostává vlastní hierarchii source sets — adresářů se zdrojovým kódem, zdroji a manifestem. Source set se nachází v src/<variantName>/ (např. src/freeDebug/) a může obsahovat java/, res/, AndroidManifest.xml, assets/. Pokud soubor existuje v source set varianty, přepisuje soubor se stejným názvem z hlavního source set (src/main/). Pro zdroje funguje slučování, nikoli nahrazování — systém kombinuje zdroje ze všech aktivních source sets a dává prioritu variantě specifickým.
Source sets pro Build Variant se staví v řetězci: src/main/ → src/flavor/ → src/type/ → src/flavorType/. Například pro paidRelease se nejprve aplikuje main, poté paid, poté release, poté paidRelease. Každý následující source set přepisuje předchozí. To znamená, že src/release/res/values/strings.xml přepíše stejné řetězce z src/paid/, ale src/paid/release/res/ je ještě prioritnější.
Použití source sets pro varianty — doporučený způsob přizpůsobení zdrojů. Místo kontroly BuildConfig.FLAVOR v kódu a větvení logiky lze jednoduše umístit různé soubory do různých source sets. Například ikony pro free a paid verze se vkládají do src/free/res/ a src/paid/res/ a AndroidManifest s různými oprávněními — do src/free/AndroidManifest.xml a src/paid/AndroidManifest.xml. Je to čistší, rychlejší (zdroje se kompilují, nekontrolují se za běhu) a bezpečnější (placenou funkcionalitu nelze náhodně zapnout v bezplatné verzi kvůli chybě v kódu).
Ve vícemodulových projektech může mít každý modul (knihovna) vlastní Build Variants. AGP automaticky synchronizuje varianty: pokud modul app sestavuje paidRelease, všechny závislé knihovny se také sestavují ve svých variantách odpovídajících paidRelease. Problém nastává, když knihovna nemá product flavors, ale modul app ano — pak se knihovna sestavuje jednou (release nebo debug v závislosti na typu).
Pro knihovní moduly se Build Variant ve výchozím nastavení shoduje s Build Type modulu app, protože knihovny nemají product flavors. Pokud se knihovna musí přizpůsobit flavor modulu app, je třeba deklarovat stejné flavorDimensions a productFlavors v knihovně. AGP přiřazuje flavor podle úplné shody názvu. Gradle doporučuje synchronizovat flavor prostřednictvím konfigurace sestavení v kořenovém projektu pomocí subprojects nebo Convention Plugins.
Od AGP 8.1 mohou knihovny publikovat multiple variants — publikovat všechny varianty knihovny současně do maven repozitáře. To řeší problém, když modul app používá paid flavor, ale knihovna je publikována pouze pro free. Multiple variants publishing (MVP) umožňuje závislému projektu automaticky vybrat požadovanou variantu. Pro aktivaci MVP je třeba přidat publishing { multipleVariants { ... } } do build.gradle knihovny.
Někdy je nutné vypnout část Build Variants — například pokud kombinace mockRelease nedává smysl (mock server by se neměl dostat do produkce). Gradle poskytuje variantFilter — blok DSL, ve kterém lze zkontrolovat vlastnosti každé varianty a vypnout ji pomocí setIgnore(true). VariantFilter se aplikuje ve fázi konfigurace, před vytvořením úkolů, takže vypnutá varianta negeneruje úkoly assemble a install.
Filtrování je také užitečné pro zrychlení sestavení. Pokud má projekt 8 variant a vývojář pracuje pouze na jedné, zbývajících 7 variant stejně prochází konfigurací (configuration phase). Při použití variantFilter vypnuté varianty nevytvářejí úkoly, což zkracuje dobu konfigurace o 30-50% pro projekty se 6+ dimenzemi flavor. V CI/CD lze varianty dynamicky filtrovat pomocí parametrů příkazového řádku -PbuildOnly=paidRelease.
android {
variantFilter { variant ->
// Vypínáme mock pro release a demo pro production
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)
}
}
}
// Dynamické filtrování přes parametry
if (project.hasProperty("buildOnly")) {
def target = project.property("buildOnly")
android.variantFilter { variant ->
variant.setIgnore(variant.name != target)
}
}
Často kladené otázky
Neexistují žádná omezení, ale Gradle vytváří kartézský součin všech flavor a typů. Pokud máte 3 dimenze po 3 flavor a 3 build type — získáte 27 variant. Příliš mnoho variant zpomaluje konfiguraci. Doporučuje se maximálně 10-12 variant v jednom modulu.
flavorDimensions seskupují Product Flavors do nezávislých os. Například dimenze „tier“ (free, paid) a „region“ (us, eu). Bez dimenzí všechny flavor patří do jedné osy a Gradle vybere pouze jeden flavor ze všech (nelze mít free+us a paid+eu jako samostatné varianty).
V bloku productFlavor nebo buildType uveďte applicationId. Například pro free verzi: free { applicationId "com.example.app.free" }. V manifestu použijte ${applicationId} — Gradle automaticky dosadí hodnotu. To umožňuje nainstalovat obě varianty na jedno zařízení.
V iOS je ekvivalentem Build Variants kombinace Scheme + Configuration. Xcode Schemes se konfigurují pomocí konfigurací Debug/Release s různými parametry. Pro více verzí (free/paid) se používají Build Configurations a Preprocessor Macros. V Androidu je koncept formálnější a zabudovaný přímo v Gradle.
Ano, každá varianta může mít jinou velikost APK. Debug sestavení obsahují ladicí informace, SDK a nepodporované zdroje. Release sestavení s minifikací a zmenšováním zdrojů dávají minimální velikost. Product Flavor také ovlivňuje: free verze bez placených knihoven bude menší než paid verze o velikost těchto knihoven.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také