Gradle 編程框架
1.groovy語法
2.Build Script Block
3.gradle api
前言
1.靈活性上: ANT和Maven 不能在構(gòu)建過程中,做自定義操作.
2.顆粒度: gradle 代碼開源, 根據(jù)task編譯,可讀,可改
3.擴展性 : 可以在gradle腳本中 可以自定義插件.自定義task
4.兼容性 : gralde代碼中, 可以繼續(xù)依賴 maven等框架
執(zhí)行過程
initliazation 解析整個工程的所有project, 構(gòu)建project對象
configuration 解析project對象中的task, 構(gòu)建好 所欲task 的拓撲圖
execution 執(zhí)行具體的task 以及依賴
project API
project 樹狀結(jié)構(gòu)
rootProject 根節(jié)點
parentProject 父節(jié)點
this.project 當前節(jié)點
subProject 子節(jié)點
project 中常用api介紹
//給某個project設(shè)置屬性
project("module-user"){Project project ->
}
//可以給所有子項目 設(shè)置 自動推送到maven倉庫
subprojects {Project project->
if(project.plugins.hasPlugin('com.android.library')){
apply from:"../publishToMaven.gradle"
}
}
//可以給所有子項目 設(shè)置 自動推送到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之間有繼承關(guān)系, 如果父類有自定義的屬性,那么結(jié)構(gòu)樹下的所有子project都會有這個屬性.
compileSdkVersion compileSdkVersion //rootProject. compileSdkVersion
1.使用 apply from '配置路徑'
首先,在根節(jié)點 新建一個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')
]
}
依賴相關(guān)
buildscript {ScriptHandler scriptHandler->
//配置工程的倉庫地址 //為啥不用閉包參數(shù)就可以調(diào)用, 因為閉包的delegate設(shè)置的就是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 //每次都會從服務(wù)器拉取
}
//compile //資源和類,都會被打進jar, 或者aar包中
//provided //編譯的時候會引入,但是不會將這個包打入.
// 比如1.類的生成器(只在編譯器起作用,不在運行時起作用).
// 2. 如果當前工程是類庫,而且該工程的類庫和 主工程有重復(fù),則可以用這種方式.
執(zhí)行外部命令
可以執(zhí)行 bash
等命令
task(name:'apkcopy'){
doLast{
//執(zhí)行外部的命令,比如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函數(shù)去創(chuàng)建
//group 組名,可以在右側(cè)gralde面板中 見到group分組
//description 就是描述,類似于注釋
task helloTask(group:'ccj',description:'task helloTask'){
println 'i am helloTask'
}
//容器創(chuàng)建
this.tasks.create(name:'hello2'){
setGroup('ccj')
setDescription('task hello')
println "i am hello2 "
}
//為什么 只執(zhí)行了 helloTask,卻連hello2也會被執(zhí)行呢?
// 因為上述task 是在 配置階段進行的, 而配置階段,gralde中的代碼都會執(zhí)行.
//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的執(zhí)行時間
def startBuildTime,endBuildTime
this.afterEvaluate {Project project->
//保證要找的task 已經(jīng)配置完畢
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 '開始解析對應(yīng)的xml文件'
if (!desFile.exists()) {
desFile.createNewFile()
}
def releases = new XmlParser().parse(srcFile) //得到根節(jié)點
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 約定大于配置, 有很多默認的配置,不改變也會安裝默認的執(zhí)行
Settings即 settings.gradle
gralde初始化會調(diào)用.
SourceSet
可以在android{}閉包下這樣寫
sourceSets{
main{
// jniLibs.src=['libs'] //修改so庫的存放位置
res.srcDirs=['src/main/res', //可以用來對資源進行分包,以后便于維護,超級好用
'src/main/res-ad',
'src/main/res-player'
]
}
}
也可以在project根節(jié)點下這樣寫
this.android.sourceSets{
main{
// jniLibs.src=['libs'] //修改so庫的存放位置
res.srcDirs=['src/main/res', //可以用來對資源進行分包,以后便于維護
'src/main/res-ad',
'src/main/res-player'
]
}
}