Gradle騷操作
Gradle是谷歌欽定的android專案構建工具。熟練使用gradle可以實現很多騷操作,比如多渠道打包,指定打包檔案路徑和檔名等,而且實現方式不止一種。Gradle工具的程式語言叫做 Groovy, Groovy的語法相對寬鬆,有點類似javascript,怎麼寫的人都有,但是最終目標可能是一致的。
本文收錄一些Gradle騷操作供大家分享,經本人驗證可行,會提供完整Demo(Gradle會存在新舊版本相容問題,執行demo不要改動gradle版本配置): Demo地https://github.com/18598925736/EnjoyGradleHank/commits/master
配置buildTypes{ xxx } 自定義"構建型別“...android { ... // 配置簽名檔案 signingConfigs { debug { // 這裡會使用預設簽名 } release { storeFile file("mykey.jks") storePassword "android" keyAlias "android" keyPassword "android" v2SigningEnabled true } } //level 1: 打包方式,預設有debug和release,當然可以自己加喜歡的 buildTypes { //內建 debug 和 release,但是我們可以忽略不計 uat { // 測試環境可除錯 debuggable true signingConfig signingConfigs.release } prd { // 正式環境 可調式 debuggable true signingConfig signingConfigs.release } online { // 正式釋出包 不可除錯 debuggable false signingConfig signingConfigs.release } }}dependencies { ...}
關鍵點:
通過指定的buildType打包出來的apk,可以讀到 當前包的buildType,並且用於app程式內部,比如配置app的網路環境設定(測試環境和正式環境),還有 是否支援日誌列印(遮蔽所有日誌和放開所有日誌),獲取的方式為BuildConfig.BUILD_TYPE: class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) tvBuildType.text = BuildConfig.BUILD_TYPE } }配置productFlavors{ xxx } 自定義"多種打包風味“Demo地址:https://github.com/18598925736/EnjoyGradleHank/commits/master(切換到時間點:78dc2ca)
打包風味 flavor 是 谷歌提供的 多渠道打包的官方手段。
app module 的 build.gradle
...android { ... //level 2: 通過productFlavors打包配置,實現多維度風味打包 flavorDimensions "zone", "themeColor" // 定義多風味 productFlavors { /** * 越南版 每一個風味選項都必須指定獨立的風味值 */ vn { applicationId "com.global.vn.ftint" dimension "zone" manifestPlaceholders = [zone: "vn"] } /** * 國內版 */ cn { applicationId "com.global.cn.ftint" dimension "zone" manifestPlaceholders = [zone: "cn"] } /** * 主題風格為紅色 */ red { dimension "themeColor" manifestPlaceholders = [themeColor: "red"] } /** * 主題風格為藍色 */ blue { dimension "themeColor" manifestPlaceholders = [themeColor: "blue"] } }}dependencies { ...}
同時必須與 manifest配合:
app module 的 AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.zhou.enjoygradle2"> <application ...> ... <meta-data android:name="ZONE" android:value="${zone}" /> <meta-data android:name="themeColor" android:value="${themeColor}" /> </application></manifest>
關鍵點:
改變apk輸出路徑和檔名目前查到有三種寫法:
重寫applicationVariants.all{} 引數閉包,支援相對路徑的寫法...android { ... // 或者,使用這種方式,只支援相對路徑 applicationVariants.all { variant -> String time = new Date().format('yyyyMMdd_HHmmss') String pkgName = "enjoy_${time}_v${defaultConfig.versionName}_${buildType.name}_${flavorName}.apk" outputs.first().outputFileName = "../../../${pkgName}" // 它不能使用絕對路徑,也就是說可以使用專案的相對路徑 }}...dependencies { ...}
通過干涉task的執行過程
...android { ...}/** * 當有序任務圖中加進去一個任務的時候,對它進行處理,doLast重新定義完成之後的行為 */tasks.whenTaskAdded { task -> if (task.name.equalsIgnoreCase("assembleCnBlueUat")) { println("=============發現任務 ${task.name}") // 如果是assembleRelease任務,在最後執行匯出apk以及mapping目錄到指定目錄 task.doFirst { println("=============doFirst") } task.doLast { outputReleaseFile() } }}void outputReleaseFile() { println("=============outputReleaseFile") android.applicationVariants.all { variant -> // 如果是正式版打包 if (variant.name.contains("cnBlueUat")) { println("=============準備拷貝${variant.name}") File outputPath = new File(myPackageDir()) println("==========把檔案${variant.outputs[0].outputFile} \\n 拷貝到 目標位置:$outputPath") outputPath.mkdir() // 但是很明顯,這裡的copy並沒有成功 copy {// 拷貝apk檔案 println("========開始拷貝...") from variant.outputs[0].outputFile into outputPath // 重新命名匯出名稱 rename { appNamePrefix() + variant.name + '_' + android.defaultConfig.versionName + '-' + releaseTime() + ".apk" } } } }}def myPackageDir(){ return "C:\\\\Users\\\\adminstrator\\\\Desktop\\\\myPackage"}def appNamePrefix() { return "HankZhou"}String releaseTime() { Date date = new Date() String dates = date.format("yyyyMMdd_hhmmss", TimeZone.getTimeZone("UTC")) return dates}dependencies { ...}
方式對比
寫applicationVariants.all{} 引數閉包的方式,修改輸出的絕對路徑,或者相對路徑,分別對應兩個api:
相對 outputs.first().outputFileName 絕對 variant.getPackageApplication().outputScope.apkDatas 和 apkData.outputFileName干涉task任務的方式,和 上面的方式比起來,寫法更加複雜,但是可控制的精度也更高,比如:它除了可以改變輸出路徑之外,還可以直接指定攔截哪些task,而不是像 重寫applicationVariants.all閉包 一樣,一律變更輸出路徑和檔名。
最新評論
延伸閱讀