我们出于自己的目的,要开发实际业务场景的插件来辅助项目构建。 自定义二进制插件,可以使用 java,kotlin,或者 groovy 来编码,因为他们都是基于JVM的编程语言,最终都会生成class交给JVM去执行。groovy提供了更多插件相关的api,有一些情况用groovy能直接达成效果,而不需要去引入其他类库。
步骤
以kotlin为例:
创建一个java library
每个androidStudio版本的操作界面可能各不相同,这是 Android Studio Electric Eel | 2022.1.1 Patch 2 版本的截图。
引入 必要的 依赖
包括两部分,一个是gradleApi,必须引入。
另外就是其他的,我们编写编码需要用到的其他依赖库,比如 发送网络请求的 okhttp,生成二维码的zxing ,接入华为云的 obs等等。
plugins {
id 'java-library'
id 'org.jetbrains.kotlin.jvm' // kotlin依赖
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation gradleApi() // 必须的gradle依赖
// 引入其他工具类库
implementation 'com.squareup.okhttp3:okhttp:3.14.6' // 使用最新版okhttp居然无法引用,很诡异
implementation 'com.huaweicloud:esdk-obs-java-bundle:3.21.8' // 引入 华为云
implementation 'com.google.zxing:core:3.4.1' // 二维码生成器
implementation 'org.springframework:spring-core:2.5.6'
implementation 'net.dongliu:apk-parser:2.5.3' // apk解析工具
}
新建一个Project实现类
import com.android.build.gradle.AppExtension
import com.tw.lib.bean.AutoUploadBean
import org.gradle.api.Plugin
import org.gradle.api.Project
class AutoUploadPlugin : Plugin<Project> {
override fun apply(project: Project) {
println("======== 自动上传插件初始化 =========")
// 配置外来参数, 表示插件的使用者可以在gradle文件中写 相关的参数
val autoUploadBean = project.extensions.create("autoUpload", AutoUploadBean::class.java)
project.afterEvaluate {
val appExtension = it.extensions.getByType(AppExtension::class.java)
appExtension.applicationVariants.all { v ->
v.outputs.all { out ->
val file = out.outputFile // 输出的apk文件
val name = out.name
project.tasks.create(
"auto_upload_$name",
AutoUploadTask::class.java,
file,
autoUploadBean
)
}
}
}
}
}
比如上面我要做一个实现自动上传的插件 AutoUploadPlugin
,它必须实现
Plugin<Project>
接口,并实现其中的apply方法。方法内部写上你要做的操作。
一个project是由多个Task组合而成,下面的代码中,我我在apply方法中创建了一个名叫 autoUpload
的 额外参数,并创建了一个名为 AutoUploadTask
的 任务。
创建 AutoUploadTask 任务
public class AutoUploadTask extends DefaultTask {
private File file;
private final AutoUploadBean autoUploadBean;
@Inject
public AutoUploadTask(File file, AutoUploadBean autoUploadBean) {
setGroup("autoUpload");
this.file = file;
this.autoUploadBean = autoUploadBean;
}
@TaskAction
public void action() throws IOException {
System.out.println("做你想做的事情");
}
}
这里有一些要素必须提到,
首先,setGroup是自定任务的分组,这个分组最终会呈现在androidStudio右侧的gradle面板中。
其次,步骤3中执行了这么一段代码:
project.tasks.create(
"auto_upload_$name",
AutoUploadTask::class.java,
file,
autoUploadBean
)
这其实是在反射创建 AutoUploadTask对象,后面的file和autoUploadBean其实就是入参,所以我们必须提供一个带这两个参数的构造函数。
最后,在接收到 file和 autoUploadBean 外来参数之后,我们可以在 重写的action方法中使用它们来完成我们自己想要的的操作。
AutoUploadBean类的内容为:
open class AutoUploadBean {
// 华为OBS账号
var userName: String? = null
// 华为OBS密码
var pwd: String? = null
// 华为OBS桶
var domain: String? = null
// 是否使用分段上传
var usePartUpload: Boolean = false
// 下载二维码的输出目录
var buildRootDir: String? = null
}
到这里,插件基本上就编写完成了。
插件注册
每一个插件都有全局唯一一个 id ,这个id注册在 /src/main/resources/META-INF/gradle-plugins
中,我们在 这个目录下,创建一个 自定义名称的com.tw.autoUpload.properties
文件,自定义的名称就是我们插件的唯一ID,文件内容为:implementation-class=com.tw.lib.AutoUploadPlugin
,也就是我们自定义Plugin的全类名。
使用插件
在 要使用插件模块的build.gradle中
apply plugin:'com.tw.autoUpload'
或者
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'com.tw.autoUpload' // 使用插件
}
并且指定插件的额外参数:
autoUpload {
userName 'c00293388'
pwd 'Wd2A@zFJ1234'
domain 'hwstaff_DigitalPayment'
usePartUpload false
buildRootDir 'C:\Users\zwx1245985\Desktop\saved'
}
执行插件任务
至此完成,经过编译之后,我们就能在 任务分组 autoupload之下,使用 auto_upload任务去执行上传操作了。