之前写过一篇Gradle_05 自定义插件,这篇算是复习吧
编写gradle插件的目的就是把逻辑独立的代码抽取和封装
基本使用
1.现在,我们在app/build.gradle下添加如下代码,
- dshPlugin是我们自己编写的一个插件
- dshExtension是一个扩展,我们可以创建一个别名为dshE的扩展
- 执行.gradlew命令,输出「Hello 大欢安卓gradle扩展插件」
apply plugin:dshPlugin //自定义插件 class dshPlugin implements Plugin<Project>{ @Override void apply(Project target) { def extension = target.extensions.create('dshE',dshExtension) println("Hello ${extension.name}") } } class dshExtension{ def name = '大欢安卓gradle扩展插件' }
2.上面我们使用了别名,如果想要修改name的值,name我们可以使用别名dshE的一个闭包
dshE{
name 'dsh_gradle'
//等价于方法调用 -> name('dsh_gradle')->setName('dsh_gradle')
}
- 但是这样并不会输出修改后的值,我们需要在afterEvaluate也就是task执行完之后才能输出
class dshPlugin implements Plugin<Project>{
@Override
void apply(Project target) {
def extension = target.extensions.create('dshE',dshExtension)
println("Hello ${extension.name}")//修改前:大欢安卓gradle扩展插件
target.afterEvaluate {
println("Hello ${extension.name}")//修改后:Hello修改后:dsh_gradle
}
}
}
3.至此,我们完成了一个简单插件的编写,但是这样在我们的gradle文件中编写显然很笨拙,我们的目的是只需要一行apply代码apply plugin:dshPlugin
就能够方便地使用和配置插件,所以我们要换一种方式,编写能够方便使用的插件
自定义插件
在项目中新建buildSrc目录,这是安卓插件的默认目录,目录结构像这样
- resources/META-INF/gradle-plugins/*.properties 中的 * 是插 件的名称,例如 *.properties 是com.dshPlugin.properties ,最终在应用插件是的代码就 应该是:
apply plugin: 'com.dshPlugin'
- *.properties 中只有一行,格式是:
implementation-class=com.dsh.plugin.DshPlugin
- 其中等号右边指定了 Plugin 具体是哪个类
- Plugin 和 Extension 写法和在 build.gradle 里的写法一样 关于 buildSrc 目录
- 这是 gradle 的一个特殊目录,这个目录的 build.gradle 会自动被执行,即 使不配置进 settings.gradle。(实际上在 gradle 的 6.0 之后, buildSrc 已经成为了一个保留字,你在 settings.gradle 里配置的项目已经不允 许叫 buildSrc )
- buildSrc 所配置出来的 Plugin 会被自动添加到编译过程中的每一个 project 的 classpath,因此它们才可以直接使用 apply plugin: 'xxx' 的方 式来便捷应用这些 plugin
这样写的代码运行结果与在build.gradle中编写的效果是一致的
Transform
- 是什么:是由 Android 提供了,在项目构建过程中把编译后的文件(jar 文件和 class 文件)添加自定义的中间处理过程的工具
- 怎么写
- 先加上依赖:buildSrc/build.gradle
repositories { google() jcenter() } dependencies { implementation 'com.android.tools.build:gradle:3.5.4' } sourceCompatibility = "1.7" targetCompatibility = "1.7"
- 然后继承 com.android.build.api.transform.Transform ,创建 一个子类:
class DshTransform extends Transform { @Override String getName() { return 'dshTransform' } @Override Set<QualifiedContent.ContentType> getInputTypes() { return TransformManager.CONTENT_CLASS } @Override Set<? super QualifiedContent.Scope> getScopes() { return TransformManager.SCOPE_FULL_PROJECT } @Override boolean isIncremental() { return false } @Override void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException { def inputs = transformInvocation.inputs def outputProvider = transformInvocation.outputProvider inputs.each { it.jarInputs.each { File dest = outputProvider.getContentLocation(it.name, it.contentTypes, it.scopes, Format.JAR) println "Jar: ${it.file}, Dest: ${dest}" FileUtils.copyFile(it.file, dest) } it.directoryInputs.each { File dest = outputProvider.getContentLocation(it.name, it.contentTypes, it.scopes, Format.DIRECTORY) println "Dir: ${it.file}, Dest: ${dest}" FileUtils.copyDirectory(it.file, dest) } } } }
- 还能做什么:修改字节码 上面的这段代码只是把编译完的内容原封不动搬 运到目标位置,没有实际用处。要修改字节码,需要引入其他工具,例如 javassist。 javassist 的使用教程在网上有很多,可以搜索一下。
- 先加上依赖:buildSrc/build.gradle