Gradle实战-07-Gradle核心之Project详解和实战

一、学习目标

  • 深入了解 Project
  • Project核心API讲解
  • Project核心API实战

二、Gradle的Project API实战

对于Gradle来说根目录也是一个Project

./gradle projects 

执行上面的命令,得到如下内容,可以看出根目录也是一种Project。 

> Task :projects

------------------------------------------------------------
Root project
------------------------------------------------------------

Root project 'GradleLearn'
+--- Project ':app'
+--- Project ':buildSrc'
+--- Project ':oema'
+--- Project ':oemb'
\--- Project ':repository'
     \--- Project ':repository:viewpagerindicator'
//config.gradle
//Gradle相关API
this.getAllprojects()
//config.gradle
//获取根目录下的所有Project
this.getProjects()


def getProjects() {
    println '-----------'
    println 'Root Project'
    println '-----------'
    //获取所有的Project
    this.getAllprojects().eachWithIndex { Project project, int index ->
        if (index == 0) {
            println "Root Project ---->:${project.name}"
        } else {
            println "+--- Project ---->:${project.name}"
        }
    }
    //获取当前Project的所有子Project
//    this.getSubprojects().eachWithIndex { Project project, int index ->
//        if (index == 0) {
//            println "Root Project ---->:${project.name}"
//        } else {
//            println "+--- Project ---->:${project.name}"
//        }
//    }
}
//config.gradle
getParentProject()

//因为已经在rootProject中,所有没有父Project了
def getParentProject() {
    def name = this.getParent().name // 因为已经是rootProject,所以getParent()获取的是null
    println "the parent project name is :${name}"
}
//config.gradle
//project api 讲解下
//'app'就是在根工程下找名为 app 的Project
//在初始学习的时候 一般把闭包参数加上 这样便于理解
project('app') { Project project ->
    // println project.name
    apply plugin: 'com.android.application'
    group 'com.imooc'
    version '1.0.0-release'
    dependencies {

    }
    android {

    }

    //如上操作就可以将app 中的build.gradle的相关配置删除了,用此处代码块替代
}
//config.gradle
project('oema') {
    // println project.name
    apply plugin: 'com.android.library'
    group 'com.imooc'
    dependencies {

    }
    android {

    }
    //如上操作就可以将app 中的build.gradle的相关配置删除了
}

如上的操作,就可以把隶属于不同项目下【application或者library】的 build.gradle 文件汇集到一处进行处理。

//config.gradle
//配置当前节点工程和其subProject
allprojects {
    group 'com.imooc'
    version '1.0.0-release'
}


//测试Project oemb的group是通过allprojects配置的
println project('oemb').group
//config.gradle
//不包括当前节点工程,只包括子节点工程
subprojects { Project project ->
    //只有含有com.android.library插件的Project才能上传到Maven,其他则不能
    if (project.plugins.hasPlugin('com.android.library')) {
        println "subProject name is ${project.name}"
        if (project.name == 'viewpagerindicator') {
            apply from: '../../publishToMaven.gradle'
        } else {
            apply from: '../publishToMaven.gradle'
        }
    }
}
//publishToMaven.gradle
println 'start publishToMaven...'

以上便是 Project 相关的API,可以通过路径或者遍历的方式获取到对应的Project对象。

Project 自带属性和 Project扩展属性

创建扩展属性方法一:

//config.gradle
//扩展属性讲解一
//ext 加上闭包就是扩展属性
ext { compileSdkVersion=29 }
//在ext 的闭包中定义的扩展属性可以在其他gradle文件中使用
println "ext.compileSdkVersion--->${rootProject.ext.compileSdkVersion}"
//可以在根工程的build.gradle中引入config.gradle,然后将相关的属性配置在其中即可

//android 不能在config.gradle中引入android扩展属性,
//因为没有引入android插件 apply plugin: 'com.android.application'   
//android { compileSdkVersion this.compileSdkVersion}

创建扩展属性方法二:

//config.gradle
//扩展属性讲解二
//步骤一
//在gradle.properties 中定义属性
isLoadTest=false

//步骤二
//config.gradle
if (hasProperty('isLoadTest')){
    println getProperties().get('isLoadTest')
    println "isLoadTest ${getProperty('isLoadTest')}"
}

//执行./gradlew clean 就可以获取输出
isLoadTest false

文件操作属性讲解

文件相关API

//config.gradle
//getRootDir是获取根项目的目录地址
println "the root file path is: ${getRootDir().absolutePath}"
//getProjectDir()是获取包含项目build文件的目录
println "the project path is: ${getProjectDir().absolutePath}"
//Project的build目录
println "the buld path is: ${getBuildDir().absolutePath}"

//输出
the root file path is: /Users/zhangfengzhou/GitHub/GradleLearn
the project path is: /Users/zhangfengzhou/GitHub/GradleLearn
the buld path is: /Users/zhangfengzhou/GitHub/GradleLearn/build

文件定位API

//config.gradle
//1.文件API
//文件定位
//输出文件的内容
def result = getContent('build.gradle')
println result

def getContent(String path) {
    try {
        def file = file(path)
        return file.text
    } catch (Exception e) {
        e.printStackTrace()
        println 'file not found'
    }
    return null
}

//输出
// Top-level build file where you can add configuration 
// options common to all sub-projects/modules.
// 根目录下的build.gradle中添加 apply from: "xx" 相当于在xml中添加include
apply from: "config.gradle"
buildscript {
    repositories {
        google()
        jcenter()
        maven {
            // 本地Maven地址
            url uri("/Users/zhangfengzhou/maven")
        }
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.2'
        // 插件Maven地址
        classpath "com.lucky.plugin.gradle:demo:1.0.2"
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

ext{
    appCompileSdkVersion=27
    appBuildToolsVersion="27.0.3"
    appApplicationId="com.aragoncs.gradlelearnTest"
    appMinSdkVersion=15
    appTargetSdkVersion=27
    appVersionCode=1
    appVersionName="5.2"
}
task clean(type: Delete) {
    delete rootProject.buildDir
}

文件拷贝

//config.gradle
//2. 文件拷贝
//copy是Project中的API,不是TASK的api
//根据测试,可以得出该操作是在配置阶段执行
copy {
    from file('README.md')
    //into getRootProject().getBuildDir()
    //into getBuildDir()
    //将README.md文件拷贝到data目录中
    into file('data')
}

//通常在我们开发的过程中 会将编译好的apk 放到指定的目录下
copy {
    from file('app/build/outputs/apk')
    //into file('data/apk')
    into getRootProject().getBuildDir().path+"/apk/"
    //exclude 在拷贝的过程中排除json文件
    exclude '**/*.json'
}

文件树的遍历

//config.gradle
//对文件树进行遍历
//在Gradle的API使用的时候 一般都会省略掉set/get方法的前缀,直接接上后面的名称即可,不加括号
fileTree('app/build/outputs/apk') { FileTree fileTree ->
    fileTree.visit { FileTreeElement element -> //FileTreeElement就是每个树的节点
        println "the file name is:${element.file.name}" //省略调用get前缀
        copy {
            from element.file
            //将file拷贝到项目的build目录下
            into getRootProject().getBuildDir().path + "/test"
        }
    }
}

依赖相关

//config.gradle
//依赖相关API
//为什么去掉handler依然可以使用?因为使用了delegate
buildscript { ScriptHandler scriptHandler ->
    //配置我们工程的仓库地址
    scriptHandler.repositories {
        RepositoryHandler repositoryHandler->
            repositoryHandler.google()
            repositoryHandler.jcenter()
            repositoryHandler.mavenCentral()
            repositoryHandler.mavenLocal()
            repositoryHandler.maven { //配置私有仓库 可以从私有仓库下载依赖
                url  'http://localhost:8081/nexus/repository/'
                name 'personal'//一般是公司名称
                credentials{
                    username = 'admin'
                    password ='admin1233'
                }
            }
    }
    //配置我们工程的"插件"依赖地址,gradle中使用的插件
    //gradle本身就是一个编程框架,也是需要一些第三方的工具来配合使用
    //应用程序中使用的dependencies和buildScript中的是不一样的
    //应用程序中使用的dependencies是依赖的本地库或者第三方库
    //如果在config.gradle中进行了配置,则可以不必再build.gradle中进行配置了
    scriptHandler.dependencies {
        classpath 'com.android.tools.build:gradle:3.1.2'
        //classpath 'com.tencent.tinker-path-gradle-plugin:1.7.7'
    }
}

Gradle 执行外部命令

外部命令指的由 shell 命令

通过执行task可以拷贝文件

//1. ./gradlew build
//2. ./gradlew apkcopy

创建task

task('sayHi'){
    setGroup('imooc') //给task分组为imooc,方便在AS右侧gradle面板中查找task
    println ">>>>>>>>>>>>>>sayHi"
}

拷贝文件task

task apkcopy {
    doLast {
        println "-------------------->apkCopy before 2 开始拷贝任务"
        //gradle的执行阶段去执行
        def sourcePath = this.rootDir.path+ '/app/build/outputs/apk/'
        def destinationPath = '/Users/zhangfengzhou/Downloads/'
        //使用其他命令的时候只需要修改command即可
        def command = "mv -f ${sourcePath} ${destinationPath}" 
        exec {
            try {
                executable 'bash'
                args '-c', command
                println 'the command is execute success.'
            }catch(GradleException e){
                println 'the command is execute failed.'
            }
        }
    }
    println "-------------------->apkCopy before 1 先执行逻辑"
}

//执行apkcopy的task
./gradlew apkcopy

//输出
-------------------->apkCopy before 1 先执行逻辑
...
配置阶段结束之后...
> Task :apkcopy
-------------------->apkCopy before 2 开始拷贝任务
the command is execute success.

从上面的结果可以看出,doLast闭包操作是在任务里的业务逻辑处理完成之后才会执行,也就是在该任务的最后阶段执行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值