Build Variant — o que é build type e product flavor no Android

Autor: IT Sectr Publicado: 2026-05-30 Tempo de leitura: 9 min

Um Build Variant no desenvolvimento Android é uma combinação de um build type e um product flavor que determina como um APK ou AAB será compilado: com quais parâmetros, recursos e código. Cada variante de compilação representa uma configuração separada do Gradle com seu próprio applicationId, chaves de assinatura e dependências incluídas. De acordo com Google Android Developers, 2025, a configuração adequada de Build Variants reduz o tempo de compilação em até 40% ao excluir recursos desnecessários para cada variante. O sistema de variantes de compilação é a base do gerenciamento de configuração em projetos Android modernos.

Pontos Principais

  • Build Variant — combinação de um Build Type e um Product Flavor.
  • Build Type define o modo de compilação: debug ou release.
  • Product Flavor define a versão do app: free, paid, demo, enterprise.
  • Gradle gera automaticamente tarefas para cada Build Variant, incluindo install e assemble.
  • Recursos e código podem ser sobrescritos para cada variante através dos source sets correspondentes.

O que é um Build Variant?

Build Variant é o resultado da combinação de um Build Type e um Product Flavor. Se nenhum Product Flavor for definido no projeto, o Build Variant corresponde ao Build Type. O Gradle gera automaticamente o conjunto completo de variantes como o produto cartesiano de todos os FlavorDimensions, Product Flavors e Build Types. Por exemplo, para os flavors free/paid e os tipos debug/release, serão criadas 4 variantes: freeDebug, freeRelease, paidDebug, paidRelease.

Cada Build Variant recebe seu próprio nome no formato <Flavor><Type> com o flavor em maiúsculo. O Gradle gera tarefas separadas para esta variante: assembleFreeDebug, installFreeDebug, bundleFreeRelease. No Android Studio, a alternância entre variantes está disponível através do painel Build Variants (View → Tool Windows → Build Variants). A seleção de uma variante afeta qual código é compilado, quais recursos são incluídos e qual APK/AAB é produzido.

O sistema de Build Variants resolve três tarefas principais: separar configurações para diferentes ambientes (dev/staging/production), criar múltiplas versões de um app (free/paid) e testar A/B de compilações. Sem Build Variants, os desenvolvedores teriam que alternar manualmente flags e configurações, levando a erros de fator humano. De acordo com um estudo da Gradle Inc., 2024, a implementação de Build Variants reduz erros de compilação em 60% em projetos com três ou mais ambientes de implantação.

Como o Gradle gera variantes

AGP (Android Gradle Plugin) calcula todas as combinações na fase de configuração. Se um projeto tem duas dimensões com dois e três flavors respectivamente, o Gradle criará 2 × 2 × 3 = 12 combinações, multiplicadas pelo número de Build Types (geralmente 2). Cada combinação recebe um nome único e um conjunto de tarefas. O AGP adiciona automaticamente um source set para cada variante: src/freeDebug/, src/paidRelease/, bem como os generalizados src/free/ e src/debug/. Prioridade de leitura de recursos: variant → flavor → type → main.

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

android {
    flavorDimensions "version", "server"

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

Build Type e Product Flavor: Diferenças

Build Type define como compilar o aplicativo — com ou sem informações de depuração, com ou sem otimização, com qual assinatura. Product Flavor define o que compilar — qual versão do produto. Build Type é um mecanismo de compilação (debug, release, staging). Product Flavor é uma variante de produto (free, paid, enterprise, demo). Ambos os conceitos são ortogonais: qualquer Build Type pode ser aplicado a qualquer Product Flavor.

Os Build Types padrão incluem debug (debuggable=true, minification=false, signing=debug.keystore) e release (debuggable=false, minification=true, signing=production.keystore). O Product Flavor padrão é um, sem nome (efetivamente o source set main). Os desenvolvedores podem adicionar seus próprios Build Types (por exemplo, “staging” com debuggable=true e minification=true) e qualquer número de Product Flavors. Outra diferença é que Build Types não podem ser agrupados em dimensões, mas Product Flavors podem.

A diferença prática principal: defaultConfig no build.gradle se aplica a todos os Variants, mas pode ser sobrescrito em productFlavors e buildTypes. Um BuildConfigField adicionado a um buildType é visível em todos os flavors desse tipo, enquanto um adicionado a um productFlavor é visível em todos os tipos desse flavor. Se um campo for definido em ambos, o buildType tem prioridade (ele é aplicado por último na cadeia).

Tabela Comparativa

CaracterísticaBuild TypeProduct Flavor
PropósitoComo compilarO que compilar
Exemplosdebug, release, stagingfree, paid, demo, enterprise
Padrãodebug + releaseum (main)
Source Setsrc/debug/, src/release/src/free/, src/paid/
DimensõesnãoflavorDimensions
Ordem de aplicaçãoapós flavor, sobrescreveapós defaultConfig
BuildConfigFieldsobrescreve flavorsobrescreve defaultConfig

Configurando Build Variants no build.gradle

Prioridade de Configuração

A configuração de Build Variants é feita no bloco android do arquivo build.gradle no nível do módulo. Primeiro, os buildTypes são declarados com seus parâmetros, depois flavorDimensions e productFlavors. O Gradle cria automaticamente as variantes com base nessas declarações. Cada variante herda o defaultConfig do módulo, sobrescrevendo os campos especificados. A ordem de declaração afeta a prioridade: os buildTypes são aplicados após os productFlavors.

Para acessar um Build Variant específico em scripts do Gradle, use android.applicationVariants (para módulos app) ou android.libraryVariants (para módulos de biblioteca). Esta é uma coleção que pode ser iterada para modificar a configuração de cada variante em tempo de configuração. Por exemplo, você pode adicionar programaticamente buildConfigField para todas as variantes que contenham a palavra “demo”.

O Android Gradle Plugin 8.x adicionou suporte para onVariants — uma API mais limpa para configurar variantes via lambdas. A API antiga (variantOutput, variantFilter) está marcada como obsoleta. Recomenda-se usar onVariants junto com onEach para módulos de biblioteca. Migrar de variantOutput para onVariants é uma etapa recomendada ao atualizar o AGP de 7.x para 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 e Substituição de Recursos

Cada Build Variant recebe sua própria hierarquia de source sets — diretórios com código fonte, recursos e manifesto. Um source set está localizado em src/<variantName>/ (por exemplo, src/freeDebug/) e pode conter java/, res/, AndroidManifest.xml, assets/. Se um arquivo existir no source set da variante, ele sobrescreve o arquivo com o mesmo nome do source set principal (src/main/). Para recursos, ocorre uma mesclagem em vez de substituição — o sistema mescla recursos de todos os source sets ativos, dando prioridade aos específicos da variante.

Os source sets para um Build Variant são construídos em cadeia: src/main/src/flavor/src/type/src/flavorType/. Por exemplo, para paidRelease, main é aplicado primeiro, depois paid, depois release, depois paidRelease. Cada source set subsequente sobrescreve o anterior. Isso significa que src/release/res/values/strings.xml sobrescreverá as mesmas strings de src/paid/, mas src/paidRelease/res/ tem prioridade ainda maior.

Usar source sets para variantes é a maneira recomendada de personalizar recursos. Em vez de verificar BuildConfig.FLAVOR no código e ramificar a lógica, você pode simplesmente colocar arquivos diferentes em source sets diferentes. Por exemplo, ícones para as versões free e paid vão em src/free/res/ e src/paid/res/ respectivamente, e o AndroidManifest com diferentes permissões vai em src/free/AndroidManifest.xml e src/paid/AndroidManifest.xml. Isso é mais limpo, mais rápido (os recursos são compilados, não verificados em tempo de execução) e mais seguro (você não pode incluir acidentalmente funcionalidade paga na versão gratuita devido a um bug no código).

Build Variant em Projetos Multimódulo

Em projetos multimódulo, cada módulo (biblioteca) pode ter seus próprios Build Variants. O AGP sincroniza automaticamente as variantes: se o módulo app compila paidRelease, todas as bibliotecas dependentes também são compiladas em suas variantes correspondentes a paidRelease. Surge um problema quando uma biblioteca não tem product flavors, mas o módulo app tem — então a biblioteca é compilada uma vez (release ou debug dependendo do tipo).

Para módulos de biblioteca, o Build Variant por padrão corresponde ao Build Type do módulo app, já que as bibliotecas não têm product flavors. Se uma biblioteca precisar se adaptar ao flavor do módulo app, os mesmos flavorDimensions e productFlavors devem ser declarados na biblioteca. O AGP corresponde flavors por correspondência exata de nome. O Gradle recomenda sincronizar flavors através da configuração de compilação no projeto raiz usando subprojects ou Convention Plugins.

A partir do AGP 8.1, as bibliotecas podem publicar múltiplas variantes — publicar todas as variantes da biblioteca em um repositório maven simultaneamente. Isso resolve o problema quando o módulo app usa um flavor pago, mas a biblioteca só está publicada para free. A publicação de múltiplas variantes (MVP) permite que o projeto dependente selecione a variante necessária automaticamente. Para habilitar o MVP, adicione publishing { multipleVariants { ... } } ao build.gradle da biblioteca.

Filtragem e Desativação de Variantes

Filtragem Dinâmica via CI/CD

Às vezes é necessário desativar alguns Build Variants — por exemplo, se a combinação mockRelease não fizer sentido (o servidor mock não deve ir para produção). O Gradle fornece variantFilter — um bloco DSL onde você pode verificar as propriedades de cada variante e desativá-la através de setIgnore(true). O VariantFilter é aplicado na fase de configuração, antes da criação de tarefas, portanto, uma variante desativada não gera tarefas assemble e install.

A filtragem também é útil para acelerar as compilações. Se um projeto tem 8 variantes, mas um desenvolvedor está trabalhando em apenas uma, as 7 variantes restantes ainda passam pela configuração. Ao usar variantFilter, as variantes desativadas não criam tarefas, reduzindo o tempo de configuração em 30-50% para projetos com 6+ dimensões de flavor. Em CI/CD, você pode filtrar dinamicamente as variantes através de parâmetros de linha de comando -PbuildOnly=paidRelease.

groovy
android {
    variantFilter { variant ->
        // Desativar mock para release e demo para 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)
        }
    }
}

// Filtragem dinâmica via parâmetros
if (project.hasProperty("buildOnly")) {
    def target = project.property("buildOnly")
    android.variantFilter { variant ->
        variant.setIgnore(variant.name != target)
    }
}

Perguntas Frequentes

Quantos Build Variants podem ser criados?

Não há limite, mas o Gradle cria o produto cartesiano de todos os flavors e tipos. Se você tem 3 dimensões com 3 flavors cada e 3 build types, obtém 27 variantes. Muitas variantes diminuem a configuração. Recomenda-se não ter mais de 10–12 variantes em um módulo.

Por que flavorDimensions são necessários?

flavorDimensions agrupam Product Flavors em eixos independentes. Por exemplo, a dimensão “tier” (free, paid) e a dimensão “region” (us, eu). Sem dimensões, todos os flavors pertencem a um eixo, e o Gradle selecionará apenas um flavor de todos (você não pode ter free+us e paid+eu como variantes separadas).

Como sobrescrever applicationId para uma variante?

No bloco productFlavor ou buildType, especifique applicationId. Por exemplo, para a versão free: free { applicationId “com.example.app.free” }. No manifesto, use ${applicationId} — o Gradle substituirá automaticamente o valor. Isso permite instalar ambas as variantes em um dispositivo.

Pode-se usar Build Variants no iOS?

No iOS, o equivalente de Build Variants é a combinação de Scheme + Configuration. Os Xcode Schemes são configurados através das configurações Debug/Release com diferentes parâmetros. Para várias versões (free/paid), são usadas Build Configurations e Preprocessor Macros. No Android, o conceito é mais formalizado e incorporado ao Gradle.

O Build Variant afeta o tamanho do APK?

Sim, cada variante pode ter um tamanho de APK diferente. As compilações debug incluem informações de depuração, SDK e recursos não suportados. As compilações release com minification e resource shrinking produzem o tamanho mínimo. O Product Flavor também afeta o tamanho: uma versão free sem bibliotecas pagas será menor que a versão paid pelo tamanho dessas bibliotecas.

Resumo

  • Build Variant — combinação de um Build Type e um Product Flavor que define a configuração de compilação.
  • Build Type controla o modo de compilação (debug/release/staging), enquanto Product Flavor controla a versão do produto (free/paid).
  • Source sets permitem sobrescrever código, recursos e manifesto para cada variante de compilação.
  • VariantFilter desativa combinações desnecessárias, acelerando a configuração do Gradle em 30–50%.
  • Projetos multimódulo exigem sincronização de flavors em todos os módulos ou publicação de múltiplas variantes.
  • BuildConfigField e source sets são duas maneiras limpas de personalizar o comportamento entre variantes.
  • Recomendação: não crie mais de 10–12 variantes em um projeto; agrupe as dimensões de forma significativa.

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também