Build Variant — ce este, build type și product flavor în Android

Autor: IT Sectr Publicat: 2026-05-30 Timp de citire: 9 min

Build Variant în dezvoltarea Android este o combinație între build type și product flavor care determină cum va fi construit APK-ul sau AAB-ul: cu ce parametri, resurse și cod. Fiecare variantă de compilare reprezintă o configurație separată Gradle cu propriul applicationId, chei de semnare și dependențe incluse. Conform Google Android Developers, 2025, configurarea corectă a Build Variants reduce timpul de compilare cu 40% prin excluderea resurselor inutile pentru fiecare variantă. Sistemul de variante de compilare stă la baza managementului configurației în proiectele Android moderne.

Principalele puncte

  • Build Variant — combinația unui Build Type și a unui Product Flavor.
  • Build Type stabilește modul de compilare: debug (depanare) sau release (lansare).
  • Product Flavor definește versiunea aplicației: free, paid, demo, enterprise.
  • Gradle generează automat sarcini pentru fiecare Build Variant, inclusiv install și assemble.
  • Resursele și codul pot fi suprascrise pentru fiecare variantă prin source sets corespunzătoare.

Ce este Build Variant?

Build Variant — este rezultatul combinării unui Build Type și a unui Product Flavor. Dacă în proiect nu sunt definite Product Flavor, Build Variant coincide cu Build Type. Gradle generează automat setul complet de variante ca produs cartezian al tuturor FlavorDimensions, Product Flavors și Build Types. De exemplu, pentru flavor free/paid și tipurile debug/release se vor crea 8 variante: freeDebug, freeRelease, paidDebug, paidRelease.

Fiecare Build Variant primește propriul nume în formatul <Flavor><Type> cu flavor cu literă mare. Pentru această variantă, Gradle generează sarcini separate: assembleFreeDebug, installFreeDebug, bundleFreeRelease. În Android Studio, comutarea între variante este disponibilă prin panoul Build Variants (View → Tool Windows → Build Variants). Selectarea variantei influențează ce cod este compilat, ce resurse sunt incluse și ce APK/AAB este creat.

Sistemul Build Variants rezolvă trei sarcini cheie: separarea configurațiilor pentru diferite medii (dev/staging/production), crearea mai multor versiuni ale aplicației (free/paid) și testarea A/B a compilărilor. Fără Build Variants, dezvoltatorii ar trebui să comute manual flagurile și configurațiile, ceea ce duce la erori de factor uman. Conform cercetării Gradle Inc., 2024, implementarea Build Variants reduce numărul erorilor de compilare cu 60% în proiecte cu trei sau mai multe medii de implementare.

Cum generează Gradle variantele

AGP (Android Gradle Plugin) calculează toate combinațiile în faza de configurare. Dacă proiectul are două dimensiuni cu două și, respectiv, trei flavor, Gradle va crea 2 × 2 × 3 = 12 combinații, înmulțite cu numărul de Build Types (de obicei 2). Fiecare combinație primește un nume unic și un set de sarcini. AGP adaugă automat un source set pentru fiecare variantă: src/freeDebug/, src/paidRelease/, precum și cele generalizate src/free/ și src/debug/. Prioritatea citirii resurselor: variant → flavor → type → main.

groovy
// Exemplu: 4 Build Variants
// flavorDimensions "version", "server"
// version: demo, prod
// server: mock, live
// buildTypes: debug, release
// Total: 2 × 2 × 2 = 8 variante

android {
    flavorDimensions "version", "server"

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

Build Type și Product Flavor: diferențe

Build Type determină cum se compilează aplicația — cu informații de depanare sau fără, cu optimizare sau fără, cu ce semnare. Product Flavor determină ce se compilează — ce versiune a produsului. Build Type — este mecanismul de compilare (debug, release, staging). Product Flavor — este varianta produsului (free, paid, enterprise, demo). Ambele concepte sunt ortogonale: orice Build Type poate fi aplicat oricărui Product Flavor.

Build Type implicit include debug (debuggable=true, minification=false, signing=debug.keystore) și release (debuggable=false, minification=true, signing=production.keystore). Product Flavor implicit este unul singur, fără nume (de fapt main source set). Dezvoltatorul poate adăuga propriile Build Types (de exemplu, „staging” cu debuggable=true și minification=true) și Product Flavors în orice număr. Diferența constă și în faptul că Build Type nu poate fi grupat în dimensiuni, iar Product Flavor — poate.

Diferența practică cheie: defaultConfig în build.gradle se aplică tuturor Variants, dar poate fi suprascris în productFlavors și buildTypes. BuildConfigField adăugat în buildType este vizibil în toate flavorurile acestui tip, iar cel adăugat în productFlavor — în toate tipurile acestui flavor. Dacă câmpul este definit și acolo, și acolo — prioritate are buildType (se aplică ultimul în lanț).

Tabel comparativ

CaracteristicăBuild TypeProduct Flavor
ScopCum să compileziCe să compilezi
Exempledebug, release, stagingfree, paid, demo, enterprise
Implicitdebug + releaseunul (main)
Source Setsrc/debug/, src/release/src/free/, src/paid/
DimensiuninuflavorDimensions
Aplicaredupă flavor, suprascriedupă defaultConfig
BuildConfigFieldsuprascrie flavorsuprascrie defaultConfig

Configurarea Build Variants în build.gradle

Prioritatea configurațiilor

Configurarea Build Variants se realizează în blocul android al fișierului build.gradle la nivel de modul. Mai întâi se declară buildTypes cu parametrii lor, apoi flavorDimensions și productFlavors. Gradle creează automat variante pe baza acestor declarații. Fiecare variantă moștenește defaultConfig al modulului, suprascriind câmpurile specificate. Ordinea declarației influențează prioritatea: buildTypes se aplică după productFlavors.

Pentru accesul la un Build Variant specific în scripturile Gradle se folosește android.applicationVariants (pentru modulul app) sau android.libraryVariants (pentru modulul de bibliotecă). Aceasta este o colecție peste care se poate itera și modifica configurația fiecărei variante în timpul configurației. De exemplu, se poate adăuga programatic buildConfigField pentru toate variantele care conțin cuvântul „demo”.

Android Gradle Plugin 8.x a adăugat suport pentru onVariants — o API mai curată pentru configurarea variantelor prin lambda. API veche (variantOutput, variantFilter) este marcată ca deprecată. Se recomandă utilizarea onVariants împreună cu onEach pentru modulele bibliotecă. Migrarea de la variantOutput la onVariants — pas recomandat la actualizarea AGP de la 7.x la 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 și suprascrierea resurselor

Fiecare Build Variant primește propria ierarhie de source sets — directoare cu cod sursă, resurse și manifest. Source set se localizează în src/<variantName>/ (de exemplu, src/freeDebug/) și poate conține java/, res/, AndroidManifest.xml, assets/. Dacă un fișier există în source set-ul variantei, acesta suprascrie fișierul cu același nume din source set-ul principal (src/main/). Pentru resurse funcționează îmbinarea, nu înlocuirea — sistemul combină resursele din toate source sets active, acordând prioritate celor specifice variantei.

Source sets pentru Build Variant se construiesc în lanț: src/main/src/flavor/src/type/src/flavorType/. De exemplu, pentru paidRelease se aplică mai întâi main, apoi paid, apoi release, apoi paidRelease. Fiecare source set următor îl suprascrie pe precedentul. Aceasta înseamnă că src/release/res/values/strings.xml va suprascrie aceleași șiruri din src/paid/, dar src/paid/release/res/ este și mai prioritar.

Utilizarea source sets pentru variante — modul recomandat de personalizare a resurselor. În loc să verifici BuildConfig.FLAVOR în cod și să ramifici logica, poți pur și simplu plasa diferite fișiere în diferite source sets. De exemplu, pictogramele pentru versiunile free și paid se pun în src/free/res/ și respectiv src/paid/res/, iar AndroidManifest cu permisiuni diferite — în src/free/AndroidManifest.xml și src/paid/AndroidManifest.xml. Este mai curat, mai rapid (resursele se compilează, nu se verifică în runtime) și mai sigur (nu se poate activa accidental funcționalitatea plătită în versiunea gratuită din cauza unei erori în cod).

Build Variant în proiecte multi-modul

În proiectele multi-modul, fiecare modul (bibliotecă) poate avea propriile Build Variants. AGP sincronizează automat variantele: dacă modulul app compilează paidRelease, toate bibliotecile dependente sunt și ele compilate în variantele corespunzătoare paidRelease. Problema apare când biblioteca nu are product flavors, dar modulul app are — atunci biblioteca este compilată o singură dată (release sau debug în funcție de tip).

Pentru modulele bibliotecă, Build Variant implicit coincide cu Build Type al modulului app, deoarece bibliotecile nu au product flavors. Dacă biblioteca trebuie să se adapteze la flavorul modulului app, este necesar să se declare aceleași flavorDimensions și productFlavors în bibliotecă. AGP potrivește flavorul după coincidența completă a numelui. Gradle recomandă sincronizarea flavorurilor prin configurarea de compilare în proiectul rădăcină cu ajutorul subprojects sau Convention Plugins.

Începând cu AGP 8.1, bibliotecile pot publica multiple variants — publică toate variantele bibliotecii simultan în depozitul maven. Aceasta rezolvă problema când modulul app folosește flavorul paid, dar biblioteca este publicată doar pentru free. Multiple variants publishing (MVP) permite proiectului dependent să selecteze automat varianta necesară. Pentru activarea MVP, trebuie adăugat publishing { multipleVariants { ... } } în build.gradle al bibliotecii.

Filtrarea și dezactivarea variantelor

Filtrarea dinamică prin CI/CD

Uneori este necesară dezactivarea unei părți din Build Variants — de exemplu, dacă combinația mockRelease nu are sens (serverul mock nu trebuie să ajungă în producție). Gradle oferă variantFilter — un bloc DSL în care se pot verifica proprietățile fiecărei variante și se poate dezactiva prin setIgnore(true). VariantFilter se aplică în faza de configurare, înainte de crearea sarcinilor, astfel încât varianta dezactivată nu generează sarcini assemble și install.

Filtrarea este utilă și pentru accelerarea compilării. Dacă proiectul are 8 variante, iar dezvoltatorul lucrează doar la una, celelalte 7 variante trec oricum prin configurare (configuration phase). Folosind variantFilter, variantele dezactivate nu creează sarcini, ceea ce reduce timpul de configurare cu 30-50% pentru proiecte cu 6+ dimensiuni de flavor. În CI/CD se pot filtra dinamic variantele prin parametri din linia de comandă -PbuildOnly=paidRelease.

groovy
android {
    variantFilter { variant ->
        // Dezactivăm mock pentru release și demo pentru producție
        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)
        }
    }
}

// Filtrare dinamică prin parametri
if (project.hasProperty("buildOnly")) {
    def target = project.property("buildOnly")
    android.variantFilter { variant ->
        variant.setIgnore(variant.name != target)
    }
}

Întrebări frecvente

Câte Build Variants se pot crea?

Nu există limitări, dar Gradle creează produsul cartezian al tuturor flavorurilor și tipurilor. Dacă ai 3 dimensiuni a câte 3 flavor și 3 build type — vei obține 27 de variante. Prea multe variante încetinesc configurarea. Se recomandă nu mai mult de 10-12 variante într-un singur modul.

De ce sunt necesare flavorDimensions?

flavorDimensions grupează Product Flavors în axe independente. De exemplu, dimensiunea „tier” (free, paid) și „region” (us, eu). Fără dimensiuni, toate flavorurile aparțin unei singure axe și Gradle va selecta doar un flavor din toate (nu se pot avea free+us și paid+eu ca variante separate).

Cum se suprascrie applicationId pentru o variantă?

În blocul productFlavor sau buildType se specifică applicationId. De exemplu, pentru versiunea free: free { applicationId "com.example.app.free" }. În manifest se folosește ${applicationId} — Gradle va înlocui automat valoarea. Aceasta permite instalarea ambelor variante pe același dispozitiv.

Se pot folosi Build Variants în iOS?

În iOS, analogul Build Variants este combinația Scheme + Configuration. Xcode Schemes se configurează prin configurațiile Debug/Release cu diferiți parametri. Pentru mai multe versiuni (free/paid) se folosesc Build Configurations și Preprocessor Macros. Pe Android, conceptul este formalizat mai riguros și încorporat în Gradle.

Build Variant influențează dimensiunea APK-ului?

Da, fiecare variantă poate avea o dimensiune diferită a APK-ului. Compilările debug includ informații de depanare, SDK și resurse nesuportate. Compilările release cu minificare și reducere a resurselor oferă dimensiunea minimă. Product Flavor influențează și el: versiunea free fără biblioteci plătite va fi mai mică decât versiunea paid cu dimensiunea acestor biblioteci.

Concluzii

  • Build Variant — combinația unui Build Type și a unui Product Flavor care determină configurația de compilare.
  • Build Type gestionează modul de compilare (debug/release/staging), iar Product Flavor — versiunea produsului (free/paid).
  • Source sets permit suprascrierea codului, resurselor și manifestului pentru fiecare variantă de compilare.
  • VariantFilter dezactivează combinațiile inutile, accelerând configurarea Gradle cu 30-50%.
  • Proiectele multi-modul necesită sincronizarea flavorurilor prin toate modulele sau multiple variants publishing.
  • BuildConfigField și source sets — două metode curate de personalizare a comportamentului între variante.
  • Recomandare: nu crea mai mult de 10-12 variante într-un singur proiect, grupează dimensiunile într-un mod semnificativ.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și