M8Test Help

语言插件

22

开发语言插件步骤如下:

  1. 在 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) }
  1. 编写一个语言类继承 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 "" } }
  1. 在 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: 实现了插件的全类名

  1. 编写一个脚本类继承 AbstractScript 并实现其中的抽象方法

  • createStringExecutor: 创建字符串脚本执行器, 每次执行字符串脚本时会调用此方法

  • createFileExecutor: 创建文件脚本执行器, 每次执行文件脚本时会调用此方法

  • createProjectExecutor: 创建项目脚本执行器, 每次执行项目脚本时会调用此方法

脚本执行器需要继承 AbstractScriptExecutor 类, RhinoScriptExecutor 继承该类, 并且有三个子类, 分别为

  1. 编写一个类实现 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() } }
  1. 编写一个类实现 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" } }
  1. 编写构建任务, 一般需要实现三个任务, 分别用于构建 lib, init 以及 src 目录, 项目中剩余的其他目录有默认实现, 也就是会直接复制所有文件到目标目录, 如果有需要的话也可以修改默认实现.

Last modified: 29 April 2025