啥也不說了,直接進入主題吧。本篇文章主要根據實際開發中遇到的需求,講解使用 Gradle
對應用的不同版本進行個性化定製。
場景介紹
- 一般的應用基本上都有正式服和測試服,這個就不需要多說了。但是有些應用可能還有
超管伺服器
專供運營人員使用,對應用內的一些內容進行監管,具有一些管理員才有的操作許可權。 - 開發過程中釋出測試伺服器的安裝包需要在版本號後面增加版本序號,超管伺服器的包在版本號後面增加
管理員
文字,線上包則正常顯示版本號。 - 每次打包
versionCode
自增,避免發版時忘記手動修改導致老版本不能覆蓋安裝。 - 超管包的渠道名為
admin
,日常執行的debug
包渠道名為test
,上線的包使用加固軟體進行多渠道加固。 debug
包和release
包使用同樣的簽名,避免直接執行的debug
包因為簽名問題不能使用需要校驗簽名的第三方服務,比如:QQ 登入,微信登入,高德地圖。debug
包列印日誌資訊,release
包不列印日誌資訊
以上某些場景從我工作以來就一直存在,以前用 eclipse
開發時除了每次都手動去修改一些開關變數也沒啥好辦法,可能是因為當時菜 ╮(╯▽╰)╭(如果你們有什麼好方法的話)。
後來切換到 Android Studio
後使用 Gradle
進行依賴管理已經讓人很是欣喜,既然如此能不能使用 Gradle
將以上問題統統解決,完全自動化呢?答案是:必須的。
解決問題
先上完整的 Gradle
配置。
android {
compileSdkVersion 25
buildToolsVersion "25.0.3"
defaultConfig {
applicationId "com.imliujun.gradle"
minSdkVersion 16
targetSdkVersion 25
versionCode gitVersionCode() //獲取 git 的 commit 次數
versionName rootProject.ext.versionName
manifestPlaceholders = [UMENG_APP_KEY : "填你的友盟 APP KEY",
UMENG_CHANNEL_VALUE: "預設的渠道名"]
}
signingConfigs {
//在這裡配置相關的簽名資訊
keyStore {
storeFile file("test.jks")
storePassword "111111"
keyAlias "test"
keyPassword "111111"
}
}
buildTypes {
release {
// 不顯示Log
buildConfigField "boolean", "LOG_DEBUG", "false"
signingConfig signingConfigs.keyStore //設定簽名檔案
}
debug {
// 顯示Log
buildConfigField "boolean", "LOG_DEBUG", "true"
versionNameSuffix "-debug" //設定字尾
signingConfig signingConfigs.keyStore //設定簽名檔案
manifestPlaceholders.UMENG_CHANNEL_VALUE = "test" //修改渠道名
}
}
productFlavors {
offline {
buildConfigField "String", "DOMAIN_NAME", "\"https://offline.domain.com/\""
versionName getTestVersionName() //修改 versionName
}
online {
buildConfigField "String", "DOMAIN_NAME", "\"https://online.domain.com/\""
}
admin {
buildConfigField "String", "DOMAIN_NAME", "\"https://admin.domain.com/\""
versionName rootProject.ext.versionName + "-管理員" //修改 versionName
manifestPlaceholders.UMENG_CHANNEL_VALUE = "admin" //修改渠道名
}
}
}複製程式碼
根目錄下的 build.gradle
檔案進行如下配置,主要是將版本號和測試包的序號抽取出來:
ext {
versionName = "2.0.2"
testNum = "0001"
}
def getTestVersionName() {
return String.format("%s.%s", rootProject.ext.versionName,
rootProject.ext.testNum)
}
static int gitVersionCode() {
def count = "git rev-list HEAD --count".execute().text.trim()
return count.isInteger() ? count.toInteger() : 0
}複製程式碼
下面就根據場景來依次介紹對應的配置程式碼。
1. 配置伺服器版本
這裡建立了三個 flavor,分別是 offline 測試服
、online 正式服
、admin 超管服
。並且通過 buildConfigField
動態配置伺服器的 URL 常量值到編譯後自動生成的 BuildConfig
類中。
圖中可以看到,不止有 DOMAIN_NAME
常量值,還有一個 FLAVOR
常量。這個 FLAVOR
常量中的值是 offline
,代表當前在 offline
這個版本上面。那怎麼切換到其他的伺服器呢?
點開左下角的 Build Variants
, 可以自由切換當前執行的版本。需要在管理員包中開啟一些高階的功能,可以判斷 FLAVOR
的值是不是 admin
,如果是的話就顯示管理員的操作佈局。當然必不可少的要對使用者許可權進行校驗哦。
2. 定製 versionName
大家看上圖 BuildConfig
類中 VERSION_NAME
常量的值為 2.0.2.0001-debug
,當前是測試服的 debug
包,所以 versionName
應該是正常的 2.0.2 版本後面拼上當前出包的序號 0001 ,再拼上 debug
的字尾,所以完整的版本號是 2.0.2.0001-debug
。
看看不同伺服器版本的 VERSION_NAME
:
offlineRelease
版本為2.0.2.0001
offlineDebug
版本為2.0.2.0001-debug
adminRelease
版本為2.0.2-管理員
adminDebug
版本為2.0.2-管理員-debug
onlineRelease
版本為2.0.2
onlineDebug
版本為2.0.2-debug
如果我們介面需要上傳版本號給伺服器呢?肯定不能直接上傳這些定製化後的 VERSION_NAME
,那麼我們在 Gradle
中增加一個 buildConfigField
將原始的版本號存起來就好了。
buildConfigField "String", "versionNumber", "\"${rootProject.ext.versionName}\""複製程式碼
3. versionCode
自增
這裡採用了主流的方式,使用 git
的 commit
次數作為 versionCode
的值。不用擔心這個值會超過 int
的上限,你得敲爛多少鍵盤才能提交 2147483648次 commit
。
static int gitVersionCode() {
def count = "git rev-list HEAD --count".execute().text.trim()
return count.isInteger() ? count.toInteger() : 0
}複製程式碼
4. 個性化渠道名
Gradle
多渠道打包的文章太多了,相關的基礎我就不講了。簡單講下本文相關的配置吧。
通過定義 manifestPlaceholders
鍵值對,在 AndroidManifest.xml
檔案中使用佔位符的方式動態輸入 UMENG_APPKEY
和 UMENG_CHANNEL
。
然後在 debug
的 buildType
中修改渠道名為 test
,在 admin
的 Flavor
中修改渠道名為 admin
。如果選擇 adminDebug
版本,則渠道名為 test
,buildType
中的配置會覆蓋掉 Flavor
中的配置。
由於我們線上使用第三方加固,所以多渠道包就交給第三方加固軟體來生成了。
關於多渠道打包我還有兩句話要說,以前使用 Gradle
進行多渠道打包,通過程式碼自定義修改 apk
檔案的輸出路徑,Android Studio
編譯的時候時不時的報一些檔案找不到的錯誤,以前都是通過在 Gradle
檔案中隨便修改一點東西然後重新整理一下 Gradle
檔案來解決。現在我打包不修改輸出路徑,再也沒遇到以前的那些問題了。
建議大家使用 assemble
命令來進行打包,比如我要出一個測試包使用 ./gradlew assembleOfflineRelease
命令,apk
檔案生成在 /build/outputs/apk/
目錄下。直接執行 assemble
命令是編譯 Build Variants
中的所有包,如果你要編譯指定版本的包,直接在 assemble
命令後面拼上指定的 Build Variant
就好了。
5. debug
包使用 release
簽名
這個問題在 eclipse
時代,可以直接在設定裡面配置 debug
簽名檔案為 release
的簽名檔案。
用 Android Studio
只需要在 Gradle
中配置就好了。
首先配置簽名檔案的資訊:
signingConfigs {
//在這裡配置相關的簽名資訊
keyStore {
storeFile file("test.jks")
storePassword "111111"
keyAlias "test"
keyPassword "111111"
}
}複製程式碼
然後在 buildTypes
中設定簽名資訊:
buildTypes {
release {
signingConfig signingConfigs.keyStore //設定簽名檔案
}
debug {
signingConfig signingConfigs.keyStore //設定簽名檔案
}
}複製程式碼
6. 日誌開關
這個太簡單了,不想單獨列出來。不過上面場景裡面提出來了,就簡單一行程式碼展示吧。
release {
// 不顯示Log
buildConfigField "boolean", "LOG_DEBUG", "false"
}
debug {
// 顯示Log
buildConfigField "boolean", "LOG_DEBUG", "true"
}複製程式碼
在日誌工具類中使用 BuildConfig
類中的 LOG_DEBUG
常量來判斷當前是否應該輸出日誌。
當然也可以用這個開關來控制開啟嚴格模式等其他只適合在 debug
模式下開啟的設定。
結語
唧唧歪歪說了這麼多,在懂的人眼中自然很簡單,在對 gradle
一點都不瞭解的人眼中就可以直接複製過去用了。當然我是不建議直接複製,畢竟需求稍微一改,你可能就束手無策了。建議大家還是以理解為主,掌握其原理自然一通百通。
相關閱讀
Android Studio 3.0 上 Gradle 改動