Gradle生命周期&project&task

gradle声明周期的监听方式

  • 在项目的build.gradle
/**
 * 配置阶段开始前的监听回调
 */
this.beforeEvaluate {
    println '配置阶段开始前.........'
}
/**
 * 配置阶段完成以后的回调
 */
this.afterEvaluate {
    println '配置阶段完成.........'
}
/**
 * gradle执行完毕后的回调监听
 */
this.gradle.buildFinished {
    println 'gradle执行完毕.........'
}

this.gradle.beforeProject {
    println 'gradle执行之前.........'
}

this.gradle.afterProject {
    println 'gradle执行之后.........'
}

  • 在module的build.gradle
this.project.afterEvaluate { project ->
    println '配置阶段完成.........'
}


project相关api

在项目的build.gradle中
  • 获取所有的project
/**
 * 获取所有的project
 */
def getProjects() {
    println '-------------------------'
    println 'Root Project'
    println '-------------------------'
    this.getAllprojects().eachWithIndex { Project project, int i ->
        if (i == 0) {
            println "Root project:${project.name}"
        } else {
            println "+--- project :${project.name}"
        }
    }
}

this.getProjects()

/**
-------------------------
Root Project
-------------------------
Root project:ParallelSearchGradle
+--- project :app
+--- project :lib_base
+--- project :lib_res
+--- project :module_fun
+--- project :module_me
+--- project :module_search
+--- project :module_thing
+--- project :module_use
-------------------------
**/
  • 获取所有的子project
/**
 * 获取所有的子project
 * @return
 */
def getSubProjects() {
    println '-------------------------'
    println 'Sub Project'
    println '-------------------------'
    this.getSubprojects().each { Project project ->
        println "+--- project :${project.name}"
    }
}

this.getSubProjects()

/**
-------------------------
Sub Project
-------------------------
+--- project :app
+--- project :lib_base
+--- project :lib_res
+--- project :module_fun
+--- project :module_me
+--- project :module_search
+--- project :module_thing
+--- project :module_use

**/
  • 获取根project
**
 * 获取根project
 * @return
 */
def  getMRootProject(){
    def name = this.getRootProject().name
    println "根project是:${name}"
}
this.getMRootProject()

/**

根project是:ParallelSearchGradle

**/
  • 在父工程中对子工程进行配置(这里依 app为例,也可以为module_use等)
/**
 *在父工程中对子工程进行配置(这里依 app为例,也可以为module_use等)
 */
project('app'){ Project project->
    apply plugin: 'com.android.application'
    group 'com.fuyao'
    version '1.0.0'
    dependencies{

    }
    android{

    }
}

  • 配置当前结点工程和其subproject的所有project(module)
/**
 * 配置当前结点工程和其subproject的所有project(module)
 */
allprojects {
    group 'com.fuyao'
    version '1.0.0'
}

println project('module_use').group//com.fuyao
  • 不包括当前结点工程,只包括它的subproject(子module)
/**
 * 不包括当前结点工程,只包括它的subproject(子module)
 */
subprojects {
    if (project.plugins.hasPlugin('com.android.library')){
        apply from:'../public.gradle'
    }
}


在module的build.gradle中
  • 获取父project
/**
 * 获取父project
 */
def getParentProject() {
    def name = this.getParent().name
    println "他的父project 是:${name}"
}

this.getParentProject()

/**
他的父project 是:ParallelSearchGradle

**/
  • 获取根project
/**
 * 获取根project
 * @return
 */
def getMRootProject() {
    def name = this.getRootProject().name
    println "根project是:${name}"
}

this.getMRootProject()

/**
根project是:ParallelSearchGradle

**/


属性

  • 扩展属性
/**
 * 扩展属性  在project的build.gradle中进行声明
 */
subprojects {
    ext{
        compileSdkVersion=28
        libSupport='com.android.support:support-v4:28.0.0'
    }
}
ext{
    minSdkVersion=19
    libConstraint='com.android.support.constraint:constraint-layout:1.1.3'
}

或者 新建gradle文件(例:public.gradle)

ext {
    android = [targetSdkVersion: 28,
               applicationId     : 'com.fuyao.parallelsearch']
    signconfigs = []
    dependence = []
}

在project的build.gradle中引入

//引入公共库
apply from: this.file('public.gradle')

或者在gradle.properties中声明

#************************************公共配置********************************

##最低版本minSdkVersion
MIN_SDK_VERSION=19
##最高版本targetSdkVersion
TAR_SDK_VERSION=28
##编译版本compileSdkVersion
COMPILER_SDK_VERSION=28
##版本号
VERSION_CODE=1
##版本名称
VERSION_NAME=1.0

在module中进行引用


android {
    compileSdkVersion this.compileSdkVersion
    dataBinding {
        enabled = true
    }
    defaultConfig {
        applicationId rootProject.ext.android.applicationId
//        minSdkVersion this.project.minSdkVersion
        //或者
        minSdkVersion this.minSdkVersion
        targetSdkVersion rootProject.ext.android.targetSdkVersion
        versionCode project.VERSION_CODE as int
        versionName project.VERSION_NAME
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    ....
}
dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation this.libSupport
//    implementation this.project.libConstraint
    //或者
    implementation this.libConstraint
}

file相关API

  • 在project的build.gradle中
/**
 * 获取根工程的文件路径
 */
println "root file path==>${getRootDir().absolutePath}"
//root file path==>E:\workspace\work_demo\ParallelSearchGradle

/**
 * 获取当前工程build文件路径
 */
println "build file path==>${getBuildDir().absolutePath}"
//build file path==>E:\workspace\work_demo\ParallelSearchGradle\build

/**
 * 获取当前工程文件路径
 */
println "project file path==>${getProjectDir().absolutePath}"
//project file path==>E:\workspace\work_demo\ParallelSearchGradle


/**
 *从当前gradle中寻找file
 * @param path
 * @return
 */
def getContent(String path){
    try {
        def  file=this.file(path)//files
        //相当于当前的project工程开始查找
        return file.text
    }catch(Exception e){
        println '文件没有找到'
    }
}
println getContent('public.gradle')

/**
ext {
    android = [targetSdkVersion: 28,
               applicationId     : 'com.fuyao.parallelsearch']
    signconfigs = []
    dependence = []
}

**/
  • 在module的build.gradle中
/**
 * 获取根工程的文件路径
 */
println "root file path==>${getRootDir().absolutePath}"
//root file path==>E:\workspace\work_demo\ParallelSearchGradle

/**
 * 获取当前工程build文件路径
 */
println "build file path==>${getBuildDir().absolutePath}"
//build file path==>E:\workspace\work_demo\ParallelSearchGradle\app\build

/**
 * 获取当前工程文件路径
 */
println "project file path==>${getProjectDir().absolutePath}"
//project file path==>E:\workspace\work_demo\ParallelSearchGradle\app


  • 文件copy
/**
 * 文件copy
 */
copy {
    from file('ceshi.jks')
    into getRootProject().getBuildDir()//拷贝到根目录的build下
}

copy {
    from file('ceshi.jks')
    into getRootDir()//拷贝到根目录下
}
/**
 * 拷贝文件夹
 */
copy {
    from file('dev/release/')
    into getRootProject().getBuildDir().path + "/release/"//拷贝到根目录的build下release中
    //筛选不想复制的内容
    exclude { details ->
        details.file.name.endsWith('.json')
    }
    //更改文件名称
    rename { fileName ->
        fileName.replace('parallelsearch', 'huang')
    }
}

/**
 * 对文件树进行遍历
 */
fileTree('dev/release/') { FileTree fileTree ->
    fileTree.visit { FileTreeElement element ->
        println "file name==>${element.file.name}"
        copy {
            from element.file
            into getRootProject().getBuildDir().path + "/test/"
        }
    }
}

在这里插入图片描述

  • 执行外部命令(以copy apk包到windows桌面为例)

tasks.create('apkcopy') {
    doLast {
        //gradle的执行阶段去执行
        def sourcePath = this.buildDir.path + '\\outputs\\apk'
        def desationPath = 'C:\\Users\\Administrator\\Desktop\\downloads'
        def command = "xcopy /s ${sourcePath} ${desationPath}"
        try {
            exec {
                workingDir  'C:\\Users\\Administrator\\Desktop'
                commandLine  'cmd', '/c', command
                println "执行外部命令copy成功"
            }
        } catch (Exception e) {
            e.printStackTrace()
            println "执行外部命令copy失败"
        }
    }
}

依赖相关API


buildscript {
    //配置我们工程的仓库地址
    repositories {
        jcenter()
        mavenCentral()
        mavenLocal()
        ivy {}
        maven {
            name 'personal'
            url '仓库地址url'
            credentials {
                username = 'admin'
                password = 'admin123'
            }
        }
    }
    //配置我们工程的“插件”依赖地址
    dependencies {
        classpath 'com.android.tools.build:gradle:3.4.1'
    }
}



sourceSets

/**
在android{}中调用
**/
android{
	...
	sourceSets {
	        main {
	            jniLibs.srcDirs = ['libs']//修改so库存放位置
	            res.srcDirs = ['src/main/res',
	                           'src/main/res-ad',
	                           'src/main/res-buy']//修改res路径
	        }
	    }
}
/**
 * 在外部调用sourceSets
 */
this.android.sourceSets{
    main {
        jniLibs.srcDirs = ['libs']//修改so库存放位置
        res.srcDirs = ['src/main/res',
                       'src/main/res-ad',
                       'src/main/res-buy']//修改res路径
    }
}

相关配置均在AndroidSourceSet类中

Task任务

  • task定义
/**
 * task定义,直接通过task函数去创建
 */
task helloTask {
    println "定义一个task"
}
task helloTask1(group: 'huang', description: 'task study') {
    println "定义一个helloTask1"
}
/**
 * task定义,通过TaskContainer去创建Task
 */
this.tasks.create(name: 'helloTask2') {
    println "定义一个helloTask2"
}

this.tasks.create(name: 'helloTask3') {
    setGroup('huang')//添加分组
    setDescription('task study')//添加描述信息
    println "定义一个helloTask3"
}

给任务添加group会新增自定义的组方便在as任务列表中找到,否则均在other中
  • doFirst,doLast使用

/**
 * doFirst使用
 */
task helloTask4(group: 'huang', description: 'task study') {
    println "定义一个helloTask4"
    doFirst {
        println "定义一个helloTask4-doFirst,他的group是:" + group
    }
    doLast {
        println "定义一个helloTask4-doLast,他的group是:" + group
    }
}
helloTask4.doFirst {
    println "定义一个helloTask4-doFirst,他的description是:" + description
}
helloTask4.doLast {
    println "定义一个helloTask4-doLast,他的description是:" + description
}
/**
 * 计算build执行时长
 */
def startBuildTime, endBuildTime
this.afterEvaluate {
    //保证要找的task已经配置完毕
    def preBuildTask = project.tasks.getByName('preBuild')
    preBuildTask.doFirst {
        startBuildTime = System.currentTimeMillis()
        println '开始编译时间:' + startBuildTime
    }
    def buildTask = project.tasks.getByName('build')
    buildTask.doLast {
        endBuildTime = System.currentTimeMillis()
        println "编译时间:${endBuildTime - startBuildTime}"
    }
}
  • Task依赖

/**
 * Task依赖
 */

task exHello {
    doLast {
        println 'hello'
    }
}

task exWorld {
    doLast {
        println 'world'
    }
}

task exMain(dependsOn: exHello) {
    doLast {
        println 'main'
    }
}
//任务多依赖
task exMain1 {
    dependsOn exHello, exWorld
    doLast {
        println 'main'
    }
}
task exMain2(dependsOn: [exHello, exWorld]) {
    doLast {
        println 'main2'
    }
}

在被依赖的任务执行完成后才执行当前任务

  • 通过运行结果指定依赖
/**
 * 通过运行结果指定依赖
 */

task lib1 {
    doLast {
        println 'lib1'
    }
}
task lib2 {
    doLast {
        println 'lib2'
    }
}

task nolib {
    doLast {
        println 'nolib'
    }
}
task exMain3(dependsOn: [exHello, exWorld]) {
    dependsOn this.tasks.findAll {
        return it.name.startsWith('lib')
    }
    doLast {
        println 'main3'
    }
}

  • 执行顺序
/**
 * 执行顺序
 */
task taskX {
    doLast {
        println 'taskX'
    }
}
task taskY {
    mustRunAfter taskX
    doLast {
        println 'taskY'
    }
}
task taskZ {
    mustRunAfter taskY
    doLast {
        println 'taskZ'
    }
}

按照 taskX ->taskY ->taskZ 顺序执行

  • 案例解析版本迭代信息
/**
 * 案例解析版本迭代信息
 */
task handleReleaseFile {
    def srcFile = file('releases.xml')
    def destDir = new File(this.buildDir, 'generated/release/')
    doLast {
        println '开始解析版本迭代信息对应的xml文件...'
        destDir.mkdir()
        def releases = new XmlParser().parse(srcFile)
        releases.resource.each { releaseNode ->
            //解析每个release结点的内容
            def name = releaseNode.versionName.text()
            def code = releaseNode.versionCode.text()
            def info = releaseNode.versionInfo.text()
            //创建文件并写入结点数据
            def destFile = new File(destDir, "release-${name}.txt")
            destFile.withWriter { writer ->
                writer.write("${name}->${code}->${info}")
            }
        }
    }
}

task handleReleaseFileTest(dependsOn: handleReleaseFile) {
    def dir = this.fileTree(this.buildDir.path + 'generated/release/')
    doLast {
        dir.each {
            println "file name is: ${it}"
        }
        println '解析版本迭代信息对应的xml文件测试完成'
    }
}
  • task输入版本信息
ext {
    versionName = '1.0.5'
    versionCode = '105'
    versionInfo = 'App的第5个版本,上线基本架构核心功能'
    destFile = file('releases.xml')
    if (destFile != null && !destFile.exists()) {
        destFile.createNewFile()
    }
}
task writeTask {
    //为task指定输入
    inputs.property('versionCode', this.versionCode)
    inputs.property('versionName', this.versionName)
    inputs.property('versionInfo', this.versionInfo)
    //为Task指定输出
    outputs.file(destFile)
    doLast {
        def data = inputs.getProperties()
        File file = outputs.getFiles().getSingleFile()
        //将map传化为实体对象
        def versionMsg = new Versionmsg(data)
        //将实体对象转换为xml
        def sw = new StringWriter()
        def xmlBuilder = new MarkupBuilder(sw)
        if (file.text != null && file.text.size() <= 0) {
            //文件中没有内容
            xmlBuilder.releases {
                release {
                    versionCode(versionMsg.versionCode)
                    versionName(versionMsg.versionName)
                    versionInfo(versionMsg.versionInfo)
                }
            }
            file.withWriter { writer -> writer.append(sw.toString()) }
        } else {
            //已有版本信息
            xmlBuilder.releases {
                release {
                    versionCode(versionMsg.versionCode)
                    versionName(versionMsg.versionName)
                    versionInfo(versionMsg.versionInfo)
                }
            }
            //将生成的xml数据插到根结点之前
            def lines = file.readLines()
            def lengths = lines.size() - 1
            file.withWriter { writer ->
                lines.eachWithIndex { String line, int index ->
                    if (index != lengths) {
                        writer.append(line + "\r\n")
                    } else if (index == lengths) {
                        writer.append('\r\r\n' + sw.toString() + '\r\n')
                        writer.append(lines.get(lengths))
                    }
                }
            }
        }
    }
}
class Versionmsg {
    String versionCode
    String versionName
    String versionInfo
}


  • 挂接结束自动执行
/**
 * 挂接结束执行
 */

this.project.afterEvaluate { project ->
    def buildTask = project.tasks.getByName('build')
    if (buildTask == null) throw GradleException("build task is not found")
    buildTask.finalizedBy "writeTask"
}

  • task读取版本信息
task readTask {
    inputs.files destFile
    doLast {
        def file = inputs.files.getSingleFile()
        println file.text
    }
}

/**
 * task 输入输出时默认先执行写,后执行读
 */
task taskTest {
    dependsOn readTask, writeTask
    doLast {
        println '输入输出任务结束'
    }
}
发布了316 篇原创文章 · 获赞 660 · 访问量 122万+

猜你喜欢

转载自blog.csdn.net/huangxiaoguo1/article/details/103618209