Build Variant — что это, build type и product flavor в Android

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

Build Variant в Android-разработке — это комбинация build type и product flavor, которая определяет, как будет собран APK или AAB: с какими параметрами, ресурсами и кодом. Каждый вариант сборки представляет собой отдельную конфигурацию Gradle со своим applicationId, signing-ключами и включёнными зависимостями. По данным 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 (или flavour). Если в проекте не определены Product Flavor, то Build Variant совпадает с Build Type. Gradle автоматически генерирует полный набор вариантов как декартово произведение всех FlavorDimensions, Product Flavors и Build Types. Например, для flavour free/paid и типов debug/release будет создано 4 варианта: 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 разработчикам пришлось бы вручную переключать флаги и конфигурации, что ведёт к ошибкам human factor. По данным исследования Gradle Inc., 2024, внедрение Build Variants снижает количество ошибок сборки на 60% в проектах с тремя и более средами развёртывания.

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

AGP (Android Gradle Plugin) вычисляет все комбинации на этапе configuration. Если в проекте два измерения с двумя и тремя 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 определяет как собирать приложение — с отладочной информацией или без, с optimise или без, с каким signing. 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) помечено как deprecated. Рекомендуется использовать onVariants вместе с onEach для библиотечных модулей. Migrate from variantOutput to onVariants — recommended step при обновлении 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/). Для ресурсов работает слияние, а не замена — система объединяет ресурсы из всех active source sets, отдавая приоритет variant-специфичным.

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. Например, icons для free и paid версий кладутся в src/free/res/ и src/paid/res/ соответственно, а AndroidManifest с разными permissions — в src/free/AndroidManifest.xml и src/paid/AndroidManifest.xml. Это чище, быстрее (ресурсы компилируются, а не проверяются в runtime) и безопаснее (нельзя случайно включить платную функциональность в бесплатной версии из-за бага в коде).

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 рекомендует синхронизировать flavors через build-конфигурацию в корневом проекте с помощью 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 не имеет смысла (мок-сервер не должен попадасть в продакшн). Gradle предоставляет variantFilter — DSL-блок, в котором можно проверять свойства каждого варианта и отключать его через setIgnore(true). VariantFilter применяется на этапе конфигурации, до создания задач, поэтому отключённый вариант не генерирует assemble и install задачи.

Фильтрация также полезна для ускорения сборки. Если в проекте 8 вариантов, а разработчик работает только над one, остальные 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 и unsupported resources. Release-сборки с minification и resource shrinking дают минимальный размер. 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 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также