1. 前言
最近工作部分内容涉及到gradle
插件的编写,在粗浅了解和编码之余来简单梳理下编写一个gradle
插件的相关用法。这里编写的插件还是发布到在前面两篇博客中的Artifactory
仓库中。一共分为如下几步:
- 配置定义
gradle
插件、上传到Artifactory
仓库的环境; - 配置插件工程模板、编写具体的
Task
; - 发布和应用插件;
2. hello-plugin
2.1 环境准备和配置
创建一个java
gradle
项目,然后进入配置过程。使用buildScript
脚本来配置仓库地址:
buildscript {
apply from: './setting.gradle'
repositories {
mavenLocal()
maven {
allowInsecureProtocol true
url "http://${maven_host}:8082/artifactory/android_group/"
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.3'
//http://plugins.gradle.org/plugin/com.jfrog.artifactory
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.15.2"
}
}
其中com.android.tools.build:gradle
是Google
推出的构建Android
应用程序的插件,而build-info-extractor-gradle
这个插件就是前面文章提到过的发布到私有Artifactory
仓库的插件。当然,若不使用改仓库可不添加,可以使用maven-publish
发布到本地仓库。然后,应用一下对应的插件:
apply plugin: 'java'
apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.artifactory'
同样配置一下依赖的仓库:
repositories {
contextUrl = "http://${maven_host}:8082/artifactory" //The base Artifactory URL if not overridden by the publisher/resolver
publish {
repository {
repoKey = 'android_local'
username = "${admin}"
password = "${password}"
maven = true
}
}
}
添加一下开发插件所需的依赖:
dependencies {
implementation gradleApi()
implementation 'com.android.tools.build:gradle:3.4.3'
}
最后配置一下发布的脚本:
apply plugin: 'maven-publish'
artifactory {
contextUrl = "http://${maven_host}:8082/artifactory" //The base Artifactory URL if not overridden by the publisher/resolver
publish {
repository {
repoKey = 'android_local'
username = "${admin}"
password = "${password}"
maven = true
}
}
}
publishing {
publications {
mengfou(MavenPublication) {
groupId = 'com.mengfou'
artifactId = 'hello-plugin-demo'
version = "1.0.0"
artifact("$buildDir/libs/${project.getName()}.jar")
pom.withXml {
def dependencies = asNode().appendNode("dependencies")
configurations.implementation.allDependencies.each {
if(it.version != null && it.group != null) {
def dependency = dependencies.appendNode("dependency")
dependency.appendNode("groupId", it.group)
dependency.appendNode("artifactId", it.name)
dependency.appendNode("version", it.version)
}
}
}
}
}
}
artifactoryPublish {
dependsOn("clean")
finalizedBy("assemble")
contextUrl = "http://${maven_host}:8082/artifactory/"
publications ('mengfou') // mengfou定义在前面
clientConfig.publisher.repoKey = 'android_local' //上传到的仓库地址
clientConfig.publisher.username = "${admin}" //artifactory 登录的用户名
clientConfig.publisher.password = "${password}" //artifactory 登录的密码
}
同步一下项目可以看见任务中就出现了我们的artifactoryPublish
这个任务。
2.2 配置项目,编写Task
在项目的resources
目录下创建META-INF/gradle-plugins
目录,然后新建一个自定义的插件名.properties
文件,比如:hello-plugin-demo.properties
,其值配置为:implementation-class=com.mengfou.plugin.HelloPlugin
。该文件也就是我们插件的入口。
下面正式来编写一个Task
(假设该task
需要向打包的apk
中塞入一个类),比如:
public class HelloTask extends DefaultTask {
@TaskAction
public void doAction() {
System.out.println("================");
}
}
然后配置一下:
public class HelloPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getLogger().info("------------------configure----------------------");
project.afterEvaluate(new Action<Project>() {
@Override
public void execute(Project project) {
AppExtension appExtension = project.getExtensions().getByType(AppExtension.class);
for (ApplicationVariant applicationVariant : appExtension.getApplicationVariants()) {
String variantName = applicationVariant.getName();
Task beforeTask = TaskHelper.findTaskByName(project, "compileDebugJavaWithJavac", variantName);
HelloTask task = project.getTasks().create(getTaskName(variantName), HelloTask.class);
task.dependsOn(beforeTask);
List<Task> tasks = TaskHelper.findTaskByName(project, PackageApplication.class, variantName);
for (Task systemTask : tasks) {
systemTask.dependsOn(task);
}
}
}
});
}
private String getTaskName(String variantName) {
variantName = variantName.substring(0, 1).toUpperCase() + variantName.substring(1);
return "hello" + variantName + "PluginDemo";
}
}
定义一个帮助类用来查找系统Task
:
public class TaskHelper {
public static List<Task> findTaskByName(Project project, Class<? extends Task> clazz, String variantName) {
TaskCollection<? extends Task> targetTasks = project.getTasks().withType(clazz).matching(task -> {
return task.getName().toLowerCase().contains(variantName);
});
return new ArrayList<>(targetTasks);
}
public static Task findTaskByName(Project project, String taskName, String variantName) {
if(!taskName.contains(variantName)) {
taskName = taskName.replace(variantName.equalsIgnoreCase("debug") ? "release" : "debug", variantName);
}
return project.getTasks().getByName(taskName);
}
}
2.3 发布和使用插件
只需要找到右边gradle
中的artifactoryPublish
这个task
,双击执行即可。
最后就是在一个app
项目中引用:
// 引入
classpath "com.mengfou:hello-plugin-demo:1.0.3"
// 使用
apply plugin: 'hello-plugin-demo'
同步后可以看见自定义的这两个Task
:
为了更加方便知道这个任务是否会被正确执行,可以使用:
gradlew assemRel --console=plain > fa.txt
根据执行结果,可以看见:
确实该任务得到了执行。
3. 系统task
不可避免的我们需要知道一些系统task
,那么如何获取当前项目的所有系统task
呢,其实前面我们使用的 --console=plain
参数可以做到,但不够简洁。也可以使用:
gradlew :app:tasks --all
4. 附
- 【Android Studio Gradle】发布aar到私有Artifactory仓库
- 【Android Studio Gradle】使用Artifactory构建本地仓库