LuaTouch 文档 首页 iOS 文档 安卓文档 开发者登录

前言

本页是 LuaTouch 安卓版 API 文档:目录、模块划分与 API 签名与 iOS 文档保持一致, 正文已按安卓端(engine.jar 引擎)的实际实现逐条核对(2026-09-15)。
条目标注 已支持 android支持 表示安卓端可用; iOS 不支持 表示安卓特有 API。

安卓端与 iOS 端共用同一套 Lua 脚本写法(全局函数、无模块前缀),差异主要在底层实现与个别平台限定的 API。

脚本约定

  • 坐标均为物理像素,示例以安卓测试机 720×1280 为准(iOS 文档示例为 1242×2208,数值不同、写法相同)
  • API 名称、参数、返回值语义与 iOS 对齐;若某个 API 在安卓端行为不同(返回值、权限、坐标单位等),会在该条目正文里单独说明
  • 老版安卓脚本使用的旧名(startApp、setClipboard、getClipboard、getWidth、getHeight、saveScreenshot、keepSurface、injectKeycode、injectKeyEvent、pressReleaseKeycode、keepScreenCapture)已于 2026-09-15 全部移除,请迁移到对应新名:appLaunch、imeSetClipText、imeGetClipText、getScreenSize、screenshot、keepCapture/releaseCapture、key/keyRaw/keyMeta
  • 安卓端另有双名 execute_shell_command(与 executeShellCommand 同一实现,安卓特有,供老脚本兼容)
  • 安卓端以下 API 已停用(注册被注释,Lua 面为 nil):srcUi、logUi/logUi_An/logUi_Dn、downloadFileUi、updateFloatingWindowPositionUi、saveScreenshotWithLeptonica、getLuaFilesDirectory、getEngineFilesDirectory、updateScript

下载项

script 模块(脚本控制)

print(...) 已支持 android支持

打印日志(输出到引擎/Lua 日志文件,用于调试)。

  • 参数:任意多个值(字符串/数字/布尔等)
  • 返回:无
print("hello", 123, true)   -- 日志输出

wsLog(...) 已支持 android支持

向中控推送日志({"type":"log"} 消息,中控 UI 实时可见);同时写入本地引擎日志。用法与 print 一致,多参数以 tab 分隔。需引擎 v1.10.1016+。

  • 参数:任意多个值(字符串/数字/布尔等)
  • 返回:boolean — true=已推送到中控;false=中控未连接(不报错,仅写本地日志)
wsLog("开始找图", pageNum)      -- 中控实时可见
local ok = wsLog("步骤1完成")   -- ok=true 已推送 / false 中控未连接

sleep(ms) 已支持 android支持

休眠指定毫秒数(暂停/停止脚本时立即响应,不等满时长)。

  • 参数:ms {int} 休眠毫秒数
  • 返回:无
sleep(1000)   -- 等 1 秒

LUA_CODE 已支持 android支持

全局配置集合变量:主 App 启动引擎时把控制面板参数集合(pass 字段,key 用 Pass_ 前缀)作为 JSON 字符串传入,引擎开启脚本时写入全局 LUA_CODE。

  • 类型:string(JSON 字符串),全局只读,脚本内直接读取
  • 内容:控制面板全部参数,key 为 Pass_ 前缀,与 NSUserDefaults 一致
  • 来源:主 App 控制面板输入框(引擎模式/账号/密码/序号/设备编号/luacode)→ 重启引擎生效
  • 取值:用 jsonToTable() 解析成表后按 key 取字段
-- LUA_CODE 内容示例:
-- {"Pass_mode":"root","Pass_account":"test","Pass_password":"test",
--  "Pass_seq":"1","Pass_device":"cs1","Pass_luacode":""}

-- 解析成表取字段(用于账号/授权校验、设备绑定等)
local cfg = jsonToTable(LUA_CODE)
if cfg and cfg.Pass_account == "test" then
    print("账号匹配: " .. cfg.Pass_account)
end

exitScript() 已支持 android支持

终止当前脚本(不重启)。调用后脚本立即停止执行。

  • 参数:无
  • 返回:无
exitScript()   -- 立即退出脚本

restartScript() 已支持 android支持

终止当前脚本并重新执行同一脚本文件(从头开始)。

  • 参数:无
  • 返回:无
restartScript()   -- 重启脚本

installScript(zipPath) 已支持 android支持

解压脚本项目包到工作目录:先清空工作目录的 res/、config/、libs/、scripts/ 四个目录,再把 zip 内对应目录解压到工作目录(等同安装一个脚本包;带 zip-slip 防护)。⚠️ 测试用的临时文件不要放这四个目录,会被清掉。

  • 参数:zipPath — 脚本包 zip 的完整路径(如 /data/local/tmp/com.luatouch.app/models/script.zip)
  • 返回:boolean 是否解压成功
local ok = installScript("/data/local/tmp/com.luatouch.app/models/script.zip")
-- zip 内 res/  → 工作目录 res/
--         config/ → 工作目录 config/
--         libs/   → 工作目录 libs/
--         scripts/→ 工作目录 scripts/
if ok then print("install ok") end

executeShellCommand(cmd) 安卓特有

执行系统 Shell 命令并返回输出。安卓端真实执行(引擎为 shell uid,权限内命令均可执行);iOS 端同名函数为空壳(不执行、恒返回 nil)。另有双名 execute_shell_command(同一实现,供老脚本兼容)。

  • cmd {string} 命令字符串;缺参/非字符串返回 nil, 错误信息
  • 返回:string 命令执行结果(stdout 输出)
local out = executeShellCommand("ls /data/local/tmp")   -- 返回目录列表
print(out)

getStartMode() 已支持 android支持

获取当前启动模式(START_MODE,int),由各启动入口在启动时设置:悬浮球点「开始」= 0、HTTP 10010 远程启动 = 1(可扩展其他模式);restartScript 重跑不重置(保留当前值)。

  • 参数:无
  • 返回:int 当前 START_MODE 值(当前版本恒为 0,预留字段)
local mode = getStartMode()
print("START_MODE =", mode)

Thread.newThread(callback) 已支持 android支持

创建子线程并立即开始执行 callback(独立 pthread + 独立 lua_State,与主脚本 真并行)。返回 thread userdata 用于后续 stopThread() 控制。

  • 参数:callback {function} 子线程入口函数
  • 返回:thread userdata;创建失败返回 nil + 错误消息

数据共享(globalSet / globalGet):每个线程(含主线程)的全局变量默认本线程私有 (标准 Lua 语义,线程之间互不可见)。跨线程共享走 C 层共享区,就两个公开 API:

  • globalSet("名", 值) —— 发布/覆盖:把值写进共享区。支持路径形式 globalSet("cfg", "ip", "1.2.3.4")(= 共享区的 cfg.ip,多层路径依次传分量); 值传 nil = 删除该路径。表/函数都能发(表逐字段入库,函数以字节码跨线程加载,取回可直接调用)
  • globalGet("名") / globalGet("cfg", "ip") —— 读取:返回共享区里的 深拷贝实体(表可正常 pairs / 索引 / #,每次读取是独立副本,改它不影响共享区); 不存在返回 nil
  • 快照语义(最重要):发布是"拷一份进共享区"——发布之后本线程再改自己的变量, 共享区不会自动跟着变,要让别人看到必须重新 globalSet 一次

重要约束:

  • 回调不能依赖闭包 upvalue(子线程通过字节码加载回调,upvalue 不跨线程传递); 数据一律用 globalSet / globalGet 传
  • 子线程里先 globalGet 取到本地再循环使用,要最新值时再取一次 (别在循环里反复取大表,每次都是深拷贝)
  • 子线程不响应主脚本的暂停/恢复;只有 stopThread() 或主脚本结束/停止时强停
-- 主脚本:发布共享数据(子线程看不到普通全局变量,必须 globalSet)
config = { count = 0, stop = false }
globalSet("config", config)            -- 整表发布(逐字段入库)

function worker()
    while true do
        local cfg = globalGet("config")          -- 取共享区副本
        if cfg and cfg.stop then break end
        print("worker tick, count=" .. tostring(cfg and cfg.count))
        sleep(1000)
    end
    print("worker exit")
end

local t = Thread.newThread(worker)
-- 主脚本继续干别的事...
sleep(5000)
config.stop = true
globalSet("config", config)            -- ★ 改完必须重新发布,子线程才看得到

thread:stopThread() 已支持 android支持

强制终止该子线程(置独立停止标志,线程内 sleep 立即响应,hook 强停)。只影响该线程, 不影响主脚本与其他子线程。主脚本结束/停止时引擎会自动强停所有子线程,无需手动清理。

  • 参数:无(thread 为 Thread.newThread 的返回值)
  • 返回:无
local t = Thread.newThread(worker)
sleep(3000)
t:stopThread()   -- 单独停掉 worker,主脚本继续跑

app 模块

appCurrentPackage() 已支持 android支持

获取当前前台应用的 Bundle Identifier。

  • 参数:无
  • 返回:string 前台应用的包名;无前台应用时返回 nil
-- 获取当前前台 App 的包名
local bid = appCurrentPackage()
print(bid)   -- 例如 "com.apple.mobilesafari"

appLaunch(packageName) 已支持 android支持

通过 Bundle Identifier 启动应用。

  • packageName {string} 应用包名
  • 返回:bool 是否启动成功
local ok = appLaunch("com.apple.mobilesafari")
if ok then print("已启动") end

appForceStop(packageName) 已支持 android支持

关闭指定应用(系统级终止进程)。

  • packageName {string} 应用包名
  • 返回:bool 是否成功终止
appForceStop("com.example.app")

appGetList(includeSystemApps) 已支持 android支持

获取已安装应用列表。

  • includeSystemApps {bool} 是否包含系统应用
  • 返回:table 应用信息数组,每个元素是下表结构
字段名类型说明
PackageNamestring应用的 Bundle Identifier
AppNamestring应用显示名称
VersionNamestring版本号(安卓版为 versionName)
VersionCodestring构建号(安卓版为 versionCode)
IsSystemAppbool是否为系统应用
local list = appGetList(true)
for _, a in ipairs(list) do
    print(a.PackageName, a.AppName, a.VersionName)
end

appGetBundlePath(packageName) 已支持 android支持

获取应用安装包(.app)路径。

  • packageName {string} 应用包名
  • 返回:string 路径;未找到返回 nil
local path = appGetBundlePath("com.auto.go")

appGetDataPath(packageName) 已支持 android支持

获取应用数据目录路径。

  • packageName {string} 应用包名
  • 返回:string 数据目录路径;未找到返回 nil
local data = appGetDataPath("com.auto.go")

appSelfPackage() 已支持 android支持

获取当前脚本/宿主自身的包名。

  • 参数:无
  • 返回:string 当前应用包名;获取失败返回 nil
local pkg = appSelfPackage()

appGetVersion(packageName) 已支持 android支持

通过包名获取应用版本号(安卓版为 versionName)。

  • packageName {string} 应用包名
  • 返回:string 版本号;未找到返回 nil
local ver = appGetVersion("com.tencent.xin")

appUninstall(packageName) 已支持 android支持

卸载应用。

  • packageName {string} 应用包名
  • 返回:bool 是否成功
appUninstall("com.example.app")

appInstall(path) 已支持 android支持

后台静默安装 APK 文件。

  • path {string} APK 文件路径
  • 返回:bool 是否成功
appInstall("/data/local/tmp/com.luatouch.app/app.apk")

appClear(packageName) 已支持 android支持

清除应用数据(删除数据容器内容)。

  • packageName {string} 应用包名
  • 返回:bool 是否成功
appClear("com.example.app")

appOpenUrl(url) 已支持 android支持

使用系统默认方式打开 URL。若未带 http:// 或 https:// 前缀,会自动补上 http://。

  • url {string} 网址或 URL Scheme
  • 返回:bool 是否成功
appOpenUrl("https://example.com")

appGetPackageName() 已支持 android支持

获取宿主 App(LuaTouch)包名。与 appSelfPackage() 的区别: appSelfPackage() 返回引擎宿主(com.luatouch.core),本函数返回主 App(com.luatouch.app)。

  • 参数:无
  • 返回:string 主 App 包名(com.luatouch.app)
print(appGetPackageName()) -- com.luatouch.app
print(appSelfPackage())   -- com.luatouch.core

device 模块

deviceGet() 已支持 android支持

一次获取设备信息(本引擎便利封装)。只含「变量 + 下方函数拿不到」的信息;内存用 deviceGetTotalMem、屏幕用 deviceGetDisplayInfo。

  • 参数:无
  • 返回:table,字段见下表(取不到时字段缺失)
字段类型说明
Modelstring设备机型标识(如 TAS-AL00)
Releasestring系统版本(如 "14.6")
Serialstring设备序列号
Buildstring系统构建号(如 18F72)
SystemNamestring系统名称(如 "iOS")
DeviceNamestring用户设置的设备名
ArchstringCPU 架构(如 arm64)
Is64Bitbool是否 64 位
CpuCountintCPU 核数
local d = deviceGet()
print(d.Model, d.Release, d.Serial)
print(d.Arch, d.Is64Bit, d.CpuCount)

deviceGetDisplayInfo() 已支持 android支持

获取主屏幕的分辨率信息(多返回值)。

  • 参数:无
  • 返回:width {int} 逻辑宽度,height {int} 逻辑高度,scale {number} 缩放因子,rotation {int} 旋转角度(0/90/180/270)
local w, h, scale, rot = deviceGetDisplayInfo()
print(w, h, scale, rot)   -- 例如 390 844 2.0 0

deviceVpnStatus() 已支持 android支持

获取 VPN 状态(存在 utun 网络接口即视为开启)。

  • 参数:无
  • 返回:bool
if deviceVpnStatus() then
    print("VPN 已开启")
end

deviceSetVPNEnabled(enabled) iOS 不支持

设置 VPN 开关状态。iOS 平台限制,恒返回 false。

  • enabled {bool} 是否打开
  • 返回:false
deviceSetVPNEnabled(true)   -- 恒 false

deviceSetWiFiEnabled(enabled) iOS 不支持

设置 WiFi 开关状态。iOS 平台限制,恒返回 false。

  • enabled {bool} 是否打开
  • 返回:false
deviceSetWiFiEnabled(true)   -- 恒 false

deviceGetBattery() 已支持 android支持

获取当前电量百分比。

  • 参数:无
  • 返回:int 0~100;读取失败返回 -1
local level = deviceGetBattery()
print("电量 " .. level .. "%")

deviceGetBatteryStatus() 已支持 android支持

获取电池状态。

  • 参数:无
  • 返回:int 0 未知,1 未充电,2 充电中,3 已充满
local st = deviceGetBatteryStatus()
if st == 2 then print("充电中") end

deviceIsScreenOn() 已支持 android支持

判断屏幕是否点亮(未锁屏即视为点亮)。

  • 参数:无
  • 返回:bool
if deviceIsScreenOn() then print("屏幕亮着") end

deviceIsScreenUnlock() 已支持 android支持

判断屏幕是否已解锁(未处于锁屏状态)。

  • 参数:无
  • 返回:bool
if deviceIsScreenUnlock() then print("已解锁") end

deviceGetBrightness() 已支持 android支持

获取当前屏幕亮度。

  • 参数:无
  • 返回:int 0~255
local b = deviceGetBrightness()
print("亮度 " .. b)

deviceGetTotalMem() 已支持 android支持

获取设备总内存。

  • 参数:无
  • 返回:int 总内存,单位 KB;失败返回 0
print(deviceGetTotalMem() .. " KB")

deviceGetAvailMem() 已支持 android支持

获取设备当前可用内存(free + inactive,host_statistics64)。

  • 参数:无
  • 返回:int 单位 KB;失败返回 0
print(deviceGetAvailMem() .. " KB")

deviceWakeUp() 已支持 android支持

唤醒设备(点亮屏幕)。

  • 参数:无
  • 返回:bool 是否成功调用
deviceWakeUp()

deviceKeepScreenOn() 已支持 android支持

保持屏幕常亮(关闭自动锁屏)。

  • 参数:无
  • 返回:bool 是否成功调用
deviceKeepScreenOn()

deviceGetIp() 已支持 android支持

获取设备局域网 IPv4 地址(优先私有网段,跳过自分配地址)。

  • 参数:无
  • 返回:string 如 "192.168.31.169";取不到返回 nil
local ip = deviceGetIp()
print(ip)

deviceGetWifiMac() 已支持 android支持

获取 Wi‑Fi 网卡 MAC 地址(en0,回退 en1)。

  • 参数:无
  • 返回:string 如 "aa:bb:cc:dd:ee:ff";取不到返回 nil
local mac = deviceGetWifiMac()
print(mac)

deviceReboot() 已支持 android支持

重启设备(root 直接 reboot(RB_AUTOBOOT),调用后设备立即重启)。

  • 参数:无
  • 返回:bool(正常不会返回)
-- 慎用:立即重启设备
deviceReboot()

getPlatform() 已支持 android支持

获取运行平台标识。iOS 版恒返回 "ios"(跨平台脚本兼容用,安卓版返回 "android")。

  • 参数:无
  • 返回:string 平台标识,iOS 上恒为 "ios"
if getPlatform() == "ios" then
    print("当前运行在 iOS")
end

file 模块

deleteFile(path) 已支持 android支持

删除文件或空目录(目录用 rmdir,文件用 remove)。

  • path {string} 文件或空目录路径
  • 返回:bool 是否删除成功
deleteFile("/data/local/tmp/com.luatouch.app/tmp.txt")

moveFile(src, dst) 已支持 android支持

移动或重命名文件(rename)。

  • src {string} 源路径
  • dst {string} 目标路径
  • 返回:bool 是否成功
moveFile("/tmp/a.txt", "/data/local/tmp/com.luatouch.app/a.txt")

unzipFile(zip, dest) 已支持 android支持

解压 zip 文件到目标目录。

  • zip {string} zip 文件路径
  • dest {string} 解压目标目录(不存在会自动创建)
  • 返回:bool 是否成功
unzipFile("/data/local/tmp/com.luatouch.app/app.zip", "/data/local/tmp/com.luatouch.app/extract")

readFileAsBase64(path) 已支持 android支持

读取文件内容并编码为 Base64(双返回值)。

  • path {string} 文件路径
  • 返回:string Base64 内容;失败返回 nil + 错误信息
local b64, err = readFileAsBase64("/tmp/img.png")
if b64 then
    print("base64 length", #b64)
end

base64Encode(str) 已支持 android支持

将字符串编码为 Base64(标准字母表 A-Z a-z 0-9 + /,= 填充)。

  • str {string} 原始内容
  • 返回:string Base64 编码结果
local b64 = base64Encode("hello")
print(b64)          -- aGVsbG8=

base64Decode(str) 已支持 android支持

将 Base64 字符串解码为原始内容(自动忽略换行/空白/= 填充,容错宽松)。

  • str {string} Base64 内容
  • 返回:string 解码结果
local raw = base64Decode("aGVsbG8=")
print(raw)          -- hello

http 模块

httpGet(url, timeout?) 已支持 android支持

HTTP GET 请求。支持 HTTP/HTTPS,默认超时 30 秒。

  • url {string} 完整 URL(如 http://192.168.1.1:8080/api)
  • timeout {number} 可选,超时秒数,默认 30
  • 返回:int HTTP 状态码(200/404…,负值为错误码见下表)+ string 响应体
local code, body = httpGet("http://example.com/api")
print(code, body)

httpPost(url, data, contentType?, timeout?) 已支持 android支持

HTTP POST 请求。支持 HTTP/HTTPS,默认超时 30 秒。

  • url {string} 完整 URL
  • data {string} 请求体(POST 数据)
  • contentType {string} 可选,Content-Type;默认 application/x-www-form-urlencoded
  • timeout {number} 可选,超时秒数,默认 30
  • 返回:int 状态码 + string 响应体
local code, body = httpPost("http://example.com/api",
    "name=test&id=1", "application/x-www-form-urlencoded")

downloadFile(url, path, timeout?) 已支持 android支持

HTTP 下载文件到本地(流式写盘,父目录自动创建)。支持 HTTP/HTTPS,默认超时 60 秒。

  • url {string} 完整 URL
  • path {string} 保存路径(绝对路径)
  • timeout {number} 可选,超时秒数,默认 60
  • 返回:boolean 是否成功 + string 错误信息(成功为空串)
local ok, err = downloadFile("http://example.com/file.zip",
    "/data/local/tmp/com.luatouch.app/downloads/file.zip")

tableToJson(table) 已支持 android支持

Lua 表序列化为 JSON 字符串。数组(连续数字键)输出数组,否则输出对象。

  • table {table} 要序列化的表
  • 返回:string JSON 字符串;参数非表返回错误串
local json = tableToJson({ name = "test", id = 1 })
print(json)   -- {"id":1,"name":"test"}

jsonToTable(str) 已支持 android支持

JSON 字符串解析为 Lua 表。

  • str {string} JSON 字符串
  • 返回:table 解析结果;解析失败返回 nil
local t = jsonToTable('{"name":"test","id":1}')
print(t.name, t.id)

HTTP 错误码 说明

码含义
-1参数错误(url 为空 / POST 无数据)
-2URL 解析失败
-4socket 创建失败
-5DNS 解析失败
-6连接失败
-7发送失败
-8无响应(超过 timeout 秒)

ime 模块

imeInputText(text) 已支持 android支持

向当前焦点控件输入文本(支持中文、英文、数字)。

  • text {string} 要输入的文本(支持中文/英文/数字)
  • 返回:bool 是否注入成功
imeInputText("Hello, World!")
imeInputText("你好世界")

imePasteText() 已支持 android支持

模拟 Command+V,把剪贴板内容粘贴到当前焦点。

  • 参数:无
  • 返回:bool 是否注入成功
imeSetClipText("要粘贴的内容")
imePasteText()

imeGetClipText() 已支持 android支持

获取剪贴板文本内容。

  • 参数:无
  • 返回:string 剪贴板文本;失败返回 nil
local text = imeGetClipText()
print(text)

imeSetClipText(text) 已支持 android支持

设置剪贴板文本内容。

  • text {string} 要写入剪贴板的文本
  • 返回:bool 是否设置成功
imeSetClipText("要复制的内容")

touch 模块

tap(x, y, tip?, barrel?, radius?) 已支持 android支持

在指定位置点击一下。

  • x {number} 横坐标(物理像素,0~屏幕宽)
  • y {number} 纵坐标(物理像素,0~屏幕高)
  • tip {number} 可选,指尖压力 0~1,默认 1
  • barrel {number} 可选,笔身压力 0~1,默认 0
  • radius {number} 可选,触摸半径,默认 0.04
  • 返回:无
tap(360, 640)   -- 点击屏幕中心(720x1280)

swipe(x1, y1, x2, y2, ms?, tip?, barrel?, radius?) 已支持 android支持

从起点滑动到终点(20 步插值)。

  • x1, y1 {number} 起点坐标
  • x2, y2 {number} 终点坐标
  • ms {int} 可选,滑动时长毫秒,默认 300(最小 50)
  • tip {number} 可选,指尖压力 0~1,默认 1
  • barrel {number} 可选,笔身压力 0~1,默认 0
  • radius {number} 可选,触摸半径,默认 0.04
  • 返回:无
swipe(621, 1600, 621, 400, 500)   -- 从下往上滑

key(name) 已支持 android支持

按命名按键(按下 → 保持约 40ms → 自动抬起)。

  • name {string} 键名,仅支持下列 6 个:home / home2 / lock(锁屏)/ volup / voldown / mute
  • 返回:bool 是否支持该键名(true=已注入;false=键名未知,不注入任何按键)
键名对应 HID说明
homepage 0x0C, usage 0x40回到主屏(Consumer Home/Menu)
home2page 0x0C, usage 0x0223回主屏的另一种实现(Consumer AC Home),部分场景比 home 更有效
lockpage 0x0C, usage 0x30锁屏 / 电源键
voluppage 0x0C, usage 0xE9音量 +
voldownpage 0x0C, usage 0xEA音量 −
mutepage 0x0C, usage 0xE2静音开关
key("home")       -- 回到主屏
key("volup")      -- 音量+
key("lock")       -- 锁屏
if not key("back") then print("key 不认识 back,需要用 keyRaw") end

keyRaw(page, usage) 已支持 android支持

按 HID 原始键码(按下 → 保持约 40ms → 自动抬起),用于 key() 未内置的按键。

  • page {int} HID 用法页(如 0x0C 消费类、0x07 键盘)
  • usage {int} 用法码
  • 返回:无
keyRaw(0x0C, 0x40)    -- Consumer Home

keyMeta(name, repeat?, meta?) 已支持 android支持

带修饰键的按键(键名范围同 key();修饰键只支持 Shift)。

  • name {string} 键名(同 key)
  • repeat {int} 可选,重复次数,默认 1
  • meta {int} 可选,修饰键位掩码:0x1 = Shift,默认 0
  • 返回:无
keyMeta("home", 2)       -- 按 home 两次
keyMeta("home", 1, 0x1)  -- Shift + home

touchDown(idx, x, y, tip?, barrel?, radius?) 已支持 android支持

多指触摸:第 idx 根手指按下。手指索引范围 0~9,按下 / 移动 / 抬起必须用同一个 idx 成对出现(自己保证配对,不做手势识别)。

  • idx {int} 手指索引(0~9)
  • x, y {number} 按下位置
  • tip {number} 可选,指尖压力 0~1,默认 1
  • barrel {number} 可选,笔身压力 0~1,默认 0
  • radius {number} 可选,触摸半径,默认 0.04
  • 返回:无
touchDown(0, 100, 300)   -- 第一根手指按下

touchMove(idx, x, y, tip?, barrel?, radius?) 已支持 android支持

多指触摸:移动第 idx 根手指到新位置。按规范应先 touchDown 同一 idx;idx 超出 0~9 会被忽略。

  • idx {int} 手指索引(0~9)
  • x, y {number} 新位置
  • tip {number} 可选,指尖压力 0~1,默认 1
  • barrel {number} 可选,笔身压力 0~1,默认 0
  • radius {number} 可选,触摸半径,默认 0.04
  • 返回:无
touchDown(0, 200, 400)
touchMove(0, 400, 400)   -- 保持按住并拖动
touchUp(0)

touchUp(idx) 已支持 android支持

多指触摸:抬起第 idx 根手指(必须与对应 touchDown 的 idx 一致,抬起位置用的是按下时记录的坐标)。若该 idx 当前并未按下,则不发送任何事件、静默返回;idx 超出 0~9 同样被忽略。

  • idx {int} 手指索引(0~9)
  • 返回:无
touchUp(0)               -- 第一根手指抬起

color 模块

keepCapture() / releaseCapture() 已支持 android支持

图色渲染帧冻结控制:图色函数读取的是后台持续更新的缓存帧。

  • keepCapture():冻结当前画面,期间所有图色函数查的是同一帧
  • releaseCapture():恢复实时画面
  • 参数:无;返回:无
  • 用途:画面静止时连续多次图色查找(循环找点)保证同一画面
keepCapture()                     -- 冻结当前帧
for i = 1, 10 do
    local x, y = findMultiColors(0, 0, 0, 0, "359bed-101010",
        "45|76|ffffff-101010|93|114|ffffff-101010|33|146|ffffff-101010|-9|432|359bed-101010|58|447|359bed-101010",
        0, 0.9)
    if x ~= -1 and y ~= -1 then print(x, y) end
end
releaseCapture()                  -- 恢复实时画面

⚠️ 注意:每次开启脚本(悬浮球「开始」)会自动恢复实时渲染,不会因上次脚本忘记释放而永久冻结;但脚本内 keep 后建议主动 release。安卓实现为图像帧层开关(keepCapture() = 停止实时更新、一直保存当前帧;releaseCapture() = 恢复实时渲染)。

颜色格式 已支持 android支持

颜色统一为 6 位十六进制 RGB,格式 目标-容差(分隔符 - 或 | 均可):

  • 目标 {string} 6 位目标颜色,如 ffffff
  • 容差 {string} 6 位容差值(R/G/B 各一字节),如 323232 表示每通道允许 ±0x32
findColor(0, 0, 720, 1280, "ffffff-323232", 0, 0, 0)
-- 多点偏移组:x|y|目标-容差
detectsMultiColors("620|389|ffffff-323232,100|200|000000-101010")

getPixel(x, y) 已支持 android支持

获取指定像素点的 RGB 分量(多返回值)。

  • x, y {int} 屏幕像素坐标
  • 返回:r, g, b(0~255);越界返回 nil
local r, g, b = getPixel(100, 200)
print(r, g, b)

getRGB(x, y) 已支持 android支持

获取指定像素点的打包颜色值。

  • x, y {int} 屏幕像素坐标
  • 返回:int 颜色 0xAARRGGBB;失败返回 0
local c = getRGB(100, 200)
print(string.format("%08X", c))

getScreenSize() 已支持 android支持

获取屏幕尺寸(多返回值)。

  • 参数:无
  • 返回:w, h(像素);无屏幕缓存返回 nil
local w, h = getScreenSize()

findColor(x1, y1, x2, y2, color, d1?, d2?, d3?) 已支持 android支持

在矩形区域内查找第一个匹配颜色的点(8 方向扫描)。

  • x1, y1, x2, y2 {int} 搜索区域(自动归一化)
  • color {string} 目标-容差,如 ffffff-323232
  • d1, d2, d3 {int} 可选,扫描方向(0/1),决定起扫边与主轴;全 0 = 左上→右下
  • 返回:x, y 命中坐标;未找到返回 -1, -1
local x, y = findColor(0, 0, 720, 1280, "ff0000-101010")
if x >= 0 then
    print("found at", x, y)
end

isColor(x, y, color) 已支持 android支持

判定指定像素点颜色是否匹配(单点快速判定:直读渲染源目标像素,不建目标面、不整帧拷贝;keepCapture 冻结期 / 50ms 去重窗口内直接读缓存帧零成本返回)。

  • x, y {int} 屏幕像素坐标
  • color {string} RRGGBB 或 RRGGBB-容差;纯 6 位串自动按容差 000000 处理
  • 返回:boolean true 命中 / false 不命中
if isColor(102, 86, "D33422-101010") then
    print("是目标颜色")
end

findMultiColors(x1, y1, x2, y2, firstColor, offsetColors, d1?, d2?, d3?) 已支持 android支持

首点 + 相对偏移多点匹配(可精确识别图标/按钮)。

  • x1, y1, x2, y2 {int} 搜索区域
  • firstColor {string} 首点颜色(目标-容差)
  • offsetColors {string} 偏移点组,x|y|目标-容差 逗号分隔(偏移相对首点)
  • d1, d2, d3 {int} 可选,扫描方向
  • 返回:x, y 首点命中坐标;未找到返回 -1, -1
local x, y = findMultiColors(0, 0, 720, 1280,
    "ffffff-323232",
    "620|391|ffffff-323232,100|200|000000-101010")

tableFindMultiColors(x1, y1, x2, y2, firstColor, offsetColors, d1?, d2?, d3?) 已支持 android支持

与 findMultiColors 同参数,但返回区域内所有匹配点的集合(而非第一个点)。

  • x1, y1, x2, y2 {int} 搜索区域
  • firstColor {string} 首点颜色(目标-容差)
  • offsetColors {string} 偏移点组,x|y|目标-容差 逗号分隔(偏移相对首点)
  • d1, d2, d3 {int} 可选,扫描方向
  • 返回:table 所有匹配点集合 {{x=,y=},...};无匹配返回空表 {}
local pts = tableFindMultiColors(0, 0, 720, 1280,
    "ffffff-323232",
    "620|391|ffffff-323232,100|200|000000-101010")
for i, p in ipairs(pts) do
    print(i, p.x, p.y)
end

findPic(x1, y1, x2, y2, files, deltaColor?, sim?, dir?) 已支持 android支持

区域找图(模板匹配):在屏幕区域内查找模板图片,返回其左上角坐标。支持透明图/异形图(模板四角同色且占比 ≥30% 时该色判为背景,匹配时只比前景像素——兼容大漠涂抹异形图用法与 PNG 真透明)、每通道偏色、多模板(| 分隔,返回最先命中的)。

  • x1, y1, x2, y2 {int} 搜索区域;x2/y2 为 0 时取整屏,坐标写反自动交换
  • files {string} 模板图片路径,多图用 | 分隔(如 a.png|b.png);相对路径以脚本工作目录 res/ 为基准;支持 png/jpg
  • deltaColor {string} 可选,偏色 RRGGBB(如 "101010"),匹配时每通道允许 ±该值;"000000" = 无偏色
  • sim {number} 可选,相似度 0.1~1.0(默认 0.9),1.0 = 逐像素完全一致
  • dir {int} 可选,扫描方向:0 从左上(默认)/ 1 从右上 / 2 从左下 / 3 从右下
  • 返回:x, y 命中模板的左上角坐标;未找到返回 -1, -1

模板图可用「图色助手 → 裁剪画笔涂抹」制作:涂抹掉不要的部分(涂抹色需一致且占比 ≥30%、四角为涂抹色,工具会自动补涂)。

-- 全屏找 btn.png,相似度 0.9,无偏色
local x, y = findPic(0, 0, 0, 0, "btn.png", "000000", 0.9, 0)
if x ~= -1 then
    tap(x + 20, y + 10)  -- 点模板内相对位置
end

-- 多模板:返回最先命中的那个(透明图/异形图直接可用)
x, y = findPic(0, 0, 0, 0, "btn2.jpg|btn3.png", "000000", 0.9, 0)
print(x, y)

findPicEx(x1, y1, x2, y2, files, deltaColor?, sim?, dir?) 已支持 android支持

区域找图(多图全部命中):与 findPic 同参数,但返回区域内所有模板命中结果的集合(而非第一个),结果按扫描方向排序,上限 1800 个。

  • 参数与 findPic 完全一致
  • 返回:table 每项 {index=模板序号, name=文件名, x=, y=};无匹配返回空表 {}
local t = findPicEx(0, 0, 0, 0, "a.png|b.png", "000000", 0.9, 0)
for i, v in ipairs(t) do
    print(i, v.name, v.x, v.y)
end
-- 无匹配时 t 为空表

getColorCountInRegion(x1, y1, x2, y2, colorStr, sim?) 已支持 android支持

统计区域内符合颜色条件的像素数量。

  • x1, y1 {int} 区域左上角坐标
  • x2, y2 {int} 区域右下角坐标;为 0 时取屏幕最大宽/高
  • colorStr {string} 颜色字符串,多颜色用 | 分隔,每组 RRGGBB 或 RRGGBB-容差,如 FFFFFF|CCCCCC-101010
  • sim {number} 可选,相似度 0.1~1.0(默认 0.9);未带容差的颜色用它换算容差 (1-sim)*255
  • 返回:int 匹配像素总数(任一颜色命中即计 1)
local count = getColorCountInRegion(0, 0, 0, 0, "FFFFFF", 0.9)
print(count)

detectsMultiColors(colors) 已支持 android支持

多点同屏判定:给定一组绝对坐标点,判断是否全部匹配(常用于区域校验)。

  • colors {string} x|y|目标-容差 逗号分隔;首点可带第 4 字段 extra 指定偏移搜索范围(默认 0)
  • 返回:bool 全部匹配返回 1,否则 0
local ok = detectsMultiColors("620|389|ffffff-323232,100|200|000000-101010")
if ok == 1 then
    print("all colors match")
end

screenshot(path) 已支持 android支持

截取全屏并保存为 PNG 文件。

  • path {string} 保存路径
  • 返回:bool 是否保存成功
screenshot("/data/local/tmp/com.luatouch.app/screen.png")

opencv 模块

cv_copyImageToMat(x1, y1, x2, y2) 已支持 android支持

截取屏幕指定区域,作为当前图像(后续处理的基础)。

  • x1, y1, x2, y2 {int} 屏幕区域坐标
  • 返回:int 0 成功;负值失败
cv_copyImageToMat(0, 0, 720, 1280)

cv_resizeImage(scale, interp?) 已支持 android支持

按倍数缩放当前图像。

  • scale {number} 缩放倍数,如 0.5 缩小一半、2 放大两倍
  • interp {int} 可选,插值方式:0=最近邻 1=双线性(默认) 2=双三次 3=面积 4=兰索斯
  • 返回:int 0 成功;负值失败
cv_resizeImage(0.5)   -- 缩小一半

cv_thresholdImage(method, p1?, p2?, p3?, p4?, p5?) 已支持 android支持

对当前图像做二值化/阈值处理(先转灰度)。

  • method {int} 处理方式:0=固定阈值 1=自适应 2=自动计算最优阈值
  • p1 {number} 方式 0 为阈值(0~255,默认 128);方式 1 为最大像素值(默认 128)
  • p2 {number} 方式 0 为最大值(0~255,默认 255);方式 1 为邻域块大小(须为大于 1 的奇数,默认 255)
  • p3 {int} 方式 0 为阈值类型(0=二值 1=反二值 2=截断 3=归零 4=反归零);方式 1 为自适应方法(0=均值 1=高斯)
  • p4 {int} 方式 1 的阈值类型(0/1),默认 0
  • p5 {number} 方式 1 的常数偏移 C,默认 0
  • 返回:int 0 成功;负值失败
cv_thresholdImage(0, 128, 255, 0)   -- 固定阈值二值化
cv_thresholdImage(2)                -- 自动阈值

cv_colorDeviationBinary("RRGGBB-RRGGBB") 已支持 android支持

按颜色范围把当前图像转为二值图:目标色 ± 偏差内的像素为白,其余为黑。

  • RRGGBB-RRGGBB {string} 目标色-偏差,如 FFFFFF-101010 表示白色 ± 0x10
  • 返回:int 0 成功;负值失败
cv_colorDeviationBinary("FFFFFF-101010")

cv_clahe(clipLimit?) 已支持 android支持

对比度受限的自适应直方图均衡,增强图像对比度。

  • clipLimit {number} 可选,对比度限制,默认 2.0
  • 返回:int 0 成功;负值失败
cv_clahe(2.0)

cv_sharpen(strength?) 已支持 android支持

图像锐化,增强边缘细节。

  • strength {number} 可选,锐化强度,默认 1.0
  • 返回:int 0 成功;负值失败
cv_sharpen(1.0)

cv_morphology(op, ksize?, kshape?) 已支持 android支持

形态学操作(腐蚀/膨胀等),常用于去噪、连通区域处理。

  • op {int} 操作:0=腐蚀 1=膨胀 2=开运算 3=闭运算 4=梯度 5=顶帽 6=黑帽
  • ksize {int} 可选,核大小,默认 3
  • kshape {int} 可选,核形状:0=矩形 1=十字 2=椭圆,默认 0
  • 返回:int 0 成功;负值失败
cv_morphology(1, 3, 0)   -- 膨胀

cv_find_image_by_path(path, method?, sim?) 已支持 android支持

在当前图像中查找模板图片,返回匹配位置。

  • path {string} 模板图片路径
  • method {int} 可选,匹配算法:0=平方差 1=归一化平方差 2=相关 3=归一化相关 4=相关系数 5=归一化相关系数(默认)
  • sim {number} 可选,相似度阈值 0~1,默认 0.8
  • 返回:x, y 匹配位置;未找到/出错时返回 x, y, errMsg(x/y 为 0,errMsg 说明原因)
local x, y = cv_find_image_by_path("/data/local/tmp/com.luatouch.app/tpl.png")
if x > 0 then
    print("找到模板", x, y)
end

cv_saveImage(path) 已支持 android支持

把当前图像保存为图片文件。

  • path {string} 保存路径(按扩展名决定格式)
  • 返回:int 0 成功;负值失败
cv_saveImage("/data/local/tmp/com.luatouch.app/out.png")

cv_matToBase64(fmt?) 已支持 android支持

把当前图像编码为 base64 字符串(便于网络传输/日志)。

  • fmt {string} 可选,编码格式,默认 png
  • 返回:string base64 内容;失败返回 nil, errMsg
local b64 = cv_matToBase64("png")

cv_rotateImage(rot) 已支持 android支持

旋转当前图像。

  • rot {int} 旋转方向:1=顺时针 90° 2=180° 3=逆时针 90°
  • 返回:int 0 成功;负值失败
cv_rotateImage(1)   -- 顺时针旋转 90°

cv_cleanup() 已支持 android支持

释放当前图像占用的内存(结束处理链后调用)。

  • 参数:无
  • 返回:无
cv_cleanup()

tessocr 模块

ocr_init(dataDir, language) 已支持 android支持

初始化文字识别引擎,加载语言数据。

  • dataDir {string} 语言数据目录,如 /data/local/tmp/com.luatouch.app/models/tessdata
  • language {string} 识别语言,如 eng(英文)
  • 返回:bool 是否初始化成功
local ok = ocr_init("/data/local/tmp/com.luatouch.app/models/tessdata", "eng")

ocr_set_param(param, value) 已支持 android支持

设置识别参数(需先 ocr_init)。底层引擎为 Tesseract 5.5.0(静态库、仅 LSTM 识别引擎),参数名沿用 Tesseract 官方变量名。

  • param {string} 参数名,见下方参数表,如 tessedit_char_whitelist(字符白名单)
  • value {string} 参数值,必须用字符串传入:布尔写 "1" / "0"(也接受 true / false / T / F / Y / N),数值写 "7"、"0.7" 这类字符串
  • 返回:bool 参数名存在即返回 true;未 ocr_init 时返回 false, "OCR not initialized"

返回值只代表“参数名存在”,不等于一定生效:

  • 参数名写错、或该变量在当前 Tesseract 版本里不存在 → 返回 false
  • 表中标注「初始化前」的参数必须在 ocr_init 之前设定,而本接口要求先 ocr_init,所以这类参数会返回 true 但实际不生效
  • 重新执行 ocr_init(例如换语言)会重置全部参数,需要重新设置

可直接使用的参数

参数名类型默认说明
tessedit_char_whiteliststring空只识别白名单内的字符,固定字符集场景可明显提高准确率
tessedit_char_blackliststring空禁止输出指定字符(与白名单互斥使用)
page_seg_modeint6页面分割模式;本引擎的专用别名,等价于 tessedit_pageseg_mode
tessedit_pageseg_modeint6同上:0=方向/脚本检测,3=全自动,6=整块文本,7=单行,8=单词,10=单字符,11=稀疏文本
preserve_interword_spacesbool0保留词间多个空格,适合列表、对齐文本
user_defined_dpiint0指定输入图像 DPI,0 表示自动判断
textord_tabfind_find_tablesbool1表格检测;纯文字截图可设 0,略快
invert_thresholddouble0.7反色判定阈值(tessedit_do_invert 的替代参数)
tessedit_do_invertbool1尝试反色图像;Tesseract 已标记废弃,6.0 版将移除
tessedit_write_imagesbool0保存预处理后的图像,排查识别不准时使用

初始化前才能设定的参数(本接口设置不会生效)

参数名默认说明
load_system_dawg1加载系统词典(关闭后不再把字符纠正成词典词)
load_freq_dawg1加载高频词词典
load_punc_dawg1加载标点词典
tessedit_ocr_engine_mode3识别引擎选择;本构建仅含 LSTM 引擎

当前版本不存在的参数名(写了会返回 false)

  • tessedit_do_orientation:5.5.0 无此变量,方向检测由页面分割模式(page_seg_mode)控制
  • tessedit_do_blur_detection:5.5.0 无此变量
  • tessedit_use_opencl:Tesseract 5 已移除 OpenCL 支持
-- 只识别数字和字母
ocr_set_param("tessedit_char_whitelist", "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

-- 单行文本 + 保留词间空格
ocr_set_param("page_seg_mode", "7")
ocr_set_param("preserve_interword_spaces", "1")

-- 纯文字截图关掉表格检测
ocr_set_param("textord_tabfind_find_tables", "0")

-- 用返回值判断参数名是否有效
print(ocr_set_param("tessedit_do_orientation", "0"))   -- false:本版本没有这个参数

ocr_from_file(path) 已支持 android支持

识别指定图片文件中的文字。

  • path {string} 图片路径
  • 返回:string 识别出的文字;失败返回 nil, errMsg
local text = ocr_from_file("/data/local/tmp/com.luatouch.app/screen.png")

ocr_from_image() 已支持 android支持

识别当前图像中的文字(配合 cv_copyImageToMat 截取屏幕区域)。

  • 参数:无
  • 返回:string 识别出的文字;失败返回 nil, errMsg
cv_copyImageToMat(0, 0, 374, 811)   -- 先截屏为当前图像
local text, err = ocr_from_image()
if text then print("识别:", text) end

ocr_from_pixels(data, w, h, bpp) 已支持 android支持

识别原始像素数据中的文字。

  • data {string} 二进制像素数据(raw 字节串)
  • w, h {int} 图像宽高
  • bpp {int} 每像素字节数
  • 返回:string 识别出的文字;失败返回 nil, errMsg
local text = ocr_from_pixels(rawdata, 720, 1280, 4)

ocr_set_rectangle(left, top, w, h) 已支持 android支持

限定识别区域(相对当前图像/像素数据的坐标),只识别该区域内的文字。

  • left, top {int} 区域左上角
  • w, h {int} 区域宽高
  • 返回:bool 设置成功;失败返回 false, errMsg
ocr_set_rectangle(100, 200, 200, 100)

ocr_clear() 已支持 android支持

清除识别状态(区域限制、临时数据等)。

  • 参数:无
  • 返回:无
ocr_clear()

ocr_close() 已支持 android支持

释放识别引擎资源。

  • 参数:无
  • 返回:无
ocr_close()

ocr 模块(点阵字库识别/找字)

点阵字库 OCR(移植自 OP 插件,大漠同语义):用字库文件里每个字的 0/1 点阵,与屏幕按颜色二值化后的点阵逐位比对。与 tessocr / ppocr 的 AI 识别不同—— 只认识字库里有的字,但速度极快(毫秒级)、结果精确可控,适合游戏内固定字体的文字 (金币数量、按钮文字、菜单项、伤害数字等)。

字库文件:用「AutoGo图色助手」的字库制作导出(OP 文本格式,每行 名字$颜色$h,w,bit$HEX),放 <数据目录>/res/ 下(与 findPic 模板同基准)。 GBK / UTF-8 编码都认(GBK 自动转 UTF-8,脚本里可直接用中文比对)。

⚠️ 字库必须与目标画面同源同尺寸:字库是在哪张截图上取的,识别就得用同一分辨率、 同一字体渲染的画面(换分辨率 / 换设备 / 换窗口大小 = 字的像素尺寸变了 → 必须重取字库, 否则简单字勉强能中、笔画复杂的字必挂)。

匹配规则:sim 0.1~1.0,默认 1.0(精确:一个像素都不许错); sim<1 时按 有效相似度 = 0.5 + sim/2 放宽容差(如 sim=0.8 → 允许 10% 像素差异)。 建议优先用 1.0,识别不到再降(越低假阳性越多)。 区域必须完整包住文字:返回坐标是字形的左上角,区域边界把字窗口切掉一部分的 字会被直接跳过(下边界多留一个字高)。

ocrSetDict(idx, path) 已支持 android支持

载入字库文件到 idx 号槽位(0~99)。重复载入同槽 = 整槽覆盖。

  • idx {number} 槽位号 0~99
  • path {string} 字库文件路径;相对路径以 <数据目录>/res/ 为基准
  • 返回:number 载入的字数;失败返回 -1
  • 字库槽全局共用:主脚本与所有子线程看到的是同一份
local n = ocrSetDict(0, "opdict.txt")     -- 实际读 <数据目录>/res/opdict.txt
print("载入 " .. n .. " 个字")

ocrUseDict(idx) 已支持 android支持

切换当前使用的字库槽位(后续 ocr/findStr 都用它)。

  • idx {number} 槽位号 0~99
  • 返回:number 该槽字数;槽空返回 0
ocrSetDict(0, "dict_main.txt")   -- 主字库(菜单/按钮)
ocrSetDict(1, "dict_num.txt")    -- 数字字库(伤害/金币)
ocrUseDict(1)                    -- 切到数字字库做识别

ocrGetNowDict() 已支持 android支持

返回当前使用的槽位号(number)。

ocrGetDictCount(idx) 已支持 android支持

返回 idx 号槽的字数;该槽未载入返回 -1。

ocr(x1, y1, x2, y2, color?, sim?) 已支持 android支持

识别区域内所有字库字,按阅读顺序(|Δy|<9 视为同一行,行内按 x)拼接成字符串返回。

  • x1, y1, x2, y2 {number} 识别区域;x2/y2 ≤ 0 表示取到帧右下角
  • color {string} 可选,颜色串(同 findColor 格式):"RRGGBB[-偏色]", '|' 分隔多组;默认 "FFFFFF-323232"。必须与做字库时用的颜色口径一致
  • sim {number} 可选,相似度 0.1~1.0,默认 1.0
  • 返回:string 拼接后的识别文本(无命中返回空串)
ocrSetDict(0, "opdict.txt")
local s = ocr(200, 310, 480, 360, "FFFFFF-323232", 1.0)
print(s)          -- 例:雷电游戏中心

ocrEx(x1, y1, x2, y2, color?, sim?) 已支持 android支持

同 ocr,但返回逐字结果(含每个字的坐标)。

  • 参数同 ocr
  • 返回:table {{index=结果序号, name=字符, x=, y=}, ...}, index 从 0 起(阅读序),x/y = 字形左上角(屏幕绝对坐标)
local hits = ocrEx(0, 0, 0, 0, "FFFFFF-323232", 1.0)
for i, h in ipairs(hits) do
    print(h.index, h.name, h.x, h.y)
end

findStr(x1, y1, x2, y2, strs, color?, sim?) 已支持 android支持

在区域内找字库里指定的词,返回第一个命中的词。

  • strs {string} 目标词,'|' 分隔多词,如 "确定|取消"; 词名必须与字库里的一致
  • 返回:3 个值 —— idx 命中的词序号(0 = 第一个词,无命中 -1)、 x / y 该词首个命中字形的左上角(无命中 -1,-1)
local idx, x, y = findStr(0, 0, 0, 0, "确定|取消", "FFFFFF-323232", 1.0)
if idx == 0 then
    print("找到 确定 @ " .. x .. "," .. y)      -- 点它: tap(x + 10, y + 10)
elseif idx == 1 then
    print("找到 取消 @ " .. x .. "," .. y)
end

findStrEx(x1, y1, x2, y2, strs, color?, sim?) 已支持 android支持

同 findStr,但返回全部命中。

  • 参数同 findStr
  • 返回:table {{index=词序号, name=词名, x=, y=}, ...}(无命中空表)
local all = findStrEx(0, 0, 0, 0, "雷|闪电|中心", "FFFFFF-323232", 1.0)
for i, h in ipairs(all) do
    print("词" .. h.index .. " [" .. h.name .. "] @ " .. h.x .. "," .. h.y)
end

ppocr 模块

ppocr_create() 已支持 android支持

创建文字识别器实例。

  • 参数:无
  • 返回:bool 创建成功;失败返回 false, errMsg
local ok = ppocr_create()

ppocr_init(det.param, det.bin, rec.param?, rec.bin?, cls.param?, cls.bin?) 已支持 android支持

加载识别模型(检测模型必填,识别/分类模型可选)。

  • det.param, det.bin {string} 文本检测模型文件路径
  • rec.param, rec.bin {string} 可选,文字识别模型文件路径
  • cls.param, cls.bin {string} 可选,方向分类模型文件路径
  • 返回:bool 加载成功;失败返回 false, errMsg
local M = "/data/local/tmp/com.luatouch.app/models/ch/"
local ok = ppocr_init(
    M .. "PP_OCRv5_mobile_det.ncnn.param", M .. "PP_OCRv5_mobile_det.ncnn.bin",
    M .. "PP_OCRv5_mobile_rec.ncnn.param", M .. "PP_OCRv5_mobile_rec.ncnn.bin")

ppocr_set_param(name, value) 已支持 android支持

设置识别参数。底层引擎为自研 PP-OCRv5(ncnn 推理),只支持下表列出的 8 个参数名,不沿用 PaddleOCR 官方配置文件里的字段名。

  • name {string} 参数名,见下方参数表
  • value {string} 参数值,必须用字符串传入:数值写 "0.45"、"960",布尔用 "1" / "0"
  • 返回:bool 仅在未先调用 ppocr_create 时返回 false, "PPOcr not created";其余情况一律返回 true

返回值不能用来判断参数是否生效(与 ocr_set_param 不同):

  • 参数名不在下表内(拼错、或用了 PaddleOCR 的字段名如 det_db_thresh、rec_img_h、num_threads)→ 静默忽略,仍然返回 true
  • 本接口可重复调用、后设覆盖先设;参数在 ppocr_create 之后即可设置,不必等 ppocr_init,且 ppocr_init 不会重置已设参数
  • 执行 ppocr_release 后再 ppocr_create 会得到全新实例,全部参数恢复默认值
  • 线程数不可调:检测固定用 ncnn 大核数、识别固定单线程

可用参数表

参数名类型默认说明
target_sizeint640检测阶段输入图最长边的缩放上限(超过则等比缩小后再送模型)。调大:小字更清晰但变慢;调小:更快,小字可能漏检
box_threshfloat0.6候选文本框的平均得分阈值(0~1),低于该值的框被丢弃。调低:框更多(含噪声);调高:框更少更干净
thresholdfloat0.3检测概率图的二值化阈值。调低:文字区域更连片(易粘连);调高:更严格(易断裂)
min_size_basefloat3.0最小框尺寸基准,实际最小边 ≈ min_size_base × 缩放比,用于过滤极小噪点框。调大:滤掉小字
max_candidatesint1000单张图最多处理的候选轮廓数,超出直接截断。密集文本可调大
enlarge_ratiofloat1.95文本框向外扩张比例,保证文字边缘被完整裁入。过大易把相邻文字并进同一行
post_process_modeint0后处理方式:0=按比例扩张矩形(快);1=DBNet unclip(按轮廓面积/周长扩张,更贴合文字形状,稍慢)
target_heightint48识别阶段文字行统一缩放到的高度。调大:小字/笔画复杂字符更准但更慢;调小:更快
ppocr_create()
ppocr_init(M .. "PP_OCRv5_mobile_det.ncnn.param", M .. "PP_OCRv5_mobile_det.ncnn.bin",
           M .. "PP_OCRv5_mobile_rec.ncnn.param", M .. "PP_OCRv5_mobile_rec.ncnn.bin")

-- 小字场景:加大检测分辨率、放宽候选框阈值
ppocr_set_param("target_size", "960")
ppocr_set_param("box_thresh", "0.4")

-- 密集文本:提高候选上限
ppocr_set_param("max_candidates", "3000")

-- 更贴合文字轮廓的后处理(略慢)
ppocr_set_param("post_process_mode", "1")
ppocr_set_param("enlarge_ratio", "1.8")

ppocr_detect_image() 已支持 android支持

识别当前图像中的文字(配合 cv_copyImageToMat 截取屏幕区域),返回逐行文字及位置。

  • 参数:无
  • 返回:table 结果表 {width, height, lines={{text=, rate=, left=, top=, right=, bottom=}, ...}};失败返回 nil, errMsg
  • width, height 识别图像尺寸;lines 每行文字,text 文字内容,rate 置信度 0~1,left/top/right/bottom 位置坐标(0~1 归一化,乘屏幕宽高得像素)
cv_copyImageToMat(0, 0, 374, 811)   -- 先截屏为当前图像
local res = ppocr_detect_image()
if res then
    for i, line in ipairs(res.lines) do
        print(i, line.text, string.format("%.2f", line.rate))
    end
end

ppocr_detect_file(path) 已支持 android支持

识别指定图片文件中的文字,返回格式同 ppocr_detect_image。

  • path {string} 图片路径
  • 返回:table 结果表;失败返回 nil, errMsg
local res = ppocr_detect_file("/data/local/tmp/com.luatouch.app/screen.png")

ppocr_release() 已支持 android支持

释放识别器资源。

  • 参数:无
  • 返回:bool 是否成功释放
ppocr_release()

hud 模块(悬浮显示)

showUi(path [, countdown [, query [, hash [, w [, h]]]]]) 已支持 android支持

显示 HTML 面板并阻塞等待用户操作。面板跟随屏幕横竖方向(横屏下面板旋转显示,宽高按所见方向自动换算);默认尺寸为屏幕宽高的 90% 居中。返回两个值:操作结果 + JS 带回的表单数据。

  • path {string} 加载目标:绝对路径(/data/local/tmp/...)、file:// 绝对路径(可自带 ?query)、http(s):// 远程 URL、或裸 HTML 字符串
  • countdown {int} 可选,默认 0:开始按钮倒计时秒数;>0 时按钮显示「开始(N)」每秒减一,归零自动触发「开始」
  • query {string} 可选,默认 0 / -1 / 空 = 不传:拼接在 URL ? 后,引擎自动 percent-encode(main.lua 直接传裸 JSON 即可)
  • hash {string} 可选,默认 0 / -1 / 空 = 不传:拼接在 URL # 后,引擎自动 percent-encode(query 的兜底通道)
  • w {number} 可选,默认 0:面板宽(每维独立)——≤0 或不传 = 屏幕宽 × 90%;0~1 = 屏幕宽的比例(如 0.5 = 半屏宽);>1 = 像素值(与 getScreenSize() 同一坐标系)
  • h {number} 可选,默认 0:面板高,规则同 w(按屏幕高计算)
  • 返回:result {int} 1=点「开始」/倒计时归零,0=点「关闭」,-1=叉号/其他方式关闭(含 hideUi 唤醒);data {string|nil} 面板 JS 在开始/关闭时带回的表单 JSON 字符串,无则 nil
-- 打开面板,把上次配置 JSON 作为 query 传入(裸 JSON,引擎 percent-encode 注入 ? 后)
local r, data = showUi("/data/local/tmp/com.luatouch.app/config/ui/index.html", 0, cfgJson)
if r == 1 then
    -- 用户点了「开始」,data 为表单 JSON,可直接落盘下次复用
elseif r == -1 then
    -- 用户关闭了面板
end

参数传递机制:引擎把第三参 percent-encode 后拼到 URL ? 后、第四参拼到 # 后。JS 端读取:location.search 优先 → location.hash 兜底 → 去 ?/# 前缀 → decodeURIComponent → JSON.parse(search 为第一通道,hash 仅在 search 为空时兜底)。

hideUi() 已支持 android支持

隐藏 HTML 面板;若有 showUi 正在阻塞,则唤醒并使其按「叉号关闭」返回 -1(无 data)。

  • 返回:无
hideUi()   -- 关闭面板(定时器等场景主动收起)

isShowUi() 已支持 android支持

检查 HTML 面板是否正在显示。

  • 返回:bool true 显示中 / false 未显示
if isShowUi() then
    -- 面板还开着,先别重复打开
end

toast(message [, x [, y [, duration]]]) 已支持 android支持

显示 Toast 提示信息(非阻塞,自动消失)。

  • message {string} 要显示的提示信息
  • x {int} 可选,默认 -1:显示 X 坐标(-1 = 水平居中)
  • y {int} 可选,默认 -1:显示 Y 坐标(-1 = 垂直居中)
  • duration {int} 可选,默认 -1:显示时长毫秒(-1 = 2000ms)
  • 返回:无
toast("Hello LuaTouch", -1, -1, -1)   -- 默认居中 2 秒
toast("操作完成", 100, 300, 3000)      -- 指定位置 3 秒

alert(title, content [, btn1Text [, btn2Text]]) 已支持 android支持

弹出系统级对话框,阻塞直到用户点击按钮。

  • title {string} 弹窗标题
  • content {string} 弹窗内容
  • btn1Text {string} 可选,默认「确定」:第一个按钮文字
  • btn2Text {string} 可选,默认空:第二个按钮文字;传空字符串则只显示一个按钮
  • 返回:int 0 = 点击第一个按钮,1 = 点击第二个按钮
local r = alert("确认操作", "是否继续?", "取消", "确定")
if r == 1 then
    -- 用户点了确定
end

inputAlert(title, content [, placeholder [, defaultText [, btn1Text [, btn2Text]]]]) API 存在

弹出带输入框的系统级对话框,阻塞等待用户操作。

  • title {string} 弹窗标题
  • content {string} 说明文字
  • placeholder {string} 可选,默认空:输入框占位提示
  • defaultText {string} 可选,默认空:输入框默认文本
  • btn1Text {string} 可选,默认「取消」:取消类按钮文字
  • btn2Text {string} 可选,默认「确定」:确认类按钮文字;为空则只显示一个按钮
  • 返回:text {string} 输入内容;ok {bool} true = 点击确认按钮,false = 点击取消
local text, ok = inputAlert("输入", "请输入备注", "备注", "", "取消", "确定")
if ok then
    -- 使用 text
end

setBallPosition(fx, fy) 已支持 android支持

移动悬浮球并保持停靠(横竖屏自动适配)。

  • fx {number} 停靠边:0=左,1=右
  • fy {number} 边缘高度百分比(0~1,支持小数点后两位)
  • 返回:无
setBallPosition(0, 0.1)   -- 靠左边缘 10% 高
setBallPosition(1, 0.5)   -- 靠右边缘中间

hud.new() 已支持 android支持

创建一个新的 HUD 实例。

  • 参数:无
  • 返回:userdata HUD 实例(方法均返回自身,支持链式调用)
local h = hud.new()

h:setPosition(fx, fy, width, height) 已支持 android支持

设置 HUD 的位置和大小(旋转自动适配)。

  • fx, fy {number} 左上角百分比(0~1,支持小数点后两位)
  • width, height {int} 宽高(屏幕点,整数)
  • 返回:userdata 自身(可链式)
h:setPosition(0.1, 0.8, 300, 60)   -- 左上角 10%、80% 处,宽 300 高 60

h:setBackgroundColor(color) 已支持 android支持

设置 HUD 背景颜色(支持透明度)。

  • color {string} 十六进制,#RRGGBB 或 #RRGGBBAA(AA 为透明度)
  • 返回:userdata 自身
h:setBackgroundColor("#2D2D30")
h:setBackgroundColor("#00000080")  -- 半透明黑色

h:setTextSize(size) 已支持 android支持

设置 HUD 字体大小。

  • size {int} 字体大小(推荐 30~60)
  • 返回:userdata 自身
h:setTextSize(45)

h:setText(items) 已支持 android支持

设置 HUD 文本内容(支持多色文本)。

  • items {table} 文本项数组,每项含 TextColor(颜色字符串)与 Text(文本)
  • 返回:userdata 自身
h:setText({
    {TextColor = "#00FF00", Text = "HP: "},
    {TextColor = "#FFFFFF", Text = "100/100"},
})

h:show() 已支持 android支持

显示 HUD。

  • 返回:userdata 自身
h:show()

h:hide() 已支持 android支持

隐藏 HUD。

  • 返回:userdata 自身
h:hide()

h:isVisible() 已支持 android支持

检查 HUD 是否可见。

  • 返回:bool true 可见 / false 隐藏
if h:isVisible() then
    -- HUD 当前可见
end

h:destroy() 已支持 android支持

销毁 HUD 实例,释放窗口资源(也可等 Lua GC 自动回收)。

  • 返回:无
h:destroy()

示例 已支持 android支持

-- 创建并配置 HUD
local h = hud.new()
h:setPosition(0.1, 0.8, 300, 60)   -- 屏幕下方,宽 300 高 60
 :setBackgroundColor("#3D000080")
 :setTextSize(45)

while true do
    h:setText({
        {TextColor = "#00FF00", Text = "当前时间: "},
        {TextColor = "#FFFFFF", Text = os.date("%Y-%m-%d %H:%M:%S")},
    })
    sleep(1000)
end

draw 模块(屏幕绘制)

drawLine(x0, y0, x1, y1, argb, thickness) 已支持 android支持

绘制一条直线(任意角度斜线均可,两端圆头)。

  • x0, y0 {int} 起始点坐标
  • x1, y1 {int} 终点坐标
  • argb {int} 颜色,如 0xffff0000(红色)
  • thickness {int} 线宽(物理像素,自动换算)
  • 返回:{int} 图形句柄(用于 clearDraw(句柄) 清除)
local id = drawLine(100, 100, 1100, 2000, 0xffff0000, 20)  -- 斜线
-- clearDraw(id) 清除这条线

drawRect(x0, y0, x1, y1, argb, thickness) 已支持 android支持

绘制矩形框;thickness = -1 填充。

  • x0, y0 {int} 左上角坐标
  • x1, y1 {int} 右下角坐标
  • argb {int} 颜色
  • thickness {int} 线宽,-1 填充
  • 返回:{int} 句柄
local id = drawRect(300, 400, 900, 900, 0xff00ff00, 10)  -- 绿框

fillRect(x0, y0, x1, y1, argb) 已支持 android支持

填充一个矩形区域。

  • x0, y0 {int} 左上角坐标
  • x1, y1 {int} 右下角坐标
  • argb {int} 颜色(可用 0x80 前缀做半透明)
  • 返回:{int} 句柄
local id = fillRect(700, 300, 1000, 600, 0x80ff0000)  -- 半透明红填充

drawCircle(x, y, radius, argb, thickness) 已支持 android支持

绘制圆形;thickness = -1 填充。

  • x, y {int} 圆心坐标
  • radius {int} 半径
  • argb {int} 颜色
  • thickness {int} 线宽,-1 填充
  • 返回:{int} 句柄
local id = drawCircle(621, 1104, 200, 0xff0000ff, -1)  -- 屏幕中心蓝色填充圆

drawPolygon(points, argb, thickness, isclosed) 已支持 android支持

绘制多边形;thickness = -1 填充。

  • points {table} 顶点数组 {{x1,y1},{x2,y2},...}
  • argb {int} 颜色
  • thickness {int} 线宽,-1 填充
  • isclosed {boolean} 是否闭合
  • 返回:{int} 句柄
local id = drawPolygon({{200,1600},{500,1500},{450,1850}}, 0xff00ff00, 8, true)

clearDraw(id?) 已支持 android支持

清除屏幕绘制图形。

  • id {int|nil} 可选:传句柄只清除对应图形;不传清除全部
  • 返回:无
clearDraw(id1)   -- 只清句柄 id1 对应的图形
clearDraw()      -- 全部清除

示例 已支持 android支持

-- 标注:找到按钮画框、点击位置画圈(坐标=物理像素,按自己屏幕分辨率换算)
local box = drawRect(300, 400, 900, 900, 0xffff0000, 10)   -- 红框标注
local dot = drawCircle(621, 1104, 60, 0xff00ff00, -1)      -- 绿点标注
sleep(1000)
clearDraw(box)      -- 单独清除红框,绿点保留
sleep(1000)
clearDraw()         -- 全部清除

uiacc 节点

1. 根据节点的id属性匹配 (id) 已支持 android支持

说明: 根据节点的id属性匹配

函数: id(str)

参数名类型必填说明
strstring是指定要查找的具体控件的id
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = id("com.luatouch.app:id/detail_tv_title")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

2. 根据id包含的部分字符串匹配 (idContains) 已支持 android支持

说明: 根据id包含的部分字符串匹配(正则 :match)

函数: idContains(str)

参数名类型必填说明
strstring是指定要查找的模糊的包含id某一段字符串的内容
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = idContains("detail_tv_title")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

3. 根据id的前缀去匹配 (idStartsWith) 已支持 android支持

说明: 根据id的前缀去匹配(正则 :match('^' .. str))

函数: idStartsWith(str)

参数名类型必填说明
strstring是指定要查找的id的前缀
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = idStartsWith("com.luatouch.app")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:id())
end

4. 根据id的后缀去匹配 (idEndsWith) 已支持 android支持

说明: 根据id的后缀去匹配(正则 :match(str .. '$'))

函数: idEndsWith(str)

参数名类型必填说明
strstring是指定要查找的id的后缀
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = idEndsWith("detail_tv_title")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

5. 正则匹配id (idMatches) 已支持 android支持

说明: 正则匹配id

函数: idMatches(str)

参数名类型必填说明
strstring是正则表达式字符串
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = idMatches(".*detail_tv_title$")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

6. 根据节点的text属性匹配 (text) 已支持 android支持

说明: 根据节点的text属性匹配

函数: text(str)

参数名类型必填说明
strstring是指定要查找的具体控件的text
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = text("LuaTouch高级版")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

7. 根据text包含的部分字符串匹配 (textContains) 已支持 android支持

说明: 根据text包含的部分字符串匹配(正则 :match)

函数: textContains(str)

参数名类型必填说明
strstring是指定要查找的模糊的包含text某一段字符串的内容
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = textContains("LuaTouch")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

8. 根据text的前缀去匹配 (textStartsWith) 已支持 android支持

说明: 根据text的前缀去匹配(正则 :match('^' .. str))

函数: textStartsWith(str)

参数名类型必填说明
strstring是指定要查找的text的前缀
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = textStartsWith("LuaTouch")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

9. 根据text的后缀去匹配 (textEndsWith) 已支持 android支持

说明: 根据text的后缀去匹配(正则 :match(str .. '$'))

函数: textEndsWith(str)

参数名类型必填说明
strstring是指定要查找的text的后缀
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = textEndsWith("高级版")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

10. 正则匹配text (textMatches) 已支持 android支持

说明: 正则匹配text

函数: textMatches(str)

参数名类型必填说明
strstring是正则表达式字符串
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = textMatches(".*高级版$")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

11. 根据节点的desc属性匹配 (desc) 已支持 android支持

说明: 根据节点的desc属性匹配

函数: desc(str)

参数名类型必填说明
strstring是指定要查找的具体控件的desc
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = desc("LuaTouch高级版")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

12. 根据desc包含的部分字符串匹配 (descContains) 已支持 android支持

说明: 根据desc包含的部分字符串匹配(正则 :match)

函数: descContains(str)

参数名类型必填说明
strstring是指定要查找的模糊的包含desc某一段字符串的内容
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = descContains("LuaTouch")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

13. 根据desc的前缀去匹配 (descStartsWith) 已支持 android支持

说明: 根据desc的前缀去匹配(正则 :match('^' .. str))

函数: descStartsWith(str)

参数名类型必填说明
strstring是指定要查找的desc的前缀
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = descStartsWith("LuaTouch")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

14. 根据desc的后缀去匹配 (descEndsWith) 已支持 android支持

说明: 根据desc的后缀去匹配(正则 :match(str .. '$'))

函数: descEndsWith(str)

参数名类型必填说明
strstring是指定要查找的desc的后缀
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = descEndsWith("高级版")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

15. 正则匹配desc (descMatches) 已支持 android支持

说明: 正则匹配desc

函数: descMatches(str)

参数名类型必填说明
strstring是正则表达式字符串
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = descMatches(".*高级版$")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

16. 根据节点的className属性匹配 (className) 已支持 android支持

说明: 根据节点的className属性匹配

函数: className(str)

参数名类型必填说明
strstring是指定要查找的具体控件的类名
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = className("AXStaticText")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

17. 根据className属性所包含的字符串模糊匹配 (classNameContains) 已支持 android支持

说明: 根据className属性所包含的字符串模糊匹配(正则 :match)

函数: classNameContains(str)

参数名类型必填说明
strstring是指定要查找className包含该字符的节点
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = classNameContains("Text")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:className())
end

18. 根据className属性前缀匹配 (classNameStartsWith) 已支持 android支持

说明: 根据className属性前缀匹配(正则 :match('^' .. str))

函数: classNameStartsWith(str)

参数名类型必填说明
strstring是指定要查找className前缀为该字符的节点
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = classNameStartsWith("AX")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:className())
end

19. 根据className属性后缀匹配 (classNameEndsWith) 已支持 android支持

说明: 根据className属性后缀匹配(正则 :match(str .. '$'))

函数: classNameEndsWith(str)

参数名类型必填说明
strstring是指定要查找className后缀为该字符的节点
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = classNameEndsWith("StaticText")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

20. 根据className属性正则匹配 (classNameMatches) 已支持 android支持

说明: 根据className属性正则匹配

函数: classNameMatches(str)

参数名类型必填说明
strstring是指定要匹配className的正则表达式
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = classNameMatches("^AX.*Text$")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

21. 根据packageName属性全字段匹配 (packageName) 已支持 android支持

说明: 根据packageName属性全字段匹配

函数: packageName(str)

参数名类型必填说明
strstring是指定要匹配节点所属的包名
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = packageName("com.apple.mobilesafari"):className("AXStaticText")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

22. 匹配包含指定字符串的节点 (packageNameContains) 已支持 android支持

说明: 匹配包含指定字符串的节点(正则 :match)

函数: packageNameContains(str)

参数名类型必填说明
strstring是包含该字符串的包名的节点将被匹配到
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = packageNameContains("apple"):className("AXStaticText")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

23. 匹配包名前缀为指定字符串的节点 (packageNameStartsWith) 已支持 android支持

说明: 匹配包名前缀为指定字符串的节点(正则 :match('^' .. str))

函数: packageNameStartsWith(str)

参数名类型必填说明
strstring是包名为该字符的前缀的节点将被匹配到
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = packageNameStartsWith("com.apple"):className("AXStaticText")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

24. 匹配包名后缀为指定字符串的节点 (packageNameEndsWith) 已支持 android支持

说明: 匹配包名后缀为指定字符串的节点(正则 :match(str .. '$'))

函数: packageNameEndsWith(str)

参数名类型必填说明
strstring是包名为该字符的后缀的节点将被匹配到
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = packageNameEndsWith("mobilesafari"):className("AXStaticText")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

25. 包名正则匹配 (packageNameMatches) 已支持 android支持

说明: 包名正则匹配

函数: packageNameMatches(str)

参数名类型必填说明
strstring是根据这个正则字符串匹配所有符合规则包名的节点
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = packageNameMatches("com.apple.*"):className("AXStaticText")
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

26. 根据节点的范围匹配 (bounds) 已支持 android支持

说明: 根据节点的范围匹配(精确匹配 bounds 坐标)

函数: bounds(l, t, r, b)

参数名类型必填说明
lnumber是左范围
tnumber是上范围
rnumber是右范围
bnumber是下范围
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = bounds(30, 212, 236, 250)
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

27. 匹配该范围内的节点 (boundsInside) 已支持 android支持

说明: 匹配 bounds 完全包含在指定范围内的节点

函数: boundsInside(l, t, r, b)

参数名类型必填说明
lnumber是左范围
tnumber是上范围
rnumber是右范围
bnumber是下范围
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = boundsInside(30, 212, 236, 250)
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

28. 根据绘制顺序匹配 (drawingOrder) 已支持 android支持

说明: 根据绘制顺序匹配

函数: drawingOrder(level)

参数名类型必填说明
levelnumber是绘制顺序级别
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = drawingOrder(1)
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

29. 根据深度索引匹配 (depth) 已支持 android支持

说明: 根据深度索引匹配

函数: depth(level)

参数名类型必填说明
levelnumber是深度索引级别
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = depth(1)
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

30. 根据在当前父节点里面的索引顺序查找 (index) 已支持 android支持

说明: 根据在当前父节点里面的索引顺序查找

函数: index(level)

参数名类型必填说明
levelnumber是索引级别
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = index(1)
local node = sel:findOne(10000)
if node ~= nil then
    print(node:text())
end

31. 根据是否可见匹配 (visibleToUser) 已支持 android支持

说明: 根据是否可见匹配

函数: visibleToUser(b)

参数名类型必填说明
bboolean是是否可见
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = visibleToUser(true)
local node = sel:findOne(10000)
if node ~= nil then
    print(node:className())
end

32. 根据是否选中匹配 (selected) 已支持 android支持

说明: 根据是否选中匹配

函数: selected(b)

参数名类型必填说明
bboolean是是否选中
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = selected(true)
local node = sel:findOne(10000)
if node ~= nil then
    print(node:className())
end

33. 根据是否可点击匹配 (clickable) 已支持 android支持

说明: 根据是否可点击匹配

函数: clickable(b)

参数名类型必填说明
bboolean是是否可点击
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = clickable(true)
local node = sel:findOne(10000)
if node ~= nil then
    print(node:className())
end

34. 根据是否可长按点击匹配 (longClickable) 已支持 android支持

说明: 根据是否可长按点击匹配

函数: longClickable(b)

参数名类型必填说明
bboolean是是否可长按点击
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = longClickable(true)
local node = sel:findOne(10000)
if node ~= nil then
    print(node:className())
end

35. 根据是否可用匹配 (enabled) 已支持 android支持

说明: 根据是否可用匹配

函数: enabled(b)

参数名类型必填说明
bboolean是是否可用
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = enabled(true)
local node = sel:findOne(10000)
if node ~= nil then
    print(node:className())
end

36. 根据是否是密码框匹配 (password) 已支持 android支持

说明: 根据是否是密码框匹配

函数: password(b)

参数名类型必填说明
bboolean是是否是密码框
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = password(true)
local node = sel:findOne(10000)
if node ~= nil then
    print(node:className())
end

37. 根据是否可以滚动来匹配 (scrollable) 已支持 android支持

说明: 根据是否可以滚动来匹配

函数: scrollable(b)

参数名类型必填说明
bboolean是是否可以滚动
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = scrollable(true)
local node = sel:findOne(10000)
if node ~= nil then
    print(node:className())
end

38. 根据是否被勾选来匹配 (checked) 已支持 android支持

说明: 根据是否被勾选来匹配

函数: checked(b)

参数名类型必填说明
bboolean是是否被勾选
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = checked(true)
local node = sel:findOne(10000)
if node ~= nil then
    print(node:className())
end

39. 根据是否可以被勾选来匹配 (checkable) 已支持 android支持

说明: 根据是否可以被勾选来匹配

函数: checkable(b)

参数名类型必填说明
bboolean是是否可以被勾选
返回值类型说明
selector返回一个选择器对象,该对象支持级联选择
local sel = checkable(true)
local node = sel:findOne(10000)
if node ~= nil then
    print(node:className())
end

findOne(timeoutMs) 已支持 android支持

查找第一个匹配节点,未找到返回 nil。

一次调用只采集一次节点树(不是内部循环轮询):引擎会拉起一次节点采集并等待结果,拿到后在结果里做匹配。所以「等某个元素出现」需要自己写成循环(见下方示例),或用 exists()。

参数名类型必填说明
timeoutMsint否等待本次采集完成的上限毫秒数,默认 10000;传 0 或负数会按 3000 处理(不会变成“立即返回”)
返回值类型说明
node匹配的节点对象;未找到 / 采集超时 / 采集失败均返回 nil
  • 采集超时(timeoutMs 到点)会终止本次采集并返回 nil
  • 同一时刻只允许一次采集:上一次还没结束时再调用,会直接返回 nil(不会排队等待)
  • 采集过程中子进程要先把「屏幕中心点采样」重试到成功(最坏约 50 次 × 50ms ≈ 2.5 秒),因此 timeoutMs 给得过小(如 1000)可能在产出前就被截断;建议 ≥ 3000
local node = text("LuaTouch"):findOne(5000)
if node then
    print("找到", node:text(), node:bounds())
end

-- findOne 不会自己重试,需要“等元素出现”时自己轮询:
local function waitText(t, ms)
    local deadline = axTimeMs() + ms
    while axTimeMs() < deadline do
        local n = t:findOne(3000)
        if n then return n end
        axSleep(300)
    end
    return nil
end
local btn = waitText(textContains("确定"), 10000)

find(timeoutMs) 已支持 android支持

查找所有匹配节点,返回数组(顺序 = 节点树中的先后顺序);未找到返回空表 {}。

与 findOne 一样是一次采集:采集一次节点树,然后在结果里收集全部匹配节点。

参数名类型必填说明
timeoutMsint否等待本次采集完成的上限毫秒数,默认 10000;传 0 或负数按 3000 处理
返回值类型说明
node[]匹配的节点数组;未找到 / 采集超时 / 采集失败均返回空表 {}
local ns = textContains("确定"):find(3000)
print("找到", #ns, "个")
for i, n in ipairs(ns) do
    print(i, n:text(), n:bounds())
end

findOnce(timeoutMs) / exists(timeoutMs) 已支持 android支持

选择器上的两个便捷方法(同样是一次采集):

方法返回说明
sel:findOnce(t)node | nilfindOne 的别名,行为完全一致(默认 10000ms)
sel:exists(t)boolean是否存在匹配节点,等价于 findOne(t) ~= nil;只关心“有没有”时更直观
-- 等按钮出现:自己轮询(每次采集一次,间隔 300ms)
local function waitExists(sel, ms)
    local deadline = axTimeMs() + ms
    while axTimeMs() < deadline do
        if sel:exists(3000) then return true end
        axSleep(300)
    end
    return false
end

if waitExists(textContains("确定"), 10000) then
    local n = textContains("确定"):findOnce(3000)
    local l, t, r, b = n:bounds()
    tap((l + r) / 2, (t + b) / 2)
end

节点方法

通过 findOne / find 拿到的节点对象是属性读取器:每个方法读取该节点对应的属性并返回,不参与匹配。属性不存在时不会报错——字符串返回 ""、数值返回 0、布尔返回 false。

方法返回类型说明
n:text()string节点显示文本
n:id()string节点唯一标识(resource-id)
n:desc()string无障碍描述(content-desc)
n:className()string节点类名
n:packageName()string所属应用包名
n:bounds()l,t,r,b节点矩形坐标(4 个返回值,物理像素)
n:clickable()boolean是否可点击
n:enabled()boolean是否可用
n:focusable()boolean是否可获得焦点
n:focused()boolean当前是否已聚焦
n:visibleToUser()boolean是否可见
n:selected()boolean是否选中
n:checkable()boolean是否可勾选
n:checked()boolean是否已勾选
n:scrollable()boolean是否可滚动
n:longClickable()boolean是否可长按
n:password()boolean是否是密码框
n:depth()int节点深度
n:index()int在父节点中的索引
n:drawingOrder()int绘制顺序
local n = text("LuaTouch"):findOne(5000)
if n then
    print("text =", n:text())
    print("class =", n:className())
    print("clickable =", n:clickable())
    local l, t, r, b = n:bounds()
    print("bounds =", l, t, r, b)
end

除方法外,节点对象还支持与 iOS 一致的字段写法(n._text 等,按需从节点属性读取,默认值规则同方法):

字段等价方法返回类型
n._textn:text()string
n._idn:id()string
n._classn:className()string
n._descn:desc()string
n._packagen:packageName()string
n._depthn:depth()int
n._indexn:index()int
n._drawingordern:drawingOrder()int
local n = depth(0):findOne(5000)
print(n._class, n._package)   -- android.view.View    android

链式组合(多条件 AND)

用 : 链式串联多个 selector,节点必须同时满足所有条件才匹配。

-- 同时满足:文本包含"确定" 且 可见 且 可点击
local n = textContains("确定"):visibleToUser(true):clickable(true):findOne(5000)

-- 包名 + 类名组合
local n2 = packageName("com.apple.mobilesafari"):className("AXStaticText"):findOne(3000)

点击节点

节点对象没有 click() 方法。标准做法:取节点 bounds 的中心 → 调用引擎 tap(x, y)。bounds 与 tap 都用物理像素,直接传即可,无需换算。

local n = text("LuaTouch"):findOne(5000)
if n then
    local l, t, r, b = n:bounds()
    local cx, cy = (l + r) / 2, (t + b) / 2
    tap(cx, cy)
end

底层 API

函数返回说明
axGetXml(timeout?)string直接取一次节点树 XML 字符串。默认 3000ms;timeout ≤ 0 按 3000 处理。失败/超时返回空字符串 "",不是 nil。同一时刻只允许一次采集,重入时也返回 ""。findOne / find 内部就是调它,一般不用自己调
axSleep(ms?)无阻塞等待指定毫秒,默认 100。属于无障碍模块的休眠,不响应脚本的暂停/停止——脚本里请优先用全局 sleep(),需要与节点采集节奏对齐时才用 axSleep
axTimeMs()int当前时间戳,单位毫秒(Unix epoch)。用于算耗时/超时截止时间

旧版 axGetTree / axDumpAttrs 已删除(不再整树转 Lua 表;属性改由节点对象的方法按需读取)。

-- 取原始节点树 XML(调试用)
local xml = axGetXml(3000)
if xml ~= "" then            -- 注意:失败返回空字符串,不是 nil
    print("XML 长度:", #xml)
else
    print("采集失败/超时")
end

-- 用 axTimeMs 自己控制等待时长
local deadline = axTimeMs() + 5000
while axTimeMs() < deadline do
    if textContains("确定"):exists(3000) then break end
    axSleep(300)
end

注意事项

  • 前台切换:节点树会随前台 App 变化,切换后建议先 findOne(5000) 等新树稳定。
  • 正则引擎:Contains / StartsWith / EndsWith / Matches 内部全用 Lua string.match,支持 Lua 正则语法(非 PCRE)。
  • 精确匹配:text("A") 是精确匹配;模糊匹配用 textContains / textMatches。
  • 性能:取树 12 个窗口 ~3000+ 节点,单次 ~50ms。建议 findOne + 短超时。
本地文档 · 引擎版本 v1.10.775
script 模块(2 个):exitScript / restartScript(脚本退出与重启)
app 模块(13 个):appCurrentPackage / appLaunch / appForceStop / appGetList / appGetBundlePath / appGetDataPath / appSelfPackage / appGetVersion / appUninstall / appInstall / appClear / appOpenUrl / appGetPackageName
device 模块(17 个):deviceGet / deviceGetDisplayInfo / deviceVpnStatus / deviceSetVPNEnabled / deviceSetWiFiEnabled / deviceGetBattery / deviceGetBatteryStatus / deviceIsScreenOn / deviceIsScreenUnlock / deviceGetBrightness / deviceGetTotalMem / deviceGetAvailMem / deviceWakeUp / deviceKeepScreenOn / deviceGetIp / deviceGetWifiMac / deviceReboot
file 模块(6 个):deleteFile / moveFile / unzipFile / readFileAsBase64 / base64Encode / base64Decode(base64 为通用编解码,解码自动忽略空白与填充)
http 模块(5 个):httpGet / httpPost / downloadFile / tableToJson / jsonToTable(支持 HTTP/HTTPS)
ime 模块(4 个):imeInputText / imePasteText / imeGetClipText / imeSetClipText(引擎唯一剪贴板 API)
touch 模块(8 个):tap / swipe / key / keyRaw / keyMeta / touchDown / touchMove / touchUp(坐标为物理像素,与 getScreenSize 一致)
color 模块(12 个):getPixel / getRGB / getScreenSize / findColor / isColor / findMultiColors / tableFindMultiColors / findPic / findPicEx / getColorCountInRegion / detectsMultiColors / screenshot(颜色格式 目标-容差,如 ffffff-323232;isColor 为单点快速判定)
opencv 模块(12 个):cv_copyImageToMat / cv_resizeImage / cv_thresholdImage / cv_colorDeviationBinary / cv_clahe / cv_sharpen / cv_morphology / cv_find_image_by_path / cv_saveImage / cv_matToBase64 / cv_rotateImage / cv_cleanup
tessocr 模块(8 个):ocr_init / ocr_set_param / ocr_from_file / ocr_from_image / ocr_from_pixels / ocr_set_rectangle / ocr_clear / ocr_close(语言数据在 data_root/models/tessdata)
ppocr 模块(6 个):ppocr_create / ppocr_init / ppocr_set_param / ppocr_detect_image / ppocr_detect_file / ppocr_release(模型在 data_root/models/ch/,坐标归一化 0~1)
hud 模块(15 个):showUi / hideUi / isShowUi / toast / alert / inputAlert / hud.new / setPosition / setBackgroundColor / setTextSize / setText / show / hide / isVisible / destroy(showUi 为全屏 HTML 面板,支持 JSON 配置注入与表单回传,内置自绘键盘;toast/alert 为系统级 UI 提示、inputAlert(带输入框)iOS 不支持;hud 多实例彩色文本浮层,坐标为屏幕点,方法返回自身支持链式)
各模块已全部实现,无待实现函数;均为全局函数(无模块前缀);deviceSetVPNEnabled / deviceSetWiFiEnabled 为 iOS 平台限制(恒返回 false)