解決依賴的moduleBuildConfig.DEBUG總是未false的問題


Android 開發中一般會通過 BuildConfig.DEBUG 判斷是否是 Debug 模式,從而做一些在 Debug 模式才開啟的特殊操作,比如打印日志。這樣好處是不用在發布前去主動修改,因為這個值在 Debug 模式下為 true,Release 模式下為 false。

1. 問題

如果應用只有一個 Module 沒有問題,Debug 模式下 BuildConfig.DEBUG 會始終為 false。如果現在有兩個 Module,分別為 App 和 Lib,且 App 依賴 Lib,在 Lib 內有工具類 LogUtils,代碼如下:

當我們在 App Module 內調用 LogUtils 時我們會發現始終無法打印日志,因為上面的 BuildConfig.DEBUG 會始終為 false。為什么呢?

2. 原因

BuildConfig.java 是編譯時自動生成的,並且每個 Module 都會生成一份,以該 Module 的 packageName 為 BuildConfig.java 的 packageName。所以如果你的應用有多個 Module 就會有多個 BuildConfig.java 生成,而上面的 Lib Module import 的是自己的 BuildConfig.java,編譯時被依賴的 Module 默認會提供 Release 版給其他 Module 或工程使用,這就導致該 BuildConfig.DEBUG 會始終為 true。

3. 解決方案

根據上面分析的原因,目前我們有兩個思路:

(1) 始終調用最終運行的 Module 的 BuildConfig,因為它沒有被任何其他 Module 依賴,所以 BuildConfig.DEBUG 值會准確。

(2) 讓被依賴的 Module 提供除 Release 版以外的其他版本。

3.1 解決方案一:使用其他的 BuildConfig.java

如果 Lib Module 中能夠 import 到外層真正運行 App 的 BuildConfig 就 ok 了,如下:

通過反射得到真正執行的 Module 的 BuildConfig,在自己的 Application 內調用:

AppUtils.syncIsDebug(getApplicationContext());

這樣看起來達到目的了。

但仔細看看會發現這種解決方案還是有問題,因為 BuildConfig.java 的 packageName 是 Module 的 Package Name,即 AndroidManifest.xml 中的 package 屬性,而 context.getPackageName() 得到的是應用的 applicationId,這個 applicationId 通過 build.gradle 是可以修改的。所以當 build.gradle 中的 applicationId 與 AndroidManifest.xml 中的 package 屬性不一致時,上面的反射查找類路徑便會出錯。

PS:這種方案還有個變種就是通過 android.app.ActivityThread.currentPackageName 得到包名,從而省去傳遞 Context 初始化的步驟,但依然有 applicationId 被修改后類查找不到類似的問題。

3.2 解決方案二:Lib publishNonDefault

讓被依賴的 Module 提供除 Release 版以外的其他版本,這種方案需要將所有被依賴 library 中添加:

android {

publishNonDefault true

}

表示該 Module 不使用默認配置,這樣會同時打包其他版本,包括 Debug 版。另外需要在 App Module 中將其依賴的 library 如下逐個添加:

dependencies {

releaseCompile project(path: ':library', configuration: 'release')

debugCompile project(path: ':library', configuration: 'debug')

}

表示依賴不同版本的依賴 Module。

然而這種方式所有 Module 配置都需要修改,侵入性太強。

3.3 最終解決方案:使用 ApplicationInfo.FLAG_DEBUGGABLE

既然 BuildConfig 的方式行不通,我們反編譯 Debug 包和 Release 包對比看看有沒有其他的區別,會發現他們 AndroidManifest.xml 中 application 節點的 android:debuggable 值是不同的。Debug 包值為 false,Release 包值為 true,這是編譯自動修改的。所以我們考慮通過 ApplicationInfo 的這個屬性去判斷是否是 Debug 版本,如下:

在自己的 Application 內調用進行初始化,

AppUtils.syncIsDebug(getApplicationContext());

這樣以后調用 AppUtils.isDebug() 即可判斷是否是 Debug 版本,比如在上面的 LogUtils 中。同時適用於 Module 是 Lib 和 applicationId 被修改的情況,比 BuildConfig.DEBUG 靠譜的多。

這個方案有個注意事項就是自己 App Module 中不能主動設置 android:debuggable,否則無論 Debug 還是 Release 版會始終是設置的值。當然本身就沒有自動設置的必要。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM