巧用 buildConfigField 實現(xiàn)本地動態(tài)配置

一、使用場景

  1. 本地動態(tài)配置:設(shè)置開關(guān)是否依賴某些插件;動態(tài)設(shè)置不同環(huán)境;是否是 Debug 模式
  2. Jekins 打包配置:local.properties 讀取配置和本地打包
  3. 運行時可根據(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

  1. BuildConfig 作用是什么?如何生成?
  • 在 buildConfig { buildConfigField "type" "name" "value" } 配置,gradle 插件會自動生成配置項至 build/generated/source/buildConfig/debug/BuildConfig.java,如果是 SDK 最終打包成 .aar 文件,該類也會被編譯打包,如果在運行期就可以使用該字段。

五、結(jié)語

這是一種同時控制編譯期和運行期開關(guān)配置的方式,非常方便。若后續(xù)有次需求,也算是一種見識。仔細想想,通過寫插件,讀取配置,然后自動生成 java 類,這個功能其實還是很常見的,完全可以自實現(xiàn)一套。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容