AutoLua 是基于 LuaJava 的安卓轻量级脚本工具,在 Lua 中直接调用 Java/Android API,无需编译。
典型场景:
默认工程目录:
init.lua 初始化脚本,应用启动时最先执行layout.aly UI 布局文件main.lua 主程序入口script.lua 脚本入口.alp 项目压缩文件,用于导出和导入工程在 App 中创建 Demo 工程即可快速体验。例如创建一个按钮并响应点击:
import("android.widget.*") layout = { LinearLayout, orientation = "vertical", { Button, text = "点击", id = "btn" }, } activity.setContentView(loadlayout(layout)) btn.onClick = function(v) print("clicked") end
主要功能区:
import() 是核心机制:通配符 .* 导入整个包(懒加载),类名导入单个类,内部类用 $ 分隔。返回值可赋值给变量,也支持加载 Lua 模块。
import("android.widget.*") -- 导入整个包 import("android.widget.Button") -- 导入单个类 import("android.view.View$OnClickListener") -- 内部类 local Btn = import("android.widget.Button") -- 赋值给变量
loadlayout(t [, root]) 解析布局表生成视图树。id 值自动注入到 root 表(默认 _G),可直接作为全局变量访问。
layout = {
LinearLayout,
orientation = "vertical",
{
TextView,
id = "tv",
text = "Hello",
textSize = "18sp",
},
}
activity.setContentView(loadlayout(layout))
print(tv.getText()) -- id 自动注入,无需声明定义以下全局函数,App 在对应生命周期阶段自动调用:
function onCreate() -- 应用创建 print("onCreate") end function onStart() -- 应用可见 print("onStart") end function onResume() -- 应用进入前台 print("onResume") end function onPause() -- 应用进入后台 print("onPause") end function onStop() -- 应用不可见 print("onStop") end function onDestroy() -- 应用销毁 print("onDestroy") end
控件事件通过 Lua 函数赋值绑定,支持 getter/setter 简写。
btn.onClick = function(v) print(v) end btn.onLongClick = function(v) return true -- 返回 true 表示已处理 end
getter/setter 简写:btn.text = "hello" 等价 btn.setText("hello")
需要 root 权限才能使用
ScriptApi 是内置自动化模块,封装了触控、图色、按键、输入法等底层操作。基于 root 实现全局模拟,无需依赖无障碍服务。与 AutoLua 基础的无障碍服务互补。
通过 require("ScriptApi") 引入,也可调用 Install2Global() 注入全局命名空间。
切换到 AutoLua 输入法后输入文字。首次调用自动设置默认输入法。
InputText("hello")恢复系统默认输入法。
启动指定应用。activity 省略时自动解析启动 Activity。
RunApp("com.android.settings")强制停止指定应用。
查找应用安装和运行状态。
| 返回值 | 说明 |
|---|---|
| -1 | 未安装 |
| 0 | 已安装未运行 |
| 1 | 已安装运行中 |
| 2 | 运行状态未知 |
枚举匹配包名,空格分隔。支持模糊匹配,空串枚举全部已安装应用。
local pkgs = EnumApp("com.tencent")设置开发基准分辨率,之后所有坐标自动按屏幕比例换算。
SetScreenScale(1080, 1920)
关闭屏幕缩放,恢复实际坐标。
保持截屏状态,后续截图复用系统缓存。与 ReleaseCapture() 配对使用,避免频繁截图。
释放截屏保持。
截取全屏并保存到文件。
SnapShot("/sdcard/screen.png")截取矩形区域保存。坐标传 0 表示屏幕边界,deg 为顺时针旋转次数(0-3)。
Capture(0, 0, 500, 300, "/sdcard/crop.png")
获取指定坐标像素颜色。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| x | number | ✓ | 横坐标 |
| y | number | ✓ | 纵坐标 |
| type | number | ✗ | 0=十六进制(默认) 1=十进制 |
local hex = GetColor(100, 200)
统计区域内匹配指定颜色的像素数量。坐标传 0 表示边界。
单点比色,判断指定坐标颜色是否匹配。相似度 0-1(1 为完全匹配)。
true 匹配,false 不匹配CmpColor(100, 200, "0xFF0000", 0.9)
多点比色,一次检查多个坐标的颜色。格式:"x|y|color,..."。
true 全部匹配,false 任一点不匹配CmpColorEx("100|200|0xFF0000,300|400|0x00FF00", 0.9)
区域内找色。坐标传 0 表示边界,dir=0 从左到右从上到下。
| 返回值 | 说明 |
|---|---|
| ret | ≥0 找到,<0 未找到 |
| x, y | 匹配点坐标 |
local ret, x, y = FindColor(0, 0, 0, 0, "0xFF0000", 0, 0.9) if ret >= 0 then Tap(x, y) end
多点找色,先定位主颜色再逐一校验偏移点。坐标传 0 表示边界。
| 参数 | 类型 | 说明 |
|---|---|---|
| x1,y1,x2,y2 | number | 搜索区域(0=边界) |
| main | string | 主颜色 |
| offsets | string | 偏移串 offX|offY|color |
| dir | number | 查找方向(0/1/2) |
| sim | number | 相似度 0-1 |
FindMultiColor(0, 0, 0, 0, "0xFF0000", "10|0|0x00FF00,-10|0|0x0000FF", 0, 0.9)
按键按下 / 弹起。
完整按键(按下+弹起)。
KeyPress("BACK") KeyPress("HOME")
点击指定坐标。
Tap(500, 300)
从起点滑动到终点,ms 默认 -1(自动速度)。
Swipe(100, 500, 900, 500, 500)
按住指定坐标,ms 默认 -1(一直按住)。
Touch(500, 300, 2000)
多点触控。id 默认 0,用于区分不同手指。
TouchDown(300, 400, 0) TouchMove(600, 400, 0, 200) TouchUp(0)
延时等待(毫秒)。休眠期间线程处于 Java 态,避免 ANR。
Delay(1000)
判断屏幕方向。
true,竖屏返回 false移动脚本悬浮窗到指定坐标。
将所有 ScriptApi 函数注入全局命名空间,之后无需 Script. 前缀。
local Script = require("ScriptApi") Script.Install2Global() Tap(500, 300) -- 直接调用
核心模块,已自动加载,无需手动 require
提供异步任务、定时器、布局构建、字符串处理、文件读写、调试输出等常用功能。所有函数自动注入全局命名空间,脚本中直接调用即可。
在线程池执行耗时任务,完成后在主线程回调结果。支持传参(仅限布尔/数值/字符串/Java 对象)。首参为数值时作为延时毫秒。
Task(function(a, b) return a + b end, 1, 2, print) -- print 收到结果 3 Task(1000, function() print("延时 1 秒后执行") end)
创建独立 Lua 线程,拥有独立的全局环境。不能直接访问外部变量,通过 call(t, fn) / set(t, k, v) 与主线程交互。
t = Thread("myscript", arg1, arg2) call(t, "doWork", data) set(t, "config", { timeout = 30 })
周期性定时器。delay 首次延时,period 周期间隔(毫秒)。设置 t.enabled = false 暂停,t.stop() 停止。若 f 有 run() 方法则重复调用 run。
t = Timer(function() print("每秒执行一次") end, 0, 1000) -- t.enabled = false -- 暂停 -- t.stop() -- 停止
解析布局表生成视图树。id 注入 root(默认 _G),支持 .aly 布局文件。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| t | table/string | ✓ | 布局表或 .aly 文件名 |
| root | table | ✗ | id→view 映射表,默认 _G |
layout = { LinearLayout, { TextView, id = "tv", text = "Hi" } }
activity.setContentView(loadlayout(layout))
print(tv.getText())悬浮窗只控制这种方式启动的脚本 启动新脚本。arg 为字符串参数;若 arg 指向存在的文件路径,自动读取为 JSON 配置。
StartScript("test") StartScript("test", "hello") StartScript("test", "/sdcard/config.json") -- 自动识别为 JSON
停止当前正在运行的脚本。
输出到 Logcat,tag 为 "lua"。参数自动空格拼接。 adb logcat -s lua
log("x=", x, "y=", y)将 Lua 对象序列化为可读字符串,支持嵌套表和循环引用检测。
print(DumpObj({ a = 1, b = { 2, 3 } }))
打印当前 Lua 调用堆栈到 Logcat,用于排查调用路径。
按分隔符拆分字符串,返回数组。
local parts = Split("a,b,c", ",") -- {"a", "b", "c"}
去除首尾空白字符。
Trim(" hello ") -- "hello"
四舍五入取整。
Round(3.6) -- 4
深拷贝表,n 为最大递归深度(默认 3)。处理循环引用。
判断文件是否存在,返回 boolean。
读取文件全部内容,失败返回 nil。
写入字符串到文件,覆盖已有内容。
弹出 Android Toast 提示。
ShowToast("操作完成")参数拼接输出到 Logcat,日志中增加了当前文件名和行号。adb logcat -s lua
TracePrint("x=", x, "y=", y)导入 Java 类/包或 Lua 模块。通配符懒加载,类名自动取最后一段作为变量名。详见 AutoLua 基础 → 导入包/类/模块。
import("android.widget.*") import("android.widget.Button")
通过 local AS = require("AccessibilityApi") 引入的无障碍函数模块,提供节点查找、手势操作、全局按键等能力。需要开启无障碍服务才能使用。
检查无障碍服务是否已连接。
if AS.IsConnected() then AS.Click(500, 300) end
坐标点击。
AS.Click(500, 300)
坐标长按。
AS.LongClick(500, 300)
按住指定坐标,delay 毫秒后松开。
AS.Press(500, 300, 2000)
从起点滑动到终点。
AS.Swipe(100, 500, 900, 500, 500)
沿 Path 路径手势滑动。
查找节点是否存在,返回 boolean。
local ok = AS.FindNode("确定")按文本查找并点击。name 为字符串。
AS.FindAndClick("确定")按文本查找输入框并设置文本。
AS.FindAndSetText("搜索", "关键词")全局返回键。
全局 Home 键。
全局最近任务键。
打开通知栏。
将所有无障碍服务函数注入全局命名空间,之后无需 AS. 前缀。
local AS = require("AccessibilityApi") AS.Install2Global() Click(500, 300) -- 直接调用