Gradle 编程框架
1.groovy语法
2.Build Script Block
3.gradle api
前言
1.灵活性上: ANT和Maven 不能在构建过程中,做自定义操作.
2.颗粒度: gradle 代码开源, 根据task编译,可读,可改
3.扩展性 : 可以在gradle脚本中 可以自定义插件.自定义task
4.兼容性 : gralde代码中, 可以继续依赖 maven等框架
执行过程
initliazation 解析整个工程的所有project, 构建project对象
configuration 解析project对象中的task, 构建好 所欲task 的拓扑图
execution 执行具体的task 以及依赖
project API
project 树状结构
rootProject 根节点
parentProject 父节点
this.project 当前节点
subProject 子节点
project 中常用api介绍
//给某个project设置属性
project("module-user"){Project project ->
}
//可以给所有子项目 设置 自动推送到maven仓库
subprojects {Project project->
if(project.plugins.hasPlugin('com.android.library')){
apply from:"../publishToMaven.gradle"
}
}
//可以给所有子项目 设置 自动推送到maven仓库
subprojects {Project project->
if(project.plugins.hasPlugin('com.android.library')){
apply from:"../publishToMaven.gradle"
}
}
//配置所有项目的属性
allprojects {Project project->
group "com.ccj"
}
project的属性API
默认属性
为啥 配置文件必须叫build.gradle?
因为project中 第一个属性就是 ,默认的文件名,不可修改
/**
* The default project build file name.
*/
public static final String DEFAULT_BUILD_FILE = "build.gradle";
/**
* The hierarchy separator for project and task path names.
*/
public static final String PATH_SEPARATOR = ":";
/**
* The default build directory name.
*/
public static final String DEFAULT_BUILD_DIR_NAME = "build";
public static final String GRADLE_PROPERTIES = "gradle.properties";
public static final String SYSTEM_PROP_PREFIX = "systemProp";
public static final String DEFAULT_VERSION = "unspecified";
public static final String DEFAULT_STATUS = "release";
扩展属性
1.在rootProject或者当前project中,使用ext字段,来自定义属性
ext{
compileSdkVersion 25
}
在项目中可以用这个字段来使用
android {
//两种方式, rootProject. compileSdkVersion 也可以直接用complieVersion
//因为, project之间有继承关系, 如果父类有自定义的属性,那么结构树下的所有子project都会有这个属性.
compileSdkVersion compileSdkVersion //rootProject. compileSdkVersion
1.使用 apply from '配置路径'
首先,在根节点 新建一个config.gradle
.然后在各个子 项目中, 直接使用apply from: this.file("config.gradle")
即可.
/*
* 在rootProject中 引用
* apply from: this.file("config.gradle")
*
* 在子project中 这样引用 rootProject.ext.android.XXX 即可
* */
ext{
android=[
compileSdkVersion: 26,
buildToolsVersion: "26.0.1",
minSdkVersion: 21,
targetSdkVersion: 26,
versionCode: 1,
versionName: "1.0"
]
dependencies=[
compile:'com.android.support:support-v4:21.0.3',
compile: (project(':CommonSDK')) { exclude group: "com.android.support" },
provided: fileTree(dir: 'src/android5/libs', include: ['*.jar']),
provided: project(':main-host')
]
}
依赖相关
buildscript {ScriptHandler scriptHandler->
//配置工程的仓库地址 //为啥不用闭包参数就可以调用, 因为闭包的delegate设置的就是repositoryHandler
scriptHandler.repositories {RepositoryHandler repositoryHandler ->
repositoryHandler.jcenter()
// repositoryHandler.mavenCentral()//这也是为啥gradle能兼容maven的原因
// google()
//repositoryHandler.flatDir("这里可以直接依赖项目")
/* repositoryHandler.maven { //可以添加自己的
name "myMaven"
url 'http://localhost:8081:/nexus/respositoeries'
getCredentials{
username = 'amdin'
password = '123'
}
}*/
}
//配置工程中插件的依赖地址
scriptHandler.dependencies { DependencyHandler dependencyHandler ->
dependencyHandler. classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
依赖冲突
compile "com.android.support:support-v4:${SUPPORT_LIB_VERSION}"{
exclude module:'support-v4'// 排除依赖
transitive false //禁止传递依赖
changing =true //每次都会从服务器拉取
}
//compile //资源和类,都会被打进jar, 或者aar包中
//provided //编译的时候会引入,但是不会将这个包打入.
// 比如1.类的生成器(只在编译器起作用,不在运行时起作用).
// 2. 如果当前工程是类库,而且该工程的类库和 主工程有重复,则可以用这种方式.
执行外部命令
可以执行 bash
等命令
task(name:'apkcopy'){
doLast{
//执行外部的命令,比如bash命令
//将 apk copy到制定目录
def sourcePath =this.buildDir.path+"/outputs/apk"
def desationPath="/Users/chenchangjun/Downloads/"
def copycommand ="mv -f ${sourcePath} ${desationPath}"
exec {ExecSpec execSpec->
try {
execSpec.executable('bash')
args('-c',copycommand)
println 'copycommand is execute success!'
}catch (GradleException e){
println 'copycommand is execute failed'+e.printStackTrace()
}
}
}
}
Task
//直接通过task函数去创建
//group 组名,可以在右侧gralde面板中 见到group分组
//description 就是描述,类似于注释
task helloTask(group:'ccj',description:'task helloTask'){
println 'i am helloTask'
}
//容器创建
this.tasks.create(name:'hello2'){
setGroup('ccj')
setDescription('task hello')
println "i am hello2 "
}
//为什么 只执行了 helloTask,却连hello2也会被执行呢?
// 因为上述task 是在 配置阶段进行的, 而配置阶段,gralde中的代码都会执行.
//task 的方法
task helloExecuteTask(group:'ccj',description:'task helloExecuteTask'){
println 'i am helloExecuteTask'
doFirst{
println 'i am helloExecuteTask>>doFirst'
}
doLast{
println 'i am helloExecuteTask>>doLast'
}
}
helloExecuteTask.doFirst{
println 'i am helloExecuteTask.doFirst'
}
//计算build的执行时间
def startBuildTime,endBuildTime
this.afterEvaluate {Project project->
//保证要找的task 已经配置完毕
def preBuildTask=project.tasks.getByName('preBuild')
preBuildTask.doFirst {
println 'preBuildTask.doFirst>>>>>>>>'
startBuildTime=System.currentTimeMillis()
}
def buildTask=project.tasks.getByName('build')
buildTask.doLast {
endBuildTime=System.currentTimeMillis()
println "the buildTask time is >>>>>>>>>>>${endBuildTime-startBuildTime}"
}
}
task 依赖dependsOn
//task 依赖
task taskDepend1{
doLast{
println "taskDepend1"
}
}
task taskDepend2{
doLast{
println "taskDepend2"
}
}
task taskDepend3(dependsOn:[taskDepend1,taskDepend2]){
doLast{
println "taskDepend3"
}
}
task handleFile {
def srcFile = file('testdepends.xml')
def desFile = new File(this.buildDir.path + "generated/release/result.text")
println "build文件目录:"+this.buildDir.path
doLast {
println '开始解析对应的xml文件'
if (!desFile.exists()) {
desFile.createNewFile()
}
def releases = new XmlParser().parse(srcFile) //得到根节点
releases.children().each { Node node ->
def value = node.text()
println value
desFile.withWriter { writer ->
writer.write(value)
}
}
}
}
task testHandleFile(dependsOn: handleFile) {
println '解析完成'
}
Task 传递
/*TaskOutputs outputs
TaskInputs taskInputs*/
task must1{
doLast{
println 'must1.doLast'
}
}
task must2{
mustRunAfter must1
//shouldRunAfter
doLast{
println 'must2.doLast'
}
}
task must3{
mustRunAfter must2
doLast{
println 'must3.doLast'
}
}
/*
*
* gradle must2 must3 must1
*
> Task :zdm_router_register:must1
must1.doLast
> Task :zdm_router_register:must2
must2.doLast
> Task :zdm_router_register:must3
must3.doLast
*/
task的方法
gradle 约定大于配置, 有很多默认的配置,不改变也会安装默认的执行
Settings即 settings.gradle
gralde初始化会调用.
SourceSet
可以在android{}闭包下这样写
sourceSets{
main{
// jniLibs.src=['libs'] //修改so库的存放位置
res.srcDirs=['src/main/res', //可以用来对资源进行分包,以后便于维护,超级好用
'src/main/res-ad',
'src/main/res-player'
]
}
}
也可以在project根节点下这样写
this.android.sourceSets{
main{
// jniLibs.src=['libs'] //修改so库的存放位置
res.srcDirs=['src/main/res', //可以用来对资源进行分包,以后便于维护
'src/main/res-ad',
'src/main/res-player'
]
}
}