Build Variant dalam pengembangan Android adalah kombinasi build type dan product flavor yang menentukan bagaimana APK atau AAB akan dibangun: dengan parameter, sumber daya, dan kode apa. Setiap varian kompilasi merupakan konfigurasi Gradle terpisah dengan applicationId sendiri, kunci penandatanganan, dan dependensi yang disertakan. Menurut Google Android Developers, 2025, konfigurasi Build Variants yang benar mengurangi waktu kompilasi hingga 40% dengan mengecualikan sumber daya yang tidak perlu untuk setiap varian. Sistem varian kompilasi adalah dasar manajemen konfigurasi dalam proyek Android modern.
Poin penting
Build Variant — adalah hasil kombinasi satu Build Type dan satu Product Flavor. Jika Product Flavor tidak didefinisikan dalam proyek, Build Variant bertepatan dengan Build Type. Gradle secara otomatis menghasilkan set lengkap varian sebagai produk Kartesian dari semua FlavorDimensions, Product Flavors, dan Build Types. Misalnya, untuk flavor free/paid dan tipe debug/release, akan dibuat 8 varian: freeDebug, freeRelease, paidDebug, paidRelease.
Setiap Build Variant mendapatkan nama sendiri dalam format <Flavor><Type> dengan flavor huruf kapital. Untuk varian ini, Gradle menghasilkan tugas terpisah: assembleFreeDebug, installFreeDebug, bundleFreeRelease. Di Android Studio, beralih antar varian tersedia melalui panel Build Variants (View → Tool Windows → Build Variants). Pemilihan varian memengaruhi kode mana yang dikompilasi, sumber daya mana yang disertakan, dan APK/AAB mana yang dibuat.
Sistem Build Variants memecahkan tiga tugas utama: pemisahan konfigurasi untuk lingkungan yang berbeda (dev/staging/production), pembuatan beberapa versi aplikasi (free/paid), dan pengujian A/B build. Tanpa Build Variants, pengembang harus beralih secara manual antara flag dan konfigurasi, yang menyebabkan kesalahan faktor manusia. Menurut penelitian Gradle Inc., 2024, penerapan Build Variants mengurangi jumlah kesalahan kompilasi hingga 60% dalam proyek dengan tiga atau lebih lingkungan deployment.
AGP (Android Gradle Plugin) menghitung semua kombinasi pada fase konfigurasi. Jika proyek memiliki dua dimensi dengan masing-masing dua dan tiga flavor, Gradle akan membuat 2 × 2 × 3 = 12 kombinasi, dikalikan dengan jumlah Build Types (biasanya 2). Setiap kombinasi mendapatkan nama unik dan set tugas. AGP secara otomatis menambahkan source set untuk setiap varian: src/freeDebug/, src/paidRelease/, serta yang digeneralisasi src/free/ dan src/debug/. Prioritas pembacaan sumber daya: variant → flavor → type → main.
// Contoh: 4 Build Variants
// flavorDimensions "version", "server"
// version: demo, prod
// server: mock, live
// buildTypes: debug, release
// Total: 2 × 2 × 2 = 8 varian
android {
flavorDimensions "version", "server"
productFlavors {
demo { dimension "version" }
prod { dimension "version" }
mock { dimension "server" }
live { dimension "server" }
}
}
Build Type menentukan bagaimana aplikasi dikompilasi — dengan informasi debugging atau tanpa, dengan optimasi atau tanpa, dengan penandatanganan apa. Product Flavor menentukan apa yang dikompilasi — versi produk mana. Build Type — adalah mekanisme kompilasi (debug, release, staging). Product Flavor — adalah varian produk (free, paid, enterprise, demo). Kedua konsep bersifat ortogonal: Build Type apa pun dapat diterapkan ke Product Flavor apa pun.
Build Type secara default mencakup debug (debuggable=true, minification=false, signing=debug.keystore) dan release (debuggable=false, minification=true, signing=production.keystore). Product Flavor secara default satu, tanpa nama (sebenarnya main source set). Pengembang dapat menambahkan Build Types sendiri (misalnya, “staging” dengan debuggable=true dan minification=true) dan Product Flavors dalam jumlah berapa pun. Perbedaannya juga terletak pada kenyataan bahwa Build Type tidak dapat dikelompokkan ke dalam dimensi, sedangkan Product Flavor bisa.
Perbedaan praktis utama: defaultConfig di build.gradle diterapkan ke semua Variants, tetapi dapat ditimpa di productFlavors dan buildTypes. BuildConfigField yang ditambahkan di buildType terlihat di semua flavor dari tipe ini, dan yang ditambahkan di productFlavor — di semua tipe dari flavor ini. Jika bidang didefinisikan di kedua tempat — buildType memiliki prioritas (diterapkan terakhir dalam rantai).
| Karakteristik | Build Type | Product Flavor |
|---|---|---|
| Tujuan | Cara mengompilasi | Apa yang dikompilasi |
| Contoh | debug, release, staging | free, paid, demo, enterprise |
| Default | debug + release | satu (main) |
| Source Set | src/debug/, src/release/ | src/free/, src/paid/ |
| Dimensi | tidak | flavorDimensions |
| Penerapan | setelah flavor, menimpa | setelah defaultConfig |
| BuildConfigField | menimpa flavor | menimpa defaultConfig |
Konfigurasi Build Variants dilakukan di blok android file build.gradle tingkat modul. Pertama dideklarasikan buildTypes dengan parameternya, kemudian flavorDimensions dan productFlavors. Gradle secara otomatis membuat varian berdasarkan deklarasi ini. Setiap varian mewarisi defaultConfig modul, menimpa bidang yang ditentukan. Urutan deklarasi memengaruhi prioritas: buildTypes diterapkan setelah productFlavors.
Untuk mengakses Build Variant tertentu di skrip Gradle, digunakan android.applicationVariants (untuk modul app) atau android.libraryVariants (untuk modul perpustakaan). Ini adalah koleksi yang dapat diiterasi dan konfigurasi setiap varian dapat diubah saat konfigurasi. Misalnya, buildConfigField dapat ditambahkan secara programatis untuk semua varian yang mengandung kata “demo”.
Android Gradle Plugin 8.x menambahkan dukungan untuk onVariants — API yang lebih bersih untuk mengonfigurasi varian melalui lambda. API lama (variantOutput, variantFilter) ditandai sebagai tidak digunakan lagi. Disarankan menggunakan onVariants bersama dengan onEach untuk modul perpustakaan. Migrasi dari variantOutput ke onVariants — langkah yang disarankan saat memperbarui AGP dari 7.x ke 8.x.
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)
}
}
Setiap Build Variant mendapatkan hierarki source sets sendiri — direktori dengan kode sumber, sumber daya, dan manifes. Source set terletak di src/<variantName>/ (misalnya, src/freeDebug/) dan dapat berisi java/, res/, AndroidManifest.xml, assets/. Jika file ada di source set varian, itu akan menimpa file dengan nama yang sama dari source set utama (src/main/). Untuk sumber daya, penggabungan bekerja, bukan penggantian — sistem menggabungkan sumber daya dari semua source sets aktif, memberikan prioritas pada yang spesifik varian.
Source sets untuk Build Variant dibangun dalam rantai: src/main/ → src/flavor/ → src/type/ → src/flavorType/. Misalnya, untuk paidRelease, pertama main diterapkan, kemudian paid, kemudian release, kemudian paidRelease. Setiap source set berikutnya menimpa yang sebelumnya. Ini berarti src/release/res/values/strings.xml akan menimpa string yang sama dari src/paid/, tetapi src/paid/release/res/ bahkan lebih prioritas.
Menggunakan source sets untuk varian — cara yang disarankan untuk menyesuaikan sumber daya. Alih-alih memeriksa BuildConfig.FLAVOR dalam kode dan melakukan percabangan logika, file yang berbeda dapat ditempatkan di source sets yang berbeda. Misalnya, ikon untuk versi free dan paid ditempatkan masing-masing di src/free/res/ dan src/paid/res/, dan AndroidManifest dengan izin berbeda — di src/free/AndroidManifest.xml dan src/paid/AndroidManifest.xml. Ini lebih bersih, lebih cepat (sumber daya dikompilasi, tidak diperiksa saat runtime) dan lebih aman (fungsionalitas berbayar tidak dapat secara tidak sengaja diaktifkan di versi gratis karena bug dalam kode).
Dalam proyek multi-modul, setiap modul (perpustakaan) dapat memiliki Build Variants sendiri. AGP secara otomatis menyinkronkan varian: jika modul app mengompilasi paidRelease, semua perpustakaan dependen juga dikompilasi dalam varian mereka yang sesuai dengan paidRelease. Masalah muncul ketika perpustakaan tidak memiliki product flavors, tetapi modul app memilikinya — maka perpustakaan dikompilasi sekali (release atau debug tergantung pada tipenya).
Untuk modul perpustakaan, Build Variant secara default bertepatan dengan Build Type modul app, karena perpustakaan tidak memiliki product flavors. Jika perpustakaan harus menyesuaikan dengan flavor modul app, perlu mendeklarasikan flavorDimensions dan productFlavors yang sama di perpustakaan. AGP mencocokkan flavor berdasarkan kecocokan nama penuh. Gradle merekomendasikan sinkronisasi flavor melalui konfigurasi build di proyek root menggunakan subprojects atau Convention Plugins.
Mulai dari AGP 8.1, perpustakaan dapat menerbitkan multiple variants — menerbitkan semua varian perpustakaan secara bersamaan ke repositori maven. Ini memecahkan masalah ketika modul app menggunakan flavor paid, tetapi perpustakaan hanya diterbitkan untuk free. Multiple variants publishing (MVP) memungkinkan proyek dependen untuk secara otomatis memilih varian yang diperlukan. Untuk mengaktifkan MVP, perlu menambahkan publishing { multipleVariants { ... } } di build.gradle perpustakaan.
Terkadang perlu menonaktifkan sebagian Build Variants — misalnya, jika kombinasi mockRelease tidak masuk akal (server mock tidak boleh masuk ke produksi). Gradle menyediakan variantFilter — blok DSL di mana properti setiap varian dapat diperiksa dan dinonaktifkan melalui setIgnore(true). VariantFilter diterapkan pada fase konfigurasi, sebelum pembuatan tugas, sehingga varian yang dinonaktifkan tidak menghasilkan tugas assemble dan install.
Penyaringan juga berguna untuk mempercepat kompilasi. Jika proyek memiliki 8 varian dan pengembang hanya bekerja pada satu, 7 varian lainnya tetap melalui konfigurasi (configuration phase). Saat menggunakan variantFilter, varian yang dinonaktifkan tidak membuat tugas, yang mengurangi waktu konfigurasi sebesar 30-50% untuk proyek dengan 6+ dimensi flavor. Di CI/CD, varian dapat difilter secara dinamis melalui parameter baris perintah -PbuildOnly=paidRelease.
android {
variantFilter { variant ->
// Nonaktifkan mock untuk release dan demo untuk produksi
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)
}
}
}
// Penyaringan dinamis melalui parameter
if (project.hasProperty("buildOnly")) {
def target = project.property("buildOnly")
android.variantFilter { variant ->
variant.setIgnore(variant.name != target)
}
}
Pertanyaan yang sering diajukan
Tidak ada batasan, tetapi Gradle membuat produk Kartesian dari semua flavor dan tipe. Jika Anda memiliki 3 dimensi dengan 3 flavor dan 3 build type — Anda akan mendapatkan 27 varian. Terlalu banyak varian memperlambat konfigurasi. Disarankan tidak lebih dari 10-12 varian dalam satu modul.
flavorDimensions mengelompokkan Product Flavors ke dalam sumbu independen. Misalnya, dimensi “tier” (free, paid) dan “region” (us, eu). Tanpa dimensi, semua flavor termasuk dalam satu sumbu dan Gradle hanya akan memilih satu flavor dari semuanya (tidak dapat memiliki free+us dan paid+eu sebagai varian terpisah).
Di blok productFlavor atau buildType, tentukan applicationId. Misalnya, untuk versi free: free { applicationId "com.example.app.free" }. Di manifes, gunakan ${applicationId} — Gradle akan secara otomatis mengganti nilainya. Ini memungkinkan menginstal kedua varian pada satu perangkat.
Di iOS, padanan Build Variants adalah kombinasi Scheme + Configuration. Xcode Schemes dikonfigurasi melalui konfigurasi Debug/Release dengan parameter berbeda. Untuk beberapa versi (free/paid) digunakan Build Configurations dan Preprocessor Macros. Di Android, konsepnya lebih formal dan tertanam di Gradle.
Ya, setiap varian dapat memiliki ukuran APK yang berbeda. Build debug menyertakan informasi debugging, SDK, dan sumber daya yang tidak didukung. Build release dengan minifikasi dan penyusutan sumber daya memberikan ukuran minimal. Product Flavor juga berpengaruh: versi free tanpa pustaka berbayar akan lebih kecil dari versi paid sebesar ukuran pustaka tersebut.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga