Build Variant — какво е, build type и product flavor в Android

Автор: IT Sectr Публикувано: 2026-05-30 Време за четене: 9 мин

Build Variant в разработката за Android е комбинация от build type и product flavor, която определя как ще бъде изграден APK или AAB: с какви параметри, ресурси и код. Всеки вариант на компилация представлява отделна Gradle конфигурация със собствен applicationId, ключове за подписване и включени зависимости. Според Google Android Developers, 2025, правилната настройка на Build Variants намалява времето за компилация с до 40% чрез изключване на ненужни ресурси за всеки вариант. Системата от варианти на компилация е основата на управлението на конфигурацията в съвременните Android проекти.

Основни точки

  • Build Variant — комбинация от един Build Type и един Product Flavor.
  • Build Type задава режим на компилация: debug (отстраняване на грешки) или release (публикуване).
  • Product Flavor определя версията на приложението: free, paid, demo, enterprise.
  • Gradle автоматично генерира задачи за всеки Build Variant, включително install и assemble.
  • Ресурси и код могат да бъдат презаписани за всеки вариант чрез съответните source sets.

Какво е Build Variant?

Build Variant — е резултат от комбинацията на един Build Type и един Product Flavor. Ако в проекта не е дефиниран Product Flavor, Build Variant съвпада с Build Type. Gradle автоматично генерира пълния набор от варианти като декартово произведение на всички FlavorDimensions, Product Flavors и Build Types. Например, за flavor free/paid и типовете debug/release ще бъдат създадени 8 варианта: freeDebug, freeRelease, paidDebug, paidRelease.

Всеки Build Variant получава собствено име във формат <Flavor><Type> с flavor с главна буква. За този вариант Gradle генерира отделни задачи: assembleFreeDebug, installFreeDebug, bundleFreeRelease. В Android Studio превключването между вариантите е достъпно чрез панела Build Variants (View → Tool Windows → Build Variants). Изборът на вариант влияе върху това кой код се компилира, кои ресурси се включват и кой APK/AAB се създава.

Системата Build Variants решава три ключови задачи: разделяне на конфигурациите за различни среди (dev/staging/production), създаване на множество версии на приложението (free/paid) и A/B тестване на компилации. Без Build Variants разработчиците биха трябвало ръчно да превключват флагове и конфигурации, което води до грешки от човешки фактор. Според изследване на Gradle Inc., 2024, внедряването на Build Variants намалява броя на грешките при компилация с 60% в проекти с три или повече среди за разполагане.

Как Gradle генерира варианти

AGP (Android Gradle Plugin) изчислява всички комбинации във фазата на конфигурация. Ако проектът има две измерения съответно с два и три flavor, Gradle ще създаде 2 × 2 × 3 = 12 комбинации, умножени по броя на Build Types (обикновено 2). Всяка комбинация получава уникално име и набор от задачи. AGP автоматично добавя source set за всеки вариант: src/freeDebug/, src/paidRelease/, както и обобщените src/free/ и src/debug/. Приоритет на четене на ресурси: variant → flavor → type → main.

groovy
// Пример: 4 Build Variants
// flavorDimensions "version", "server"
// version: demo, prod
// server: mock, live
// buildTypes: debug, release
// Общо: 2 × 2 × 2 = 8 варианта

android {
    flavorDimensions "version", "server"

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

Build Type и Product Flavor: разлики

Build Type определя как се компилира приложението — с информация за отстраняване на грешки или без, с оптимизация или без, с какво подписване. Product Flavor определя какво се компилира — коя версия на продукта. Build Type — е механизмът за компилация (debug, release, staging). Product Flavor — е вариантът на продукта (free, paid, enterprise, demo). И двете понятия са ортогонални: всеки Build Type може да се приложи към всеки Product Flavor.

Build Type по подразбиране включва debug (debuggable=true, minification=false, signing=debug.keystore) и release (debuggable=false, minification=true, signing=production.keystore). Product Flavor по подразбиране е един, без име (всъщност main source set). Разработчикът може да добавя свои Build Types (например, «staging» с debuggable=true и minification=true) и Product Flavors в произволен брой. Разликата се състои и в това, че Build Type не може да се групира в измерения, а Product Flavor може.

Ключовата практическа разлика: defaultConfig в build.gradle се прилага към всички Variants, но може да бъде презаписан в productFlavors и buildTypes. BuildConfigField, добавен в buildType, е видим във всички flavor от този тип, а добавен в productFlavor — във всички типове от този flavor. Ако полето е дефинирано и там, и там — приоритет има buildType (прилага се последен във веригата).

Сравнителна таблица

ХарактеристикаBuild TypeProduct Flavor
ПредназначениеКак да компилирамеКакво да компилираме
Примериdebug, release, stagingfree, paid, demo, enterprise
По подразбиранеdebug + releaseедин (main)
Source Setsrc/debug/, src/release/src/free/, src/paid/
ИзмерениянеflavorDimensions
Прилаганеслед flavor, презаписваслед defaultConfig
BuildConfigFieldпрезаписва flavorпрезаписва defaultConfig

Настройка на Build Variants в build.gradle

Приоритет на конфигурациите

Настройката на Build Variants се извършва в блока android на файла build.gradle на ниво модул. Първо се декларират buildTypes с техните параметри, след това flavorDimensions и productFlavors. Gradle автоматично създава варианти въз основа на тези декларации. Всеки вариант наследява defaultConfig на модула, презаписвайки определени полета. Редът на деклариране влияе на приоритета: buildTypes се прилагат след productFlavors.

За достъп до конкретен Build Variant в Gradle скриптове се използва android.applicationVariants (за модул app) или android.libraryVariants (за библиотечен модул). Това е колекция, която може да бъде итерирана и конфигурацията на всеки вариант може да бъде променяна по време на конфигурация. Например, може програмно да се добави buildConfigField за всички варианти, съдържащи думата «demo».

Android Gradle Plugin 8.x добави поддръжка за onVariants — по-чист API за настройка на варианти чрез ламбди. Старото API (variantOutput, variantFilter) е маркирано като остаряло. Препоръчва се използването на onVariants заедно с onEach за библиотечни модули. Миграцията от variantOutput към onVariants — препоръчителна стъпка при актуализиране на AGP от 7.x на 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 и презаписване на ресурси

Всеки Build Variant получава собствена йерархия от source sets — директории с изходен код, ресурси и манифест. Source set се намира в src/<variantName>/ (например, src/freeDebug/) и може да съдържа java/, res/, AndroidManifest.xml, assets/. Ако файл съществува в source set на варианта, той презаписва файла със същото име от основния source set (src/main/). За ресурси работи сливане, а не замяна — системата комбинира ресурси от всички активни source sets, давайки приоритет на специфичните за варианта.

Source sets за Build Variant се изграждат във верига: src/main/src/flavor/src/type/src/flavorType/. Например, за paidRelease първо се прилага main, след това paid, след това release, след това paidRelease. Всеки следващ source set презаписва предходния. Това означава, че src/release/res/values/strings.xml ще презапише същите низове от src/paid/, но src/paid/release/res/ е още по-приоритетен.

Използването на source sets за варианти — препоръчителният начин за персонализиране на ресурси. Вместо да проверявате BuildConfig.FLAVOR в кода и да разклонявате логиката, можете просто да поставите различни файлове в различни source sets. Например, иконите за free и paid версии се поставят съответно в src/free/res/ и src/paid/res/, а AndroidManifest с различни разрешения — в src/free/AndroidManifest.xml и src/paid/AndroidManifest.xml. Това е по-чисто, по-бързо (ресурсите се компилират, не се проверяват по време на изпълнение) и по-безопасно (не може случайно да се включи платена функционалност в безплатната версия поради грешка в кода).

Build Variant в мултимодулни проекти

В мултимодулни проекти всеки модул (библиотека) може да има свои Build Variants. AGP автоматично синхронизира вариантите: ако модулът app компилира paidRelease, всички зависими библиотеки също се компилират в техните варианти, съответстващи на paidRelease. Проблемът възниква, когато библиотеката няма product flavors, но модулът app има — тогава библиотеката се компилира веднъж (release или debug в зависимост от типа).

За библиотечни модули Build Variant по подразбиране съвпада с Build Type на модула app, тъй като библиотеките нямат product flavors. Ако библиотеката трябва да се адаптира към flavor на модула app, трябва да се декларират същите flavorDimensions и productFlavors в библиотеката. AGP съпоставя flavor по пълно съвпадение на името. Gradle препоръчва синхронизиране на flavor чрез конфигурацията за изграждане в основния проект с помощта на subprojects или Convention Plugins.

От AGP 8.1 нататък библиотеките могат да публикуват multiple variants — да публикуват всички варианти на библиотеката едновременно в maven хранилище. Това решава проблема, когато модулът app използва paid flavor, но библиотеката е публикувана само за free. Multiple variants publishing (MVP) позволява на зависимия проект автоматично да избере необходимия вариант. За активиране на MVP трябва да се добави publishing { multipleVariants { ... } } в build.gradle на библиотеката.

Филтриране и изключване на варианти

Динамично филтриране чрез CI/CD

Понякога е необходимо да се изключи част от Build Variants — например, ако комбинацията mockRelease няма смисъл (mock сървърът не трябва да достига до продукция). Gradle предоставя variantFilter — DSL блок, в който могат да се проверят свойствата на всеки вариант и да се изключи чрез setIgnore(true). VariantFilter се прилага във фазата на конфигурация, преди създаването на задачи, така че изключеният вариант не генерира задачи assemble и install.

Филтрирането е полезно и за ускоряване на компилацията. Ако проектът има 8 варианта и разработчикът работи само върху един, останалите 7 варианта все пак преминават през конфигурация (configuration phase). При използване на variantFilter изключените варианти не създават задачи, което намалява времето за конфигурация с 30-50% за проекти с 6+ flavor измерения. В CI/CD вариантите могат да бъдат динамично филтрирани чрез параметри на командния ред -PbuildOnly=paidRelease.

groovy
android {
    variantFilter { variant ->
        // Изключваме mock за release и demo за 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)
        }
    }
}

// Динамично филтриране чрез параметри
if (project.hasProperty("buildOnly")) {
    def target = project.property("buildOnly")
    android.variantFilter { variant ->
        variant.setIgnore(variant.name != target)
    }
}

Често задавани въпроси

Колко Build Variants могат да бъдат създадени?

Няма ограничения, но Gradle създава декартово произведение на всички flavor и типове. Ако имате 3 измерения с по 3 flavor и 3 build type — ще получите 27 варианта. Твърде много варианти забавят конфигурацията. Препоръчват се не повече от 10-12 варианта в един модул.

За какво служат flavorDimensions?

flavorDimensions групират Product Flavors в независими оси. Например, измерение «tier» (free, paid) и «region» (us, eu). Без измерения всички flavor принадлежат към една ос и Gradle ще избере само един flavor от всички (не можете да имате free+us и paid+eu като отделни варианти).

Как да презапиша applicationId за вариант?

В блока productFlavor или buildType посочете applicationId. Например, за free версия: free { applicationId "com.example.app.free" }. В манифеста използвайте ${applicationId} — Gradle автоматично ще замести стойността. Това позволява инсталиране на двата варианта на едно устройство.

Могат ли да се използват Build Variants в iOS?

В iOS аналогът на Build Variants е комбинацията Scheme + Configuration. Xcode Schemes се конфигурират чрез Debug/Release конфигурации с различни параметри. За множество версии (free/paid) се използват Build Configurations и Preprocessor Macros. В Android концепцията е по-формализирана и вградена в Gradle.

Build Variant влияе ли на размера на APK?

Да, всеки вариант може да има различен размер на APK. Debug компилациите включват информация за отстраняване на грешки, SDK и неподдържани ресурси. Release компилациите с минификация и намаляване на ресурсите дават минимален размер. Product Flavor също влияе: free версията без платени библиотеки ще бъде по-малка от paid версията с размера на тези библиотеки.

Резюме

  • Build Variant — комбинация от един Build Type и един Product Flavor, определяща конфигурацията на компилация.
  • Build Type управлява режима на компилация (debug/release/staging), а Product Flavor — версията на продукта (free/paid).
  • Source sets позволяват презаписване на код, ресурси и манифест за всеки вариант на компилация.
  • VariantFilter изключва ненужни комбинации, ускорявайки Gradle конфигурацията с 30-50%.
  • Мултимодулни проекти изискват синхронизиране на flavor през всички модули или multiple variants publishing.
  • BuildConfigField и source sets — два чисти начина за персонализиране на поведението между варианти.
  • Препоръка: не създавайте повече от 10-12 варианта в един проект, групирайте измеренията смислено.

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също