对于gradle中相关代码的解释这里引用的是字节跳动团队的推文
深入理解Gradle框架之一:Plugin, Extension, buildSrc
但是还是简单的介绍一下,就拿我们常见的app/build.gradle文件来说。 我们最先看到的其实是
apply plugin: 'com.android.application'
他告诉了gradle,我们使用了一个名字为com.android.application的插件(关于插件的定义等在之前我已经说过了 Gradle Transform的定义过程),接下来常见的就是
android{}
dependencies{}
这两个叫做Extension,对于我们来说其实就是Javabean,是为插件提供数据的,在插件的task开始执行时需要用到这些数据。比如我定义一个TestExtension
class TestExtension{
String name
String userNo
String cookie
}
在app/build.gradle中使用
test {
name "testStr"
userNo "testUserNo"
cookie "testCookie"
}
因为这是我自定义的一个extension,所以要在plugin中添加这个Extension,
def customExtensions = project.getExtensions().create("test", TestExtension.class)
其实就是在自定插件的apply方法中通过create创建一个extension,注意这里的“test”就是在build.gradle中添加这个extension的名字。好了到此准备工作就做完了。那么回到题目所述问题,打包完成之后,先上传到蒲公英,后发消息到钉钉。这里就涉及到几个问题
- 在哪儿获取打包之后
- 如何创建一个任务
- 如何在打包之后插入一个上传任务
- 在插件中的上传文件如何编写
这里涉及到执行顺序的问题,那么我们就看看gradle的执行流程
- 初始化阶段:就是执行 settings.gradle,它的下一个阶段是配置阶段
- 配置阶段:解析每个 project 中的 build.gradle。解析每个子目录中的 build.gradle。在这两个阶段之间,我们可以加一些定制化的 Hook。这当然是通过 API 来添加的。这个阶段完成之后,整个 build 的 project 以及内部的 Task 关系就确定了。一个 Project 包含很多 Task,每个 Task 之间有依赖关系此时会建立一个有向图来描述 Task 之间的依赖关系。所以,我们可以添加一个 HOOK,即当 Task 关系图建立好后,执行一些操作。
- 执行阶段:就是按顺序执行配置阶段完成的有向无环图中的task。一个新建的APP,点击安装时他的构建过程如下
def assembleTask=project.tasks.findByName("assembleDebug")
当然这个创建的代码是在自定义plugin的apply中。接下来是第二个问题,如何创建一个task,其实他与extension的创建差不多,比如这里的uploadTask
UploadToPgyTask task = project.tasks.create("uploadTask", UploadToPgyTask.class)
而这个类的定义如下
class UploadToPgyTask extends DefaultTask {
def cookie = ""
def userNo = ""
void init(String userNo,String cookie) {
setDescription("test Task")
setGroup("releaseHelPer")
this.userNo = userNo
this.cookie = cookie
}
@TaskAction
void upLoadToPyg() {
System.out.print("执行了上传任务到蒲公英\n")
NetApi api = NetWorkManager.getInstent().getNetApi()
Call<GiftStateBean> call = api.getGiftBagRewardState(userNo, cookie)
Response<GiftStateBean> response = call.execute()
if (response.successful)
System.out.print("上传成功")
}
}
可以看到如果要定义task的话需要继承DefaultTask,并且利用@TaskAction注解来指定task执行时的入口,至于里面的上传使用的是retrofit,用法就跟在APP中使用一样,只不过这里的上传任务用的是同步方法。现在的第二个问题也解决了。那就看第三个问题,如何保证执行顺序,其实就一行代码
assembleTask.finalizedBy(task)
接下来就是最后一个问题了上传文件。这里给的是一段普通的post请求,如果是文件上传的话用retrofit也是很简单的,只是需要在定义call的时候定义成文件类型,调用跟这里的一样(不懂的可以看 retrofit的使用 一文),至此整个流程就结束了,那么完整的plugin代码如下
class TestPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.getExtensions().create("test", TestExtension.class)
//其实是gradle的回调,它会在配置阶段结束后调用
project.afterEvaluate {
//获取android这个extension下的属性值
Collection<ApplicationVariant> appVarients = ((AppExtension) project.getExtensions().getByName("android")).getApplicationVariants()
for (ApplicationVariant applicationVariant : appVarients) {
//判断当前的buildType:debug或者是release
if (applicationVariant.getBuildType().getName().equalsIgnoreCase("debug")) {
//获取自定义extension的值
String deliveredName = ((TestExtension) project.getExtensions().getByName("test")).name
String deliveredUserNo = ((TestExtension) project.getExtensions().getByName("test")).userNo
String deliveredCookie = ((TestExtension) project.getExtensions().getByName("test")).cookie
print("CustomPlugin ==>>name==>> $deliveredName==>>userNo==>>$deliveredUserNo==>>cookie==>>$deliveredCookie")
//创建上传蒲公英的task
UploadToPgyTask task = project.tasks.create("uploadTask", UploadToPgyTask.class)
task.init(deliveredUserNo,deliveredCookie)
//找到系统打包的那个task,当然这里还可以根据buildType获取Release的
def assembleTask=project.tasks.findByName("assembleDebug")
//把上传蒲公英的任务放到assemble之后
assembleTask.finalizedBy(task)
//创建发送消息到钉钉的任务
SendMsgToDingDingTask secondTask = project.tasks.create("sendMsgTask", SendMsgToDingDingTask.class)
secondTask.init()
//该任务放到上传任务之后
task.finalizedBy(secondTask)
}
}
}
}
}
我们在app/build.gradle中使用该插件
apply plugin: 'com.android.application'
apply plugin: 'com.mwy.test'
test {
name "testStr"
userNo "6247133"
cookie "54NaELPpO165t4ZTfy5bUZBegNcfuRU1+Qk5tJGxVpc="
}
直接点击运行,我们看build日志 首先在项目开始编译之前会读取配置的参数