Build Variants
Build Variants cho phép bạn tạo nhiều phiên bản khác nhau của ứng dụng từ một codebase duy nhất. Mỗi variant có thể có code, resources, và cấu hình riêng.
Build Variant = Build Type + Product Flavor
| Thành phần | Mô tả | Ví dụ |
|---|---|---|
| Build Type | Cách build ứng dụng | debug, release, staging |
| Product Flavor | Phiên bản nội dung | demo, full, free, paid |
| Build Variant | Kết hợp type + flavor | demoDebug, fullRelease |
Build Types
Build Types định nghĩa cách Gradle build và package ứng dụng. Mặc định Android Studio tạo 2 build types:
Cấu hình Build Types
android {
buildTypes {
debug {
// Debug được cấu hình mặc định: debuggable = true
applicationIdSuffix = ".debug"
versionNameSuffix = "-debug"
// Không minify để build nhanh
isMinifyEnabled = false
}
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
// Custom build type
create("staging") {
// Kế thừa từ debug
initWith(getByName("debug"))
applicationIdSuffix = ".staging"
versionNameSuffix = "-staging"
// Môi trường staging
buildConfigField("String", "API_URL", "\"https://staging.api.com\"")
}
}
}Các thuộc tính Build Type
| Thuộc tính | Mô tả | Mặc định Debug | Mặc định Release |
|---|---|---|---|
isDebuggable | Cho phép attach debugger | true | false |
isMinifyEnabled | Bật code shrinking (R8) | false | false |
isShrinkResources | Loại bỏ resources không dùng | false | false |
applicationIdSuffix | Suffix cho applicationId | ||
versionNameSuffix | Suffix cho versionName | ||
signingConfig | Signing configuration | debug keystore | (cần cấu hình) |
💡 Mẹo: Debug build được tự động sign với debug keystore. Release build cần cấu hình signing riêng.
Product Flavors
Product Flavors tạo các phiên bản khác nhau của ứng dụng với nội dung hoặc tính năng khác nhau.
Khai báo Product Flavors
android {
// Bắt buộc: Khai báo flavor dimensions
flavorDimensions += "version"
productFlavors {
create("demo") {
dimension = "version"
applicationIdSuffix = ".demo"
versionNameSuffix = "-demo"
// Custom build config fields
buildConfigField("Boolean", "IS_DEMO", "true")
buildConfigField("Int", "MAX_ITEMS", "10")
}
create("full") {
dimension = "version"
buildConfigField("Boolean", "IS_DEMO", "false")
buildConfigField("Int", "MAX_ITEMS", "Integer.MAX_VALUE")
}
}
}Sử dụng BuildConfig
// Trong code Kotlin
if (BuildConfig.IS_DEMO) {
showDemoLimitation()
}
val maxItems = BuildConfig.MAX_ITEMS⚠️ Quan trọng: Để sử dụng
BuildConfig, phải bậtbuildFeatures.buildConfig = truetrongbuild.gradle.kts.
Flavor Dimensions
Khi có nhiều “chiều” khác nhau cho product flavors, sử dụng flavor dimensions:
android {
flavorDimensions += listOf("version", "api")
productFlavors {
// Dimension: version
create("demo") {
dimension = "version"
applicationIdSuffix = ".demo"
}
create("full") {
dimension = "version"
}
// Dimension: api
create("minApi24") {
dimension = "api"
minSdk = 24
}
create("minApi28") {
dimension = "api"
minSdk = 28
}
}
}Build Variants được tạo
Gradle tạo variants từ tất cả combinations:
demoMinApi24Debug
demoMinApi24Release
demoMinApi28Debug
demoMinApi28Release
fullMinApi24Debug
fullMinApi24Release
fullMinApi28Debug
fullMinApi28ReleaseVí dụ thực tế: App với môi trường Dev/Prod
android {
namespace = "com.example.myapp"
compileSdk = 35
defaultConfig {
applicationId = "com.example.myapp"
minSdk = 24
targetSdk = 35
versionCode = 1
versionName = "1.0.0"
}
buildFeatures {
buildConfig = true
}
flavorDimensions += "environment"
productFlavors {
create("dev") {
dimension = "environment"
applicationIdSuffix = ".dev"
versionNameSuffix = "-dev"
// Môi trường development
buildConfigField("String", "API_BASE_URL", "\"https://dev.api.example.com\"")
buildConfigField("String", "API_KEY", "\"dev_api_key_123\"")
buildConfigField("Boolean", "ENABLE_LOGGING", "true")
// Resource values
resValue("string", "app_name", "MyApp Dev")
}
create("staging") {
dimension = "environment"
applicationIdSuffix = ".staging"
versionNameSuffix = "-staging"
buildConfigField("String", "API_BASE_URL", "\"https://staging.api.example.com\"")
buildConfigField("String", "API_KEY", "\"staging_api_key_456\"")
buildConfigField("Boolean", "ENABLE_LOGGING", "true")
resValue("string", "app_name", "MyApp Staging")
}
create("prod") {
dimension = "environment"
buildConfigField("String", "API_BASE_URL", "\"https://api.example.com\"")
buildConfigField("String", "API_KEY", "\"prod_api_key_789\"")
buildConfigField("Boolean", "ENABLE_LOGGING", "false")
resValue("string", "app_name", "MyApp")
}
}
buildTypes {
debug {
isMinifyEnabled = false
}
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
}Sử dụng trong code
// NetworkModule.kt
object NetworkModule {
val retrofit: Retrofit = Retrofit.Builder()
.baseUrl(BuildConfig.API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.apply {
if (BuildConfig.ENABLE_LOGGING) {
client(
OkHttpClient.Builder()
.addInterceptor(HttpLoggingInterceptor().setLevel(Level.BODY))
.build()
)
}
}
.build()
}Source Sets cho Variants
Mỗi variant có thể có source code và resources riêng:
app/src/
├── main/ # Common source
│ ├── java/
│ └── res/
├── debug/ # Debug build type specific
│ └── java/
├── release/ # Release build type specific
├── dev/ # Dev flavor specific
│ ├── java/
│ └── res/
├── prod/ # Prod flavor specific
│ └── res/
└── devDebug/ # Dev + Debug combination
└── java/Thứ tự merge source sets
Variant source set > Build type > Flavor > mainVí dụ với variant devDebug:
src/devDebug/(nếu có)src/debug/src/dev/src/main/
Filter Variants
Loại bỏ các variants không cần thiết:
android {
flavorDimensions += listOf("version", "api")
productFlavors {
create("demo") { dimension = "version" }
create("full") { dimension = "version" }
create("minApi24") { dimension = "api" }
create("minApi28") { dimension = "api" }
}
}
// Filter variants
androidComponents {
beforeVariants { variantBuilder ->
// Loại bỏ demo + minApi28 combinations
if (variantBuilder.productFlavors.containsAll(
listOf("version" to "demo", "api" to "minApi28"))
) {
variantBuilder.enable = false
}
}
}Signing Configuration
Cấu hình signing cho từng build type:
android {
signingConfigs {
// Debug đã có sẵn, không cần khai báo
create("release") {
storeFile = file("keystore/release.jks")
storePassword = System.getenv("KEYSTORE_PASSWORD")
keyAlias = System.getenv("KEY_ALIAS")
keyPassword = System.getenv("KEY_PASSWORD")
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
// ...
}
}
}🚨 Chú ý: KHÔNG commit passwords vào source control! Sử dụng environment variables hoặc
local.properties.
Sử dụng local.properties
// build.gradle.kts
import java.util.Properties
val localProperties = Properties().apply {
val localPropertiesFile = rootProject.file("local.properties")
if (localPropertiesFile.exists()) {
load(localPropertiesFile.inputStream())
}
}
android {
signingConfigs {
create("release") {
storeFile = file(localProperties.getProperty("RELEASE_STORE_FILE", ""))
storePassword = localProperties.getProperty("RELEASE_STORE_PASSWORD", "")
keyAlias = localProperties.getProperty("RELEASE_KEY_ALIAS", "")
keyPassword = localProperties.getProperty("RELEASE_KEY_PASSWORD", "")
}
}
}Chọn Build Variant trong Android Studio
- Mở panel Build Variants (View → Tool Windows → Build Variants)
- Chọn variant cho mỗi module
- Click Sync nếu cần
Hoặc build từ command line:
# Build variant cụ thể
./gradlew assembleDevDebug
./gradlew assembleProdRelease
# Build tất cả variants của một type
./gradlew assembleDebug
./gradlew assembleRelease
# Build AAB
./gradlew bundleProdReleaseTóm tắt
| Concept | Mục đích | Ví dụ |
|---|---|---|
| Build Type | Cách build (debug settings, minification) | debug, release, staging |
| Product Flavor | Phiên bản ứng dụng | demo/full, free/paid, dev/prod |
| Flavor Dimension | Nhóm các flavors | version, api, environment |
| Build Variant | Build type + Flavor(s) | demoDebug, prodRelease |
| Source Set | Code/resources cho variant | src/demo/, src/debug/ |