自定义gradle插件
因为gradle插件是在编译过程中生效, 不用修改代码就能实现很多功能, 几乎每个app都使用了gradle插件。最近一直在深挖Android Gradle的学习,发现其实所谓的Android Gradle也不过就是一个gradle插件,所以如果能学好gradle的开发,我们就可以利用Gradle为我们做很多事,比如干预Android的打包,打出我们想要地apk或者jar,再或者多渠道设置等等。
建立插件工程
使用Android Studio实现对Gradle的开发
buildSrc方式
buildSrc是Android的保留名称,只能作为plugin插件使用。
在Android Studio新建一个工程,再新建一个Java Library形式的Module作为插件模块,删除里面所有文件,在src文件夹中建立main/groovy ,main/resources,留下build.gradle,目录结构如下:
修改build.gradle配置如下代码:
apply plugin: 'groovy'
dependencies {
compile gradleApi()
compile localGroovy()
}
这样就可以在groovy文件夹中添加对应代码进行gradle开发了。
java Library方式
与buildSrc创建不同的过程就是名字不是buildSrc,如果是新建java Library的形式需要添加依赖:
dependencies {
compile gradleApi()
compile localGroovy()
compile 'com.android.tools.build:gradle:2.3.3'
}
区别
使用buildSrc可以在该Project中的任何module中直接使用,如果使用新建的Java Library的形式,需要上传Gradle插件到本地代码库
插件测试
groovy新建一个TestPlugin.groovy文件(注意后缀一定要是groovy):
public class TestPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
println("aaaaaa")
}
}
gradle插件使用都需要在build.gradle中apply,如:
apply plugin: 'com.android.application'
所以他需要有一个对外的名字,这就需要resources下的文件起作用了。
在resources文件夹下建立 META-INF/gradle-plugins
然后在这个文件夹下建一个properties文件,这个文件的名字就是对外的名字,所以起的时候要慎重,我们暂时叫hhh.properties,插件入口在hhh.properties里声明,文件内容如下:
implementation-class=TestPlugin
然后我们利用Android Studio自带的app module做个测试:
apply plugin: 'com.android.application'
apply plugin: 'hhh'
然后执行打包可以发现输出中:
上传到本地仓库
如果使用java Library,需要上传到本地仓库才能引用,现在就需要介绍一下如何进行操作
- 首先需要修改build.gradle文件:
apply plugin: 'groovy'
apply plugin: "maven"
dependencies {
compile gradleApi()
compile localGroovy()
}
uploadArchives{
repositories{
mavenDeployer{
repository(url:"http://10.1.11.182:8080/nexus-2.1.2/content/repositories/releases/"){
authentication(userName: "admin", password: "admin123")
}
pom.groupId = 'com.test.plugin' // 组名
pom.artifactId = 'test' // 插件名
pom.version = '2.0.0' // 版本号
}
}
}
-
然后执行这个uploadArchives Task
-
app module如果需要使用,需要添加依赖
apply plugin: 'com.android.application'
apply plugin: 'hhh'
buildscript{
repositories{
maven{
url uri('../repo')
}
}
dependencies{
classpath 'com.test.plugin:test:2.0.0'
}
}
Extension
前面介绍了如何编写一个插件,但是并不能通过外面传递参数进来,如果想使用一些自定义的参数可以使用Extension,我们可以再建立一个MyExtension.groovy
class MyExtension {
def aaa;
def bbb;
}
然后找到插件类
public class TestPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.extensions.create("deep", MyExtension)
project.afterEvaluate {
MyExtension extension = project['deep'];
String a = extension.aaa
String b = extension.bbb
println("deep:${a},${b}")
}
}
}
- Project本身是支持拓展的,所以提供了create方法,project.extensions.create(“deep”, MyExtension)
这句代码的意思是将我们的自定义的类作为Project的一个属性值,key是deep。
项目中gradle执行的时候,会先解析setting.gradle,然后是build.gradle,如果想在解析build.gradle之前做点事,可以使用project.beforeEvaluate如果想在解析build.gradle之后做点事可以project.afterEvaluate。
apply plugin: 'hhh'
deep{
aaa="this is a"
bbb="this is b"
}
在解析完build.gradle之后,在访问project中我们设置的属性,即可得到build.gradle中设入的值。
执行任务打印:
android
通过上面的例子,我想到了正经的android工程不是也是这样配置的吗,我们可以测试一下。
都知道android工程中的project,样式如下:
android {
compileSdkVersion 26
buildToolsVersion "26.0.3"
defaultConfig {
applicationId "deep.com.testgroovy"
minSdkVersion 14
targetSdkVersion 26
versionCode 1
versionName "1.0"
}
}
这些不都是project的一个拓展类吗?我们可以测试一下,修改插件:
@Override
void apply(Project project) {
project.afterEvaluate {
println("包名:"+project['android']["defaultConfig"].applicationId)
}
我取project下的android,然后再取android下的defaultConfig,就可以得到包名,执行一下看看:
果然可以获取包名,同理,在打包的时候可以拿到更多的设置信息。