Android geliştirmede Build Variant, bir build type ve bir product flavor’ın birleşimidir ve bir APK veya AAB’nin hangi parametrelerle, kaynaklarla ve kodla oluşturulacağını belirler. Her derleme varyantı, kendi applicationId’si, imzalama anahtarları ve dahil edilen bağımlılıklarıyla ayrı bir Gradle yapılandırmasını temsil eder. Google Android Developers, 2025’a göre, Build Variants’ın doğru yapılandırılması, her varyant için gereksiz kaynakları hariç tutarak derleme süresini %40’a kadar azaltır. Derleme varyantı sistemi, modern Android projelerinde yapılandırma yönetiminin temelidir.
Önemli Noktalar
Build Variant, bir Build Type ile bir Product Flavor’ın birleştirilmesinin sonucudur. Projede hiçbir Product Flavor tanımlanmamışsa, Build Variant Build Type ile eşleşir. Gradle, tüm FlavorDimensions, Product Flavors ve Build Types’ın Kartezyen çarpımı olarak varyantların tam kümesini otomatik olarak oluşturur. Örneğin, free/paid flavor’lar ve debug/release türleri için 4 varyant oluşturulur: freeDebug, freeRelease, paidDebug, paidRelease.
Her Build Variant, flavor büyük harfle başlayacak şekilde <Flavor><Type> formatında kendi adını alır. Gradle bu varyant için ayrı görevler oluşturur: assembleFreeDebug, installFreeDebug, bundleFreeRelease. Android Studio’da, Build Variants paneli (View → Tool Windows → Build Variants) aracılığıyla varyantlar arasında geçiş yapılabilir. Bir varyant seçmek, hangi kodun derleneceğini, hangi kaynakların dahil edileceğini ve hangi APK/AAB’nin üretileceğini etkiler.
Build Variants sistemi üç temel görevi çözer: farklı ortamlar (dev/staging/production) için yapılandırmaları ayırmak, bir uygulamanın birden çok sürümünü (free/paid) oluşturmak ve derlemelerin A/B testini yapmak. Build Variants olmadan, geliştiricilerin manuel olarak bayrakları ve yapılandırmaları değiştirmesi gerekir ve bu da insan hatasına yol açar. Gradle Inc., 2024 tarafından yapılan bir araştırmaya göre, Build Variants’ın uygulanması, üç veya daha fazla dağıtım ortamına sahip projelerde derleme hatalarını %60 oranında azaltır.
AGP (Android Gradle Plugin) yapılandırma aşamasında tüm kombinasyonları hesaplar. Bir projenin sırasıyla iki ve üç flavor’a sahip iki boyutu varsa, Gradle 2 × 2 × 3 = 12 kombinasyon oluşturur ve bu da Build Types sayısıyla (genellikle 2) çarpılır. Her kombinasyon benzersiz bir ad ve görev kümesi alır. AGP her varyant için otomatik olarak bir source set ekler: src/freeDebug/, src/paidRelease/ ve genelleştirilmiş src/free/ ile src/debug/. Kaynak okuma önceliği: variant → flavor → type → main.
// Örnek: 4 Build Variants
// flavorDimensions "version", "server"
// version: demo, prod
// server: mock, live
// buildTypes: debug, release
// Toplam: 2 × 2 × 2 = 8 varyant
android {
flavorDimensions "version", "server"
productFlavors {
demo { dimension "version" }
prod { dimension "version" }
mock { dimension "server" }
live { dimension "server" }
}
}
Build Type, uygulamanın nasıl derleneceğini tanımlar — hata ayıklama bilgisiyle veya olmadan, optimizasyonla veya olmadan, hangi imzayla. Product Flavor neyin derleneceğini tanımlar — ürünün hangi sürümünü. Build Type bir derleme mekanizmasıdır (debug, release, staging). Product Flavor bir ürün varyantıdır (free, paid, enterprise, demo). Her iki kavram da ortogonaldir: herhangi bir Build Type herhangi bir Product Flavor’a uygulanabilir.
Varsayılan Build Type’lar debug (debuggable=true, minification=false, signing=debug.keystore) ve release’i (debuggable=false, minification=true, signing=production.keystore) içerir. Varsayılan Product Flavor birdir ve adsızdır (etkin olarak main source set). Geliştiriciler kendi Build Type’larını (örneğin, debuggable=true ve minification=true olan “staging”) ve istedikleri sayıda Product Flavor’ı ekleyebilir. Diğer bir fark, Build Type’ların boyutlara göre gruplandırılamaması, ancak Product Flavor’ların gruplandırılabilmesidir.
Temel pratik fark: build.gradle’daki defaultConfig tüm Variants’lara uygulanır ancak productFlavors ve buildTypes içinde geçersiz kılınabilir. Bir buildType’a eklenen BuildConfigField, o türdeki tüm flavor’larda görünürken, bir productFlavor’a eklenen, o flavor’un tüm türlerinde görünür. Bir alan her ikisinde de tanımlanmışsa, buildType önceliklidir (zincirde en son uygulanır).
| Özellik | Build Type | Product Flavor |
|---|---|---|
| Amaç | Nasıl derleneceği | Neyin derleneceği |
| Örnekler | debug, release, staging | free, paid, demo, enterprise |
| Varsayılan | debug + release | bir (main) |
| Source Set | src/debug/, src/release/ | src/free/, src/paid/ |
| Boyutlar | hayır | flavorDimensions |
| Uygulama sırası | flavor’dan sonra, geçersiz kılar | defaultConfig’ten sonra |
| BuildConfigField | flavor’ı geçersiz kılar | defaultConfig’i geçersiz kılar |
Build Variants yapılandırması, modül düzeyindeki build.gradle dosyasının android bloğunda yapılır. Önce buildTypes parametreleriyle birlikte bildirilir, ardından flavorDimensions ve productFlavors. Gradle bu bildirimlere dayanarak varyantları otomatik olarak oluşturur. Her varyant, modülün defaultConfig’ini devralır ve belirtilen alanları geçersiz kılar. Bildirim sırası önceliği etkiler: buildTypes, productFlavors’tan sonra uygulanır.
Gradle betiklerinde belirli bir Build Variant’a erişmek için android.applicationVariants (app modülleri için) veya android.libraryVariants (kütüphane modülleri için) kullanın. Bu, yapılandırma çalışma zamanında her varyantın yapılandırmasını değiştirmek için yinelenebilen bir koleksiyondur. Örneğin, “demo” kelimesini içeren tüm varyantlar için programlama yoluyla buildConfigField ekleyebilirsiniz.
Android Gradle Plugin 8.x, lambda’lar aracılığıyla varyantları yapılandırmak için daha temiz bir API olan onVariants desteğini ekledi. Eski API (variantOutput, variantFilter) kullanımdan kaldırıldı olarak işaretlendi. Kütüphane modülleri için onEach ile birlikte onVariants kullanılması önerilir. variantOutput’tan onVariants’a geçiş, AGP’yi 7.x’ten 8.x’e yükseltirken önerilen bir adımdır.
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)
}
}
Her Build Variant, kendi source set hiyerarşisini alır — kaynak kodu, kaynaklar ve bildirim içeren dizinler. Bir source set src/<variantName>/ konumunda bulunur (örneğin, src/freeDebug/) ve java/, res/, AndroidManifest.xml, assets/ içerebilir. Varyantın source set’inde bir dosya varsa, ana source set’ten (src/main/) aynı ada sahip dosyayı geçersiz kılar. Kaynaklar için değiştirme yerine birleştirme gerçekleşir — sistem, tüm etkin source set’lerden kaynakları birleştirir ve varyanta özgü olanlara öncelik verir.
Bir Build Variant için source set’ler bir zincir halinde oluşturulur: src/main/ → src/flavor/ → src/type/ → src/flavorType/. Örneğin, paidRelease için önce main, ardından paid, sonra release ve en son paidRelease uygulanır. Sonraki her source set bir öncekini geçersiz kılar. Bu, src/release/res/values/strings.xml’in src/paid/ şıkkındaki aynı dizeleri geçersiz kılacağı, ancak src/paidRelease/res/ şıkkının daha da yüksek önceliğe sahip olduğu anlamına gelir.
Varyantlar için source set kullanmak, kaynakları özelleştirmenin önerilen yoludur. Kodda BuildConfig.FLAVOR’u kontrol edip mantığı dallandırmak yerine, farklı dosyaları farklı source set’lere yerleştirebilirsiniz. Örneğin, free ve paid sürümlerinin simgeleri sırasıyla src/free/res/ ve src/paid/res/ içine, farklı izinlere sahip AndroidManifest ise src/free/AndroidManifest.xml ve src/paid/AndroidManifest.xml içine konur. Bu daha temiz, daha hızlıdır (kaynaklar derlenir, çalışma zamanında kontrol edilmez) ve daha güvenlidir (kod hatası nedeniyle ücretsiz sürüme yanlışlıkla ücretli işlevsellik ekleyemezsiniz).
Çok modüllü projelerde, her modül (kütüphane) kendi Build Variants’ına sahip olabilir. AGP varyantları otomatik olarak senkronize eder: app modülü paidRelease oluşturursa, bağımlı tüm kütüphaneler de paidRelease’e karşılık gelen varyantlarında oluşturulur. Bir kütüphanede product flavor yoksa ancak app modülünde varsa sorun ortaya çıkar — bu durumda kütüphane bir kez (türüne göre release veya debug) oluşturulur.
Kütüphane modülleri için Build Variant varsayılan olarak app modülünün Build Type‑ıyla eşleşir, çünkü kütüphanelerde product flavor bulunmaz. Bir kütüphanenin app modülünün flavor’ına uyum sağlaması gerekiyorsa, aynı flavorDimensions ve productFlavors kütüphanede bildirilmelidir. AGP, flavor’ları tam ad eşleşmesiyle eşleştirir. Gradle, kök projede subprojects veya Convention Plugins kullanarak derleme yapılandırması aracılığıyla flavor’ları senkronize etmeyi önerir.
AGP 8.1’den itibaren kütüphaneler birden çok varyant yayınlayabilir — tüm kütüphane varyantlarını aynı anda bir maven deposuna yayınlayabilir. Bu, app modülünün ücretli bir flavor kullanması ancak kütüphanenin yalnızca ücretsiz için yayınlanması sorununu çözer. Birden çok varyant yayınlama (MVP), bağımlı projenin gerekli varyantı otomatik olarak seçmesine olanak tanır. MVP’yi etkinleştirmek için kütüphanenin build.gradle’ına publishing { multipleVariants { ... } } ekleyin.
Bazen bazı Build Variants’ları devre dışı bırakmak gerekebilir — örneğin, mockRelease kombinasyonu anlamlı değilse (mock sunucu üretime gönderilmemelidir). Gradle, her varyantın özelliklerini kontrol edebileceğiniz ve setIgnore(true) ile devre dışı bırakabileceğiniz bir DSL bloğu olan variantFilter’ı sağlar. VariantFilter, görev oluşturmadan önce yapılandırma aşamasında uygulanır, bu nedenle devre dışı bırakılan bir varyant assemble ve install görevleri üretmez.
Filtreleme, derlemeleri hızlandırmak için de kullanışlıdır. Bir projede 8 varyant varsa ancak bir geliştirici yalnızca birinde çalışıyorsa, kalan 7 varyant yine de yapılandırmadan geçer. variantFilter kullanıldığında, devre dışı bırakılan varyantlar görev oluşturmaz ve 6+ flavor boyutuna sahip projelerde yapılandırma süresini %30-50 oranında azaltır. CI/CD’de, komut satırı parametreleri -PbuildOnly=paidRelease aracılığıyla varyantları dinamik olarak filtreleyebilirsiniz.
android {
variantFilter { variant ->
// release için mock’u ve production için demo’yu devre dışı bırak
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)
}
}
}
// Parametrelerle dinamik filtreleme
if (project.hasProperty("buildOnly")) {
def target = project.property("buildOnly")
android.variantFilter { variant ->
variant.setIgnore(variant.name != target)
}
}
Sıkça Sorulan Sorular
Bir sınır yoktur, ancak Gradle tüm flavor’ların ve türlerin Kartezyen çarpımını oluşturur. 3 boyutun her birinde 3 flavor ve 3 build type varsa, 27 varyant elde edersiniz. Çok fazla varyant yapılandırmayı yavaşlatır. Bir modülte 10–12’den fazla varyant olmaması önerilir.
flavorDimensions, Product Flavors’ı bağımsız eksenler halinde gruplandırır. Örneğin, “tier” boyutu (free, paid) ve “region” boyutu (us, eu). Boyutlar olmadan, tüm flavor’lar tek bir eksene aittir ve Gradle tümünden yalnızca bir flavor seçer (free+us ve paid+eu’yu ayrı varyantlar olarak sahip olamazsınız).
productFlavor veya buildType bloğunda applicationId belirtin. Örneğin, ücretsiz sürüm için: free { applicationId “com.example.app.free” }. Bildirimde ${applicationId} kullanın — Gradle değeri otomatik olarak değiştirecektir. Bu, her iki varyantın da aynı cihaza yüklenmesine olanak tanır.
iOS’te, Build Variants’ın eşdeğeri Scheme + Configuration kombinasyonudur. Xcode Schemes, farklı parametrelerle Debug/Release yapılandırmaları aracılığıyla yapılandırılır. Birden çok sürüm (free/paid) için Build Configurations ve Preprocessor Macros kullanılır. Android’de konsept daha resmidir ve Gradle’a yerleşiktir.
Evet, her varyant farklı APK boyutuna sahip olabilir. Debug derlemeleri hata ayıklama bilgilerini, SDK’yı ve desteklenmeyen kaynakları içerir. Minification ve resource shrinking ile release derlemeleri minimum boyut üretir. Product Flavor da boyutu etkiler: ücretsiz kitaplıkları olmayan ücretsiz sürüm, bu kitaplıkların boyutu kadar ücretli sürümden daha küçük olacaktır.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun