Gradle Sao collection operation

EDITORIAL;

Gradle is Google handpicked android project build tool. Familiar with gradle can achieve a lot Sao operations, such as multi-channel packages, specify the package file path and file name, etc., and to achieve more than one way. Gradle programming language tool called Groovy, Groovy syntax is relatively loose, somewhat similar to javascript, how people have written, but the ultimate goal may be the same.


This article included some of Gradle Sao operation for all to share, as I verified feasible, will provide a complete Demo (Gradle there will be compatibility problems old and new versions, running demo do not change gradle version configuration):
Demo Address: https://github.com/18598925736/ EnjoyGradleHank / commits / master

 

Configuring buildTypes {xxx} custom "type construct"

 

...
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 {
    ...
}

key point:

  • Before configuring buildTypes, must be equipped signingConfigs, the signature file with a good, otherwise, the situation will be missing install Task

 

  • buildTypes which have default debug and release, it can be seen as inside, the other three in the figure below is our own added type:

 

  • Packed out by designated buildType apk, you can read the current buildType package, and for internal app program, such as configuring the app network environment settings ( test environment and formal environment), as well as support log printing ( screen all logs and release all logs), acquired way BuildConfig.BUILD_TYPE:
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        tvBuildType.text = BuildConfig.BUILD_TYPE
    }
}

 

Configuring productFlavors {xxx} Custom "flavor variety pack"

Demo Address: https://github.com/18598925736/EnjoyGradleHank/commits/master (switching time 78dc2capoint: )

Flavor flavor is packaged multi-channel Google provides a means of packaging the official.

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 {
    ...
}

And must cooperate with the 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>

key point:

  • Multi-flavor pack supports multi-dimensional, dimension is defined in flavorDimensions "zone", "themeColor"this code, defined here two dimensions: "Region", "Theme Colors"
  • Configuration flavor productFlavor must specify the time dimension: the following code is to specify the dimensions for the zone, the value of a dimension is cn, and also specifies the package name applicationId.
   cn {
            applicationId "com.global.cn.ftint"
            dimension "zone"
            manifestPlaceholders = [zone: "cn"]
        }
  • Numerical Cartesian product of multiple dimensions, is the total number of packaging methods, such as upper, zone 2 flavor dimension, two dimensions of the themeColor flavor, the flavor is the total number of 2x2 = 4, as also seen in the corresponding the task, however, and the total number of dimensions here before buildType and the formation of a new Cartesian product, preceded by five (uat, prd, online, as well as built-in debug and release), we are able to see the task total of 4x5 = 20

 

Apk change the output path and file name

Currently, there are three found written:

  • Rewrite applicationVariants.all{}parameters closures, absolute path wording
...

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 {
    ...
}

Execution gradlew assembleCnBlueOnlineafter myPackage file on your desktop folder there will be a apk:

 

  • Rewriting applicationVariants.all{}parameter closure support relative path wording
...

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 {
    ...
}

Execution gradlew assembleCnBLueUatafter, will appear in the build directory apk app module is:

 

  • Through the implementation of interference 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 {
    ...
}

Execution gradlew assembleCnBlueUatafter, there will be mypackage directory on your desktop, inside there is a apk

 

方式对比

  • 重写applicationVariants.all{} 参数闭包的方式,修改输出的绝对路径,或者相对路径,分别对应两个api:
    • 相对 outputs.first().outputFileName
    • 绝对 variant.getPackageApplication().outputScope.apkDatas 和 apkData.outputFileName
  • 使用 干涉task任务的方式,和 上面的方式比起来,写法更加复杂,但是可控制的精度也更高,比如:它除了可以改变输出路径之外,还可以直接指定拦截哪些task,而不是像 重写applicationVariants.all闭包 一样,一律变更输出路径和文件名。

先写这么多。后续还有继续补上,欢迎关注,有问题一起交流学习~



 

发布了17 篇原创文章 · 获赞 0 · 访问量 176

Guess you like

Origin blog.csdn.net/chuhe1989/article/details/104267046
Sao