一、学习目标
- 深入了解 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闭包操作是在任务里的业务逻辑处理完成之后才会执行,也就是在该任务的最后阶段执行。