Gradle 作為一款靈活多變的構建外掛,與 Android Studio 的結合,能夠解決過去使用 Eclipse 開發 App 時所遇到的諸多問題。同時,基於 Groove 這樣一款 DSL 語言的指令碼特性,記住各種語法顯然又是一件比較困難的事情。
事實上,Gradle 外掛的常用使用場景並不是很多,也不需要死記硬背,或者完全學會 Groove 的所有使用方式。這裡將 Android 開發中較為常用的 Gradle 使用場景總結出來,用於將來需要的時候有個參考。
多渠道打包
舉一個最常見的多渠道使用場景,友盟統計,看看最基本的 Gradle 多渠道打包方式的用法。
修改 Manifest 檔案中友盟統計的渠道名為引用變數(變數名自取):
<meta-data
android:name="${UMENG_CHANNEL_VALUE}"
android:value="Channel_ID" />複製程式碼
然後在 build.gradle 檔案 productFlavors 配置項中新增渠道名,並統一設定到上面提到的變數名:
android {
productFlavors {
xiaomi {}
yingyongbao {}
}
productFlavors.all {
flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
}複製程式碼
執行打包 Task 的命令語句即可:
./gradle assembleRelease複製程式碼
或者有針對性的只打特定渠道包,如:
./gradle assembleXiaomiRelease複製程式碼
備註:在 Gradle projects 視窗中能夠檢視所有可執行的 Tasks 列表。這種原生態打包方式適合渠道名比較少的使用場景。當渠道多達數十個甚至上百個時,打包時間就會比較長,推薦其他打包方案,如:
自定義輸出 APK 檔名
可以修改打包輸出的 apk 檔名,新增時間戳、編譯型別、版本資訊等關鍵字,是 apk 檔案更具識別性,如:
apply plugin: 'com.android.application'
def releaseTime() {
return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}
android {
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(output.outputFile.parent, rootProject.getName()
+ "-" + buildType.name
+ "-" + releaseTime()
+ "-v" + defaultConfig.versionName
+ "-" + defaultConfig.versionCode
+ ".apk");
}
}
}複製程式碼
這裡將專案名稱新增到 apk 檔名中,也可以使用 applicationId 等,結果如下:
YFSample-release-2017-09-12-v1.0-1.apk複製程式碼
Debug 和 Release 相同簽名
android {
buildTypes {
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "boolean", "DEBUG_MODE", "true"
signingConfig signingConfigs.config
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "boolean", "DEBUG_MODE", "false"
signingConfig signingConfigs.config
}
}
}複製程式碼
這一步操作可以通過圖形化介面操作,更方便一些。右鍵專案,點選 Open Module Settings,開啟 Project Structure 視窗,在 Build Types 選項卡中設定。
隱藏簽名資訊
簽名資訊作為專案裡最為私密的一部分內容,如果直接暴露在 build.gradle 檔案中,顯然不夠安全。尤其是需要上傳到 GitHub 等託管平臺時。
比較妥當的做法是,在專案根目錄下新建一個專門用來儲存簽名資訊的檔案,並且將其新增到 ignore 檔案配置當中。具體操作過程如下:
第一步,新建一個 keystore.properties 檔案:
ReleaseKeyPassword=sampleKeyPwd
ReleaseKeyAlias=sampleAlias
ReleaseStorePassword=sampleStorePwd
ReleaseStoreFile=../sample.jks複製程式碼
第二步,在 build.gradle 檔案的最外層引入簽名資訊:
allprojects {
afterEvaluate { project ->
def propsFile = rootProject.file('keystore.properties')
def configName = 'config'
if (propsFile.exists() && android.signingConfigs.hasProperty(configName)) {
def props = new Properties()
props.load(new FileInputStream(propsFile))
android.signingConfigs[configName].storeFile = file(props['ReleaseStoreFile'])
android.signingConfigs[configName].storePassword = props['ReleaseStorePassword']
android.signingConfigs[configName].keyAlias = props['ReleaseKeyAlias']
android.signingConfigs[configName].keyPassword = props['ReleaseKeyPassword']
}
}
}複製程式碼
如此即可。其中第二步還有一種縮減版的寫法,也可以直接使用:
def keystorePropertiesFile = rootProject.file("keystore.properties");
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
signingConfigs {
config {
storeFile file(keystoreProperties['ReleaseStoreFile'])
storePassword keystoreProperties['ReleaseStorePassword']
keyAlias keystoreProperties['ReleaseKeyAlias']
keyPassword keystoreProperties['ReleaseKeyPassword']
}
}
}複製程式碼
當然,隱藏簽名資訊的方式還有很多。比如配置在本地環境變數中,或者 build.gradle 檔案中,或者編譯時從命令列中動態讀取輸入內容等,設定不同,讀取方式有所不同。
日誌開關
在 app/build.gradle 檔案中分別定義 debug 和 release 不同編譯模式的控制變數,變數名可自由更改:
buildTypes {
debug {
buildConfigField "boolean", "DEBUG_MODE", "true"
}
release {
buildConfigField "boolean", "DEBUG_MODE", "false"
}
}複製程式碼
重新編譯後,自動生成的 BuildConfig 類中包含上面定義的 DEBUG_MODE 屬性,即可使用。
Log 日誌開關更多解決方案,可參考:Android 中能夠作為 Log 開關的一些操作以及安全性淺談。
環境分離
開發中測試伺服器和生產伺服器的同時使用也是很常見的場景之一,如何在一臺裝置中同時安裝配置測試環境的 debug 包和生產環境的 release 包,也是需要面對的問題。不妨參考我的這篇文章:
Android 利用 Gradle 實現 app 的環境分離
參考連結
學習有關 Android、Gradle 和 Groove 更多詳細資訊,除了訪問 Gradle 官方網站,推薦你閱讀這些文章:
END
關於我:亦楓,部落格地址:yifeng.studio/,新浪微博:IT亦楓
微信掃描二維碼,歡迎關注我的個人公眾號:安卓筆記俠
不僅分享我的原創技術文章,還有程式設計師的職場遐想