一、使用場景
- 本地動態(tài)配置:設(shè)置開關(guān)是否依賴某些插件;動態(tài)設(shè)置不同環(huán)境;是否是 Debug 模式
- Jekins 打包配置:local.properties 讀取配置和本地打包
- 運行時可根據(jù) gradle 配置,獲取某些開關(guān),實現(xiàn)編譯期和運行期 執(zhí)行邏輯一致。
二、配置步驟
步驟一:主工程 build.gradle 文件中,在 defaultConfig {} 閉包中配置如下:
defaultConfig {
buildConfigField "String", "MESSAGE", "\"I am the base apk\""
buildConfigField "boolean", "DEBUG_MODE", DEBUG_MODE
buildConfigField "boolean", "CANNARY", CANNARY
buildConfigField "String", "LAUNCHER", "\"${LAUNCHER}\""
}
步驟二:項目根 build.gradle 文件中,配置全局屬性如下:
buildScript {
ext {
DEBUG_MODE = Boolean.valueOf(getLocalPropertyString("isDebugMode")).toString()
CANNARY = Boolean.valueOf(getLocalPropertyString("isDebugMode")).toString()
LAUNCHER = getLocalPropertyString("LAUNCHER")
}
def getLocalPropertyString = { key ->
// System.getenv 獲取系統(tǒng)環(huán)境變量;getProperties 獲取當前系統(tǒng)環(huán)境變量
String value = System.getenv(key)
if (!value) {
try {
def properties = new Properties()
properties.load(new FileInputStream(file("local.properties")))
value = properties.getProperty(key, "")
} catch (Exception e) {
}
}
return value
}
}
步驟三:local.properties 文件中配置(也可以直接 gradle.properties 配置)如下:
isDebugMode=true
LAUNCHER=debug
CANNARY=true
步驟四:實際應(yīng)用,可以直接在 build.gradle 腳本文件中使用,則對應(yīng)的是 ext 中的全局屬性變量,如:
if (DEBUG_MODE) {
apply plugin ':com.jakewharton.hugo'
}
也可以在運行時根據(jù) android gradle 插件根據(jù) buildConfigField 生成的 、、build/generated/source/buildConfig/debug/BuildConfig.java 構(gòu)建配置類獲取自動生成的常量字段做一些判斷或取值,如:
public boolean isDebug() {
return BuildConfig.DEBUG_MODE;
}
每個 Android Application 或 library 都可以生成 BuildConfig 文件,其中包含一些必須字段和一些自定義字段,自定義字段就是我們通過 buildConfigField 配置進行生成的,根據(jù)構(gòu)建類型 variant 區(qū)分,debug 構(gòu)建內(nèi)容如下:
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "packageName";
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "";
public static final int VERSION_CODE = 100000;
public static final String VERSION_NAME = "1.0.0";
// Fields from default config.
public static final boolean DEBUG_MODE = true;
public static final boolean CANNRY = true;
public static final String LAUNCHER = "debug";
public static final String MESSAGE = "I am the base apk";
}
三、實際案例
比如,接入 LeakCanary,我們會可能會做一些業(yè)務(wù)相關(guān)的初始化(雖然最新版的去除了底層的初始化),為了防止影響正常提測,我們一般希望在打包時可以通過開關(guān)控制 LeakCanary SDK 的依賴以及在應(yīng)用啟動時的初始化。解決這個問題,現(xiàn)在有了 buildConfigField 這個配置,完全可以實現(xiàn),具體代碼如下:
// 1. 在所需要依賴項目的 build.gradle 文件中動態(tài)添加 leakCanary 依賴如下:
project.afterEvaluate {
// debugImplementation "com.coral.canary:library:$CANARY_LIB_VERSION"
if (CANNARY == 'true') {
println "Add dependencies:" + pro.name + ", " + CANNARY
project.dependencies.add("debugImplementation", "com.coral.canary:library:$CANARY_LIB_VERSION")
}
}
// 2. 應(yīng)用初始化化時,根據(jù) BuildConfig.CANNARY 決定是否進行初始化:
if (BuildConfig.CANNARY) {
Cannary.init("your business logic");
}
四、FAQ
- BuildConfig 作用是什么?如何生成?
- 在 buildConfig { buildConfigField "type" "name" "value" } 配置,gradle 插件會自動生成配置項至 build/generated/source/buildConfig/debug/BuildConfig.java,如果是 SDK 最終打包成 .aar 文件,該類也會被編譯打包,如果在運行期就可以使用該字段。
五、結(jié)語
這是一種同時控制編譯期和運行期開關(guān)配置的方式,非常方便。若后續(xù)有次需求,也算是一種見識。仔細想想,通過寫插件,讀取配置,然后自動生成 java 類,這個功能其實還是很常見的,完全可以自實現(xiàn)一套。