JavaScript 引擎是 AutoGo 脚本引擎的一部分,用于执行 JavaScript 脚本。它提供了丰富的 API 接口,支持与设备交互、文件操作、网络请求等功能。
创建一个 JavaScript 脚本文件,例如 test.js,并编写以下代码:
// 直接使用全局模块,无需 require
// 输出日志
console.log("Hello, AutoGo!");
// 获取设备信息
console.log("屏幕宽度: " + device.width);
console.log("屏幕高度: " + device.height);重要提示:AutoGo 项目的运行必须要使用 AutoGo 的 VSCode Extension 或者 GoLand 的 Extension 来执行,不能直接使用 go run 或者 go build 命令。
JavaScript 脚本可以通过以下两种方式执行:
- Embed 方式:将脚本嵌入到 Go 程序中编译执行
- 手动放置方式:将脚本文件手动放到移动设备上,然后根据路径执行
- 创建一个包含所有脚本文件的目录,例如
scripts - 在 Go 代码中使用
embed指令嵌入脚本文件:
package main
import (
"embed"
"log"
"github.com/ZingYao/autogo_scriptengine/js_engine"
"github.com/ZingYao/autogo_scriptengine/js_engine/define/android/autogo/all_models"
)
//go:embed scripts/*
var scriptsFS embed.FS
func main() {
// 初始化 JavaScript 引擎,配置文件系统以支持 require
config := js_engine.DefaultConfig()
config.FileSystem = scriptsFS
engine := js_engine.NewJSEngine(&config)
defer engine.Close()
// 注册所有 autogo 风格模块
engine.RegisterModule(all_models.AllModules...)
// 执行主脚本
err := engine.ExecuteFile("scripts/main.js")
if err != nil {
log.Fatalf("Failed to execute main.js: %v", err)
}
}使用 AutoGo 的 VSCode Extension 或 GoLand Extension 来运行项目。
- 将脚本文件手动复制到移动设备的指定目录
- 在 Go 代码中指定脚本路径并执行:
package main
import (
"log"
"github.com/ZingYao/autogo_scriptengine/js_engine"
"github.com/ZingYao/autogo_scriptengine/js_engine/define/android/autogo/all_models"
)
func main() {
// 初始化 JavaScript 引擎
config := js_engine.DefaultConfig()
engine := js_engine.NewJSEngine(&config)
defer engine.Close()
// 注册所有 autogo 风格模块
engine.RegisterModule(all_models.AllModules...)
// 执行设备上的脚本文件
err := engine.ExecuteFile("/sdcard/scripts/main.js")
if err != nil {
log.Fatalf("Failed to execute main.js: %v", err)
}
}以下示例演示如何从网络中加载 JavaScript 代码并执行:
package main
import (
"fmt"
"io"
"net/http"
"log"
"github.com/ZingYao/autogo_scriptengine/js_engine"
"github.com/ZingYao/autogo_scriptengine/js_engine/define/android/autogo/all_models"
)
func main() {
// 初始化 JavaScript 引擎
config := js_engine.DefaultConfig()
engine := js_engine.NewJSEngine(&config)
defer engine.Close()
// 注册所有 autogo 风格模块
engine.RegisterModule(all_models.AllModules...)
// 从网络加载脚本代码
url := "https://example.com/scripts/main.js"
resp, err := http.Get(url)
if err != nil {
log.Fatalf("Failed to download script: %v", err)
}
defer resp.Body.Close()
// 读取脚本内容
scriptContent, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatalf("Failed to read script: %v", err)
}
// 执行脚本
err = engine.ExecuteString(string(scriptContent), "main.js")
if err != nil {
log.Fatalf("Failed to execute script: %v", err)
}
fmt.Println("Script executed successfully!")
}- 使用
http.Get或其他 HTTP 客户端从网络下载脚本 - 读取下载的内容为字符串
- 使用
ExecuteString方法执行脚本内容 - 可以指定脚本文件名用于错误提示
JavaScript 引擎使用 goja_nodejs 提供的 require 功能,可以加载其他 JavaScript 文件(仅限用户自定义的 JS 文件)。使用方式与标准 Node.js 相同:
// 加载同目录下的 utils.js 文件
const utils = require("./utils");
// 调用 utils 中的函数
utils.doSomething();如果文件在子目录中,可以使用相对路径:
// 加载 lib/utils.js 文件
const utils = require("./lib/utils");AutoGo 脚本引擎提供了 autogo 风格包,所有模块都已通过 Go 代码注入到 JavaScript 全局环境中,无需使用 require:
autogo 风格:基于 AutoGo 原生 API
使用注入模块的示例:
// 直接使用全局模块,无需 require
// console 模块:控制台输出
console.log("Hello");
// device 模块:设备信息
console.log("屏幕宽度: " + device.width);
// app 模块:应用操作
app.launch("com.example.app");
// motion 模块:触摸操作
motion.click(100, 200);
// websocket 模块:WebSocket 客户端
var handle = websocket.connect(
"ws://echo.websocket.org",
function(h) { console.log("连接成功"); },
function(h) { console.log("连接关闭"); },
function(h, err) { console.log("错误: " + err); },
function(h, msg) { console.log("收到: " + msg); }
);autogo 风格遵循 Go API 映射规则:Go 导出函数挂到对应模块对象下,方法名按常规小驼峰转换。例如 app.OpenUrl 映射为 app.openUrl,不会额外保留历史别名,也不会注册 click(...) 这类全局入口。
JavaScript autogo define 已按系统拆分。Android 项目使用 js_engine/define/android/autogo/...,iOS 项目使用 js_engine/define/ios/autogo/...。iOS 项目可参考 examples/js_engine/autogo_ios,不要使用 Android-only 的 app.startActivity、uiacc、apkctl 或 displayId 参数。
autogo 风格遵循 Go API 映射规则:Go 导出函数挂到对应模块对象下,方法名按常规小驼峰转换。例如 app.OpenSetting 映射为 app.openSetting,不会额外保留 app.openAppSetting 等历史别名,也不会注册 click(...) 这类全局入口。
在 JavaScript 中,使用 module.exports 来导出模块,与标准 Node.js 相同:
// utils.js
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
module.exports = {
add: add,
subtract: subtract
};JavaScript 引擎使用 goja_nodejs 提供的 Node.js 兼容层,支持以下 Node.js 特性:
require()函数 - 与 Node.js 相同的模块加载机制module.exports模块导出 - 标准的 Node.js 模块导出方式__dirname和__filename变量 - 提供模块的目录和文件名信息console模块 - 标准的控制台输出功能process模块 - 提供进程相关信息
这使得你可以使用与 Node.js 完全相同的方式编写 JavaScript 脚本,提高了代码的可移植性和兼容性。
JavaScript 引擎支持两种执行模式:
同步执行是默认模式,会阻塞等待脚本执行完成:
// 同步执行文件
err := engine.ExecuteFile("script.js")
if err != nil {
log.Fatalf("执行失败: %v", err)
}
// 同步执行字符串
err = engine.ExecuteString("console.log('Hello');", "scripts")
if err != nil {
log.Fatalf("执行失败: %v", err)
}异步执行会在后台运行脚本,不会阻塞当前线程:
// 异步执行文件
err := engine.ExecuteFileWithMode("script.js", js_engine.ExecuteModeAsync)
if err != nil {
log.Fatalf("执行失败: %v", err)
}
// 异步执行字符串
err = engine.ExecuteStringWithMode("console.log('Hello');", js_engine.ExecuteModeAsync, "scripts")
if err != nil {
log.Fatalf("执行失败: %v", err)
}- 脚本执行时,当前脚本所在目录会自动添加到模块搜索路径中
- 这意味着你可以直接 require 同目录下的文件,无需指定完整路径
你可以通过 API 添加自定义的 require 搜索路径:
// 添加单个路径
erengine.AddRequirePath("/path/to/modules")
// 设置多个路径
erengine.SetRequirePaths([]string{
"/path/to/modules",
"/another/path"
})- JavaScript 脚本文件的扩展名必须是
.js - require 时可以添加
.js扩展名,也可以省略 - 脚本执行时,当前目录会被添加到模块搜索路径中
- 所有 autogo 模块都已通过 Go 代码注入到 JavaScript 全局环境中,无需使用 require
- JavaScript 引擎支持 ES6 语法
- 使用
embed时,需要配置FileSystem为嵌入的文件系统 - 手动放置脚本时,需要确保脚本文件路径正确
- AutoGo 项目的运行必须要使用 AutoGo 的 VSCode Extension 或 GoLand Extension 来执行
// 直接使用全局模块,无需 require
// 输出日志
console.log("Hello, AutoGo!");
// 获取设备信息
console.log("屏幕宽度: " + device.width);
console.log("屏幕高度: " + device.height);utils.js:
// 工具函数
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
module.exports = {
add: add,
subtract: subtract
};main.js:
// 加载工具模块(用户自定义的 JS 文件)
const utils = require("./utils");
// 直接使用全局模块(无需 require)
console.log("Hello, AutoGo!");
// 测试工具函数
const sum = utils.add(5, 3);
const difference = utils.subtract(10, 4);
// 输出结果
console.log("5 + 3 = " + sum);
console.log("10 - 4 = " + difference);package main
import (
"embed"
"fmt"
"log"
"github.com/ZingYao/autogo_scriptengine/js_engine"
"github.com/ZingYao/autogo_scriptengine/js_engine/define/android/autogo/all_models"
)
//go:embed scripts/*
var scriptsFS embed.FS
func main() {
// 初始化 JavaScript 引擎,配置文件系统以支持 require
config := js_engine.DefaultConfig()
config.FileSystem = scriptsFS
engine := js_engine.NewJSEngine(&config)
defer engine.Close()
// 注册所有 autogo 风格模块
engine.RegisterModule(all_models.AllModules...)
// 执行工具脚本(以便主脚本可以引用)
err := engine.ExecuteFile("scripts/utils.js")
if err != nil {
log.Fatalf("Failed to execute utils.js: %v", err)
}
// 执行主脚本
err = engine.ExecuteFile("scripts/main.js")
if err != nil {
log.Fatalf("Failed to execute main.js: %v", err)
}
// 输出执行结果
fmt.Println("JavaScript autogo style example completed!")
}package main
import (
"fmt"
"log"
"github.com/ZingYao/autogo_scriptengine/js_engine"
"github.com/ZingYao/autogo_scriptengine/js_engine/define/android/autogo/all_models"
)
func main() {
// 初始化 JavaScript 引擎
config := js_engine.DefaultConfig()
engine := js_engine.NewJSEngine(&config)
defer engine.Close()
// 注册所有 autogo 风格模块
engine.RegisterModule(all_models.AllModules...)
// 执行设备上的脚本文件
err := engine.ExecuteFile("/sdcard/scripts/main.js")
if err != nil {
log.Fatalf("Failed to execute main.js: %v", err)
}
// 输出执行结果
fmt.Println("JavaScript autogo style example completed!")
}JavaScript 引擎的示例代码可以在以下 GitHub 地址找到:
- JavaScript autogo 风格示例:examples/js_engine/autogo
该示例包含了完整的 JavaScript 脚本和 Go 代码,展示了如何使用 embed 和 require 功能。