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: 12 June 2025