settings.gradle(对应Settings.java)决定哪些工程须要被gradle处理,占用了整个gradle生命周期的三分之一,即Initialzation初始化阶段。html
对默认的文件位置进行修改,从而让gradle知道哪一种资源要从哪些文件夹中去查找。java
// sourceSets是能够调用屡次的
android {
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
sourceSets {
main {
res.srcDirs = ['src/main/res',
'src/main/res-ad',
'src/main/res-player']
}
}
}
// sourceSets通常状况下是一次性配置
android {
sourceSets {
main {
jniLibs.srcDirs = ['libs']
res.srcDirs = ['src/main/res',
'src/main/res-ad',
'src/main/res-player']
}
}
}
// 使用编程的思想,配置sourceSets
this.android.sourceSets{
main {
jniLibs.srcDirs = ['libs']
res.srcDirs = ['src/main/res',
'src/main/res-ad',
'src/main/res-player']
}
}
复制代码
Gradle中的Plugin是对完成指定功能的Task封装的体现,只要工程依赖了某个Plugin,就能执行该Plugin中全部的功能,如:使用java插件,就能够打出jar包,使用Android插件,就能够生成apk、aar。android
apply plugin: 'groovy'
sourceSets {
main {
groovy {
srcDir 'src/main/groovy'
}
resources {
srcDir 'src/main/resources'
}
}
}
复制代码
最后,Async一下工程,buildSrc就会被识别出来了,总体目录如图:git
与java同样,在groovy目录下,建立一个包,再建立一个插件类(如:com.lqr.gradle.study.GradleStudyPlugin),该插件类必须实现Plugin接口。github
注意:gradle插件类是.groovy文件,不是.java文件编程
import org.gradle.api.Plugin
import org.gradle.api.Project
/** * 自定义Gradle插件 */
class GradleStudyPlugin implements Plugin<Project> {
/** * 插件引入时要执行的方法 * @param project 引入当前插件的project */
@Override
void apply(Project project) {
println 'hello gradle study plugin. current project name is ' + project.name
}
}
复制代码
在编写完插件类的逻辑以后,须要在META-INF.gradle-plugins目录下建立一个properties文件(建议以插件类包名来命名,如:com.lqr.gradle.study.properties),在该properties中声明插件类,以此来指定插件入口。api
该properties文件的名字将做为当前gradle插件被app工程引用的依据。闭包
implementation-class=com.lqr.gradle.study.GradleStudyPlugin // 若是报错 Could not find implementation class 'xxx' 的话,通常是类全路径有问题,默认包不须要写包路径,修改以下便可: // implementation-class=GradleStudyPlugin 复制代码
打开app工程的build.gradle,应用上面的自定义gradle插件,并Async。app
apply plugin: 'com.android.application'
apply plugin: 'com.lqr.gradle.study'
android {
...
}
复制代码
能够看到,在gradle的配置阶段,就输出了前面自定义插件的apply方法中的日志。 maven
插件每每会在gradle脚本中进行参数配置,如在android{}中,能够配置compileSdkVersion等参数,其实本质上,就是在gradle脚本中使用闭包方式建立了一个javaBean,并将其传递到插件中被插件识别读取而已。步骤以下:
1)建立一个实体类,声明成员变量,用于接收gradle中配置的参数。(能够理解为就是javaBean,不过要注意,该文件后缀是.groovy,不是.java)
class ReleaseInfoExtension {
String versionCode
String versionName
String versionInfo
String fileName
ReleaseInfoExtension() {}
@Override
String toString() {
return "versionCode = ${versionCode} , versionName = ${versionName} ," +
" versionInfo = ${versionInfo} , fileName = ${fileName}"
}
}
复制代码
2)在自定义插件中,对当前project进行扩展。
class GradleStudyPlugin implements Plugin<Project> {
/** * 插件引入时要执行的方法 * @param project 引入当前插件的project */
@Override
void apply(Project project) {
// 这样就能够在gradle脚本中,经过releaseInfo闭包来完成ReleaseInfoExtension的初始化。
project.extensions.create("releaseInfo", ReleaseInfoExtension)
}
}
复制代码
3)打开在app工程的build.gradle,经过扩展key值命名闭包的方式,就能够配置指定参数了。
apply plugin: 'com.lqr.gradle.study'
releaseInfo {
versionCode = '1.0.0'
versionName = '100'
versionInfo = '第一个app信息'
fileName = 'release.xml'
}
复制代码
4)接收参数,如:
def versionCodeMsg = project.extensions.releaseInfo.versionCode
复制代码
自定义插件无非就是封装一些经常使用Task,因此,扩展Task才是自定义插件的最重要的一部分。
扩展Task也很简单,继承DefaultTask,编写TaskAction注解方法,下面以 “把app版本信息写入到xml文件中”的task 为例,注释很详细,很少赘述:
import groovy.xml.MarkupBuilder
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
class ReleaseInfoTask extends DefaultTask {
ReleaseInfoTask() {
group 'lqr' // 指定分组
description 'update the release info' // 添加说明信息
}
/** * 使用TaskAction注解,可让方法在gradle的执行阶段去执行。 * doFirst其实就是在外部为@TaskAction的最前面添加执行逻辑。 * 而doLast则是在外部为@TaskAction的最后面添加执行逻辑。 */
@TaskAction
void doAction() {
updateInfo()
}
private void updateInfo() {
// 获取gradle脚本中配置的参数
def versionCodeMsg = project.extensions.releaseInfo.versionCode
def versionNameMsg = project.extensions.releaseInfo.versionName
def versionInfoMsg = project.extensions.releaseInfo.versionInfo
def fileName = project.extensions.releaseInfo.fileName
// 建立xml文件
def file = project.file(fileName)
if (file != null && !file.exists()) {
file.createNewFile()
}
// 建立写入xml数据所须要的类。
def sw = new StringWriter();
def xmlBuilder = new MarkupBuilder(sw)
// 若xml文件中没有内容,就多建立一个realease节点,并写入xml数据
if (file.text != null && file.text.size() <= 0) {
xmlBuilder.releases {
release {
versionCode(versionCodeMsg)
versionName(versionNameMsg)
versionInfo(versionInfoMsg)
}
}
file.withWriter { writer ->
writer.append(sw.toString())
}
} else { // 若xml文件中已经有内容,则在原来的内容上追加。
xmlBuilder.release {
versionCode(versionCodeMsg)
versionName(versionNameMsg)
versionInfo(versionInfoMsg)
}
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(sw.toString() + '\r\n')
writer.append(line + '\r\n')
}
}
}
}
}
}
复制代码
与建立扩展属性同样,扩展Task也须要在project中建立注入。
/** * 自定义Gradle插件 */
class GradleStudyPlugin implements Plugin<Project> {
/** * 插件引入时要执行的方法 * @param project 引入当前插件的project */
@Override
void apply(Project project) {
// 建立扩展属性
// 这样就能够在gradle脚本中,经过releaseInfo闭包来完成ReleaseInfoExtension的初始化。
project.extensions.create("releaseInfo", ReleaseInfoExtension)
// 建立Task
project.tasks.create("updateReleaseInfo", ReleaseInfoTask)
}
}
复制代码
再次Async工程以后,就能够在Idea的gradle标签里看到自定义好的Task了。
以上就是自定义gradle插件的核心内容了,可是,这种在工程下直接建立buildSrc目录编写的插件,只能对当前工程可见,因此,若是须要将咱们自定义好的grdle插件被其余工程所使用,则须要单首创建一个库工程,并建立如buildSrc目录下全部的文件,最后上传maven仓库便可,这部分可自行百度了解。
Manipulation tasks(操做task) | Gradle Android插件用户指南翻译
自定义Apk输出位置:
this.afterEvaluate {
this.android.applicationVariants.all { variant ->
def output = variant.outpus.first() // 获取变体输出文件(outputs返回是一个集合,但只有一个元素,即输出apk的file)
def apkName = "app-${variant.baseName}-${variant.versionName}.apk"
output.outputFile = new File(output.outputFile.parent, apkName)
}
}
复制代码
variant.baseName : baidu-release variant.name : baiduRelease