首頁>技術>

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閉包 一樣,一律變更輸出路徑和檔名。

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • ASP.NET CORE WEBAPI SWAGGER快速上手秒學即用