语言插件

开发语言插件步骤如下:
在 build.gradle.kts 文件中添加 m8test sdk 依赖 , 为了减小插件apk大小, 如果是 M8Test Version Catalog 中存在的依赖库请使用 compileOnly 来依赖项目
import com.m8test.util.VersionUtils
plugins {
alias(m8test.plugins.android.application)
alias(m8test.plugins.kotlin.android)
}
android {
namespace = "com.m8test.language.rhino"
compileSdk = m8test.versions.compileSdk.get().toInt()
defaultConfig {
minSdk = m8test.versions.minSdk.get().toInt()
targetSdk = m8test.versions.targetSdk.get().toInt()
versionName = libs.versions.versionName.get()
versionCode = VersionUtils.getCode(versionName!!)
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.toVersion(m8test.versions.sourceCompatibility.get())
targetCompatibility = JavaVersion.toVersion(m8test.versions.targetCompatibility.get())
}
kotlinOptions {
jvmTarget = m8test.versions.jvmTarget.get()
}
}
dependencies {
compileOnly(m8test.m8test.sdk)
implementation(libs.rhino)
}
编写一个语言类继承 AbstractLanguage 并实现其中的抽象方法
getExtensions: 语言所支持的文件扩展名列表
getBuildPluginProviderClass: 构建项目的插件提供全类名
createScript: 用于创建脚本对象
getVariablePrefix: 全局变量创建时需要添加的前缀, 用于区分其他变量
getVariableSuffix: 全局变量创建时需要添加的后缀, 用于区分其他变量
package com.m8test.language.rhino
import com.m8test.plugin.api.ApkPluginProvider
import com.m8test.script.core.api.config.ScriptConfig
import com.m8test.script.core.api.engine.Script
import com.m8test.script.core.api.engine.ScriptContext
import com.m8test.script.core.api.engine.ScriptEngine
import com.m8test.script.core.api.language.LanguageExtension
import com.m8test.script.core.impl.language.AbstractLanguage
import com.m8test.script.core.impl.language.DefaultLanguageExtension
/**
* Description TODO
*
* @date 2025/02/08 15:14:10
* @author M8Test,
[email protected], https://m8test.com
*/
class RhinoLanguage(apkPluginProvider: ApkPluginProvider) : AbstractLanguage(apkPluginProvider) {
private val extensions =
listOf<LanguageExtension>(DefaultLanguageExtension("js", R.drawable.ic_javascript))
override fun getExtensions(): List<LanguageExtension> {
return extensions
}
override fun getBuildPluginProviderClass(): String {
return "com.m8test.language.rhino.RhinoLanguageBuildPluginProvider"
}
override fun createScript(
scriptEngine: ScriptEngine,
scriptContext: ScriptContext,
scriptConfig: ScriptConfig
): Script<*> {
return RhinoScript(this, scriptEngine, scriptContext, scriptConfig)
}
override fun getVariablePrefix(): String {
return "$"
}
override fun getVariableSuffix(): String {
return ""
}
}
在 AndroidManifest.xml 中配置插件信息
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:icon="@drawable/ic_launcher">
<meta-data
android:name="com.m8test.plugin.description"
android:value="本插件使用 rhino 实现 javascript 语言." />
<meta-data
android:name="com.m8test.plugin.url"
android:value="https://github.com/m8test/Plugins" />
<meta-data
android:name="com.m8test.plugin.type"
android:value="language" />
<meta-data
android:name="com.m8test.plugin.name"
android:value="RhinoJs" />
<meta-data
android:name="com.m8test.plugin.className"
android:value="com.m8test.language.rhino.RhinoLanguage" />
</application>
</manifest>
com.m8test.plugin.type: 插件类型, 此处为 language
com.m8test.plugin.name: 插件名称, 可以为任意字符串
com.m8test.plugin.className: 实现了插件的全类名
编写一个脚本类继承 AbstractScript 并实现其中的抽象方法
createStringExecutor: 创建字符串脚本执行器, 每次执行字符串脚本时会调用此方法
createFileExecutor: 创建文件脚本执行器, 每次执行文件脚本时会调用此方法
createProjectExecutor: 创建项目脚本执行器, 每次执行项目脚本时会调用此方法
脚本执行器需要继承 AbstractScriptExecutor 类, RhinoScriptExecutor 继承该类, 并且有三个子类, 分别为
编写一个类实现 BuildPluginProvider, 此类需要返回构建插件(工程插件, 设置插件)
package com.m8test.language.rhino
import com.m8test.script.builder.api.BuildPluginProvider
import com.m8test.script.builder.api.Plugin
import com.m8test.script.builder.api.Project
import com.m8test.script.builder.api.Settings
import com.m8test.script.core.api.engine.ScriptContext
/**
* Description TODO
*
* @date 2025/02/08 15:14:10
* @author M8Test,
[email protected], https://m8test.com
*/
class RhinoLanguageBuildPluginProvider : BuildPluginProvider {
override fun getProjectPlugins(): Map<String, (context: ScriptContext) -> Plugin<Project>> {
return mapOf(RhinoProjectPlugin.ID to { context -> RhinoProjectPlugin(context) })
}
override fun getSettingsPlugins(): Map<String, (context: ScriptContext) -> Plugin<Settings>> {
return emptyMap()
}
}
编写一个类实现 Plugin, 此类用于实现如何构建一个脚本项目, 在上一个步骤中返回此类对象
package com.m8test.language.rhino
import com.m8test.language.rhino.task.CompileRhinoInitTask
import com.m8test.language.rhino.task.CompileRhinoLibTask
import com.m8test.language.rhino.task.CompileRhinoSrcTask
import com.m8test.script.builder.api.Plugin
import com.m8test.script.builder.api.Project
import com.m8test.script.builder.impl.PluginIds
import com.m8test.script.core.api.engine.ScriptContext
/**
* Description TODO
*
* @date 2025/02/08 15:14:10
* @author M8Test,
[email protected], https://m8test.com
*/
class RhinoProjectPlugin(private val context: ScriptContext) : Plugin<Project> {
override fun apply(target: Project) {
if (!target.getPlugins().has(PluginIds.getLibrary())) {
target.getPlugins().apply(PluginIds.getLibrary())
}
// 添加一个task
target.getTasks().add(CompileRhinoLibTask(target), null)
target.getTasks().add(CompileRhinoInitTask(target), null)
target.getTasks().add(CompileRhinoSrcTask(target), null)
}
override fun getId(): String {
return ID
}
companion object {
const val ID = "rhino-js"
}
}
编写构建任务, 一般需要实现三个任务, 分别用于构建 lib, init 以及 src 目录, 项目中剩余的其他目录有默认实现, 也就是会直接复制所有文件到目标目录, 如果有需要的话也可以修改默认实现.
Last modified: 29 April 2025