Gradle騷操作合集

Gradle騷操作

Gradle是谷歌欽定的android項(xiàng)目構(gòu)建工具。熟練使用gradle可以實(shí)現(xiàn)很多騷操作,比如多渠道打包,指定打包文件路徑和文件名等,而且實(shí)現(xiàn)方式不止一種。Gradle工具的編程語言叫做 Groovy, Groovy的語法相對寬松,有點(diǎn)類似javascript,怎么寫的人都有,但是最終目標(biāo)可能是一致的。
本文收錄一些Gradle騷操作供大家分享,經(jīng)本人驗(yàn)證可行,會提供完整Demo(Gradle會存在新舊版本兼容問題,運(yùn)行demo不要改動gradle版本配置):
Demo地址:https://github.com/18598925736/EnjoyGradleHank/commits/master

配置buildTypes{ xxx } 自定義"構(gòu)建類型“

...
android {
    ...
    // 配置簽名文件
    signingConfigs {
        debug {
            // 這里會使用默認(rèn)簽名
        }
        release {
            storeFile file("mykey.jks")
            storePassword "android"
            keyAlias "android"
            keyPassword "android"
            v2SigningEnabled true
        }
    }
    //level 1: 打包方式,默認(rèn)有debug和release,當(dāng)然可以自己加喜歡的
    buildTypes {

        //內(nèi)置 debug 和 release,但是我們可以忽略不計(jì)
        uat {
            // 測試環(huán)境可調(diào)試
            debuggable true
            signingConfig signingConfigs.release
        }
        prd {
            // 正式環(huán)境 可調(diào)式
            debuggable true
            signingConfig signingConfigs.release
        }
        online {
            // 正式發(fā)布包 不可調(diào)試
            debuggable false
            signingConfig signingConfigs.release
        }

    }

}

dependencies {
    ...
}

關(guān)鍵點(diǎn):

  • 配置buildTypes之前,必須 配signingConfigs,把簽名文件配好,否則,就會出現(xiàn) install Task缺失的情況

    image-20200117112348582.png
  • buildTypes里面默認(rèn)就有 debug和release,這一點(diǎn)在as里面可以看到,下圖中另外3個是我們自己加的type:
image-20200117112654199.png
  • 通過指定的buildType打包出來的apk,可以讀到 當(dāng)前包的buildType,并且用于app程序內(nèi)部,比如配置app的網(wǎng)絡(luò)環(huán)境設(shè)置(測試環(huán)境和正式環(huán)境),還有 是否支持日志打印屏蔽所有日志和放開所有日志),獲取的方式為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 } 自定義"多種打包風(fēng)味“

Demo地址:https://github.com/18598925736/EnjoyGradleHank/commits/master(切換到時(shí)間點(diǎn):78dc2ca

打包風(fēng)味 flavor 是 谷歌提供的 多渠道打包的官方手段。

app module 的 build.gradle

...

android {
    ...

    //level 2: 通過productFlavors打包配置,實(shí)現(xiàn)多維度風(fēng)味打包
    flavorDimensions "zone", "themeColor"
    // 定義多風(fēng)味
    productFlavors {
        /**
         * 越南版  每一個風(fēng)味選項(xiàng)都必須指定獨(dú)立的風(fēng)味值
         */
        vn {
            applicationId "com.global.vn.ftint"
            dimension "zone"
            manifestPlaceholders = [zone: "vn"]
        }

        /**
         * 國內(nèi)版
         */
        cn {
            applicationId "com.global.cn.ftint"
            dimension "zone"
            manifestPlaceholders = [zone: "cn"]
        }

        /**
         * 主題風(fēng)格為紅色
         */
        red {
            dimension "themeColor"
            manifestPlaceholders = [themeColor: "red"]
        }

        /**
         * 主題風(fēng)格為藍(lán)色
         */
        blue {
            dimension "themeColor"
            manifestPlaceholders = [themeColor: "blue"]
        }
    }
}

dependencies {
    ...
}

同時(shí)必須與 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>

關(guān)鍵點(diǎn):

  • 多風(fēng)味打包支持多維度,定義維度是在 flavorDimensions "zone", "themeColor" 這樣代碼中 , 此處定義了兩個維度:“地區(qū)”,“主題顏色”

  • 配置 風(fēng)味 productFlavor的時(shí)候必須指定維度:以下代碼就是指定維度為 zone ,維度的值,則是 cn,同時(shí)還指定了包名applicationId.

       cn {
                applicationId "com.global.cn.ftint"
                dimension "zone"
                manifestPlaceholders = [zone: "cn"]
            }
    
  • 多種維度的笛卡爾積的數(shù)值,就是 打包方式的總個數(shù),比如上方,zone維度2個風(fēng)味,themeColor維度2個風(fēng)味,所以風(fēng)味的總數(shù)是 2x2=4,在as中也能看到對應(yīng)的task,但是,此處的 維度總數(shù) 和 之前的buildType又形成了一個新的笛卡兒積,之前有5個(uat,prd,online,還有自帶的 debug和release ),所以能看到的task一共是 4x5=20

image.png

改變apk輸出路徑和文件名

目前查到有三種寫法:

  • 調(diào)用applicationVariants.all{} 重寫參數(shù)閉包,支持絕對路徑的寫法

    ...
    
    android {
        ...
    
        //level3
        applicationVariants.all { variant ->
            //這個修改輸出的APK路徑
            if (variant.buildType.name != "debug") {//防止AS無法安裝debug包(apk)
                variant.getPackageApplication().outputDirectory = new File(myPackageDir())
            }
            variant.getPackageApplication().outputScope.apkDatas.forEach { apkData ->
                //這個修改輸出APK的文件名
                apkData.outputFileName = "${appNamePrefix()}" +
                        variant.versionName + "_" +
                        "${releaseTime()}" + "_" +
                        variant.flavorName + "_" +
                        variant.buildType.name + "_" +
                        ".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 {
        ...
    }
    

    執(zhí)行 gradlew assembleCnBlueOnline 之后在 電腦桌面上的 myPackage 文件夾中會存在一個apk:

image-20200117145635162.png
  • 調(diào)用applicationVariants.all{} 重寫參數(shù)閉包,支持相對路徑的寫法

    ...
    
    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}" // 它不能使用絕對路徑,也就是說可以使用項(xiàng)目的相對路徑
        }
    }
    
    ...
    
    dependencies {
        ...
    }
    

    執(zhí)行 gradlew assembleCnBLueUat 之后,app module的build目錄內(nèi)會出現(xiàn) apk:

image-20200117145810555.png
  • 通過干涉task的執(zhí)行過程

    ...
    
    android {
        ...
    }
    
    /**
     * 當(dāng)有序任務(wù)圖中加進(jìn)去一個任務(wù)的時(shí)候,對它進(jìn)行處理,doLast重新定義完成之后的行為
     */
    tasks.whenTaskAdded { task ->
        if (task.name.equalsIgnoreCase("assembleCnBlueUat")) {
            println("=============發(fā)現(xiàn)任務(wù) ${task.name}")
    
            // 如果是assembleRelease任務(wù),在最后執(zhí)行導(dǎo)出apk以及mapping目錄到指定目錄
            task.doFirst {
                println("=============doFirst")
            }
            task.doLast {
                outputReleaseFile()
            }
        }
    }
    
    void outputReleaseFile() {
        println("=============outputReleaseFile")
        android.applicationVariants.all { variant ->
            // 如果是正式版打包
            if (variant.name.contains("cnBlueUat")) {
                println("=============準(zhǔn)備拷貝${variant.name}")
                File outputPath = new File(myPackageDir())
                println("==========把文件${variant.outputs[0].outputFile} \n 拷貝到 目標(biāo)位置:$outputPath")
                outputPath.mkdir()
                // 但是很明顯,這里的copy并沒有成功
                copy {// 拷貝apk文件
                    println("========開始拷貝...")
                    from variant.outputs[0].outputFile
                    into outputPath
                    // 重命名導(dǎo)出名稱
                    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 {
        ...
    }
    
    

    執(zhí)行 gradlew assembleCnBlueUat之后,電腦桌面上會出現(xiàn) mypackage目錄,內(nèi)部有一個apk

    image-20200117150006820.png

方式對比

  • 調(diào)用applicationVariants.all{} 重寫參數(shù)閉包的方式,修改輸出的絕對路徑,或者相對路徑,分別對應(yīng)兩個api:
    • 相對 outputs.first().outputFileName
    • 絕對 variant.getPackageApplication().outputScope.apkDatas 和 apkData.outputFileName
  • 使用 干涉task任務(wù)的方式,和 上面的方式比起來,寫法更加復(fù)雜,但是可控制的精度也更高,比如:它除了可以改變輸出路徑之外,還可以直接指定攔截哪些task,而不是像 applicationVariants.all閉包 一樣,一律變更輸出路徑和文件名。

先寫這么多。后續(xù)還有繼續(xù)補(bǔ)上

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容