Longarm 批处理任务
批处理任务可以保存可复用的多步骤工作流,并在之后从应用、REST API 或 MCP 运行。
关键行为
- 同一时间只能有一个批处理运行
- 运行请求会立即返回
runId - 通过状态和历史记录检查进度
screenshot步骤捕获的截图会保存到批处理历史- 默认保留
30次运行记录
录制任务
在 Batch 标签页停止录制会创建一个普通的批处理任务,其中包含已分类的 tap、long-press、swipe 和 delay 步骤。录制任务并不是特殊的不可变来源 —— 可以像手动创建的任务一样,通过相同的应用、REST 和 MCP 操作进行编辑、 复制、删除、运行或更新。
如果在开始录制时的设置中启用了 UI 检查,每个录制的手势前面都会附带一个
ui_context 注解,描述该手势执行前的 UI 状态。它在应用中以只读 JSON
形式展示,并保存在已保存的任务、JSON 导出/导入以及 REST/MCP 任务数据中。
执行器在运行时会跳过整个注解 —— 它不计入执行步骤数,也不产生步骤日志,
原始的坐标手势保持不变。AI 编辑器可以利用注解中的节点文本、viewId、
class、边界、状态和可执行操作,把录制的手势细化为语义化目标。
如果录制时未启用 UI 检查,录制只会保存手势,不带注解。包含旧版录制元数据 的历史任务会作为普通批处理任务加载;过时的元数据会在任务下次保存时被 丢弃。
任务 JSON 结构
顶层任务:
{
"id": "bt_...",
"name": "Open Settings and capture",
"steps": [],
"repeat": 1,
"variables": {},
"createdAt": "2026-07-13T00:00:00.000Z",
"updatedAt": "2026-07-13T00:00:00.000Z"
}
对于 POST /api/batch 和 batch_save,需要提供 name、steps,以及可选
的 repeat 和 variables。服务器可以自动分配 id 和时间戳。
步骤 JSON 结构
{
"id": "step_1",
"type": "tap",
"params": { "x": 540, "y": 1200, "duration": 80 },
"repeat": 1,
"delayAfterMs": 0,
"continueOnError": false,
"children": []
}
children 保存嵌套步骤,供 loop 使用。
支持的步骤类型
免费:
taplong_pressscreenshotopen_appopen_intentapp_function_queryapp_function_calloverlay_showoverlay_hidedelaysetui_actionset_textui_scrollwait_for_uiloop
Plus:
swipepinchtwo_finger_swiperotate
常见示例
Tap
{
"type": "tap",
"params": { "x": 540, "y": 1200, "duration": 80 }
}
基于目标的 tap:
{
"type": "tap",
"params": {
"target": { "text": "Sign in", "role": "button" },
"mode": "semantic_then_gesture"
}
}
Swipe(Plus)
{
"type": "swipe",
"params": {
"startX": 540,
"startY": 1800,
"endX": 540,
"endY": 600,
"duration": 700
}
}
Screenshot
{
"type": "screenshot",
"params": {
"gridSize": 1,
"gridUnit": "cm",
"scale": true
}
}
Open app
{
"type": "open_app",
"params": {
"packageName": "com.android.settings"
}
}
Delay
{
"type": "delay",
"params": { "ms": 1500 }
}
查询并调用 AppFunction
app_function_query 可以把完整的发现结果保存到批处理变量中,
app_function_call 之后可以引用它,并可选择保存解码后的返回值:
{
"steps": [
{
"type": "app_function_query",
"params": {
"packageName": "com.example.notes",
"maxResults": 20,
"resultVariable": "availableFunctions"
}
},
{
"type": "app_function_call",
"params": {
"packageName": "com.example.notes",
"functionId": "{{availableFunctions.functions.0.functionId}}",
"arguments": { "title": "Groceries" },
"resultVariable": "createdNote"
}
}
]
}
这些步骤不需要无障碍服务,但仍需要 Android AppFunctions 支持,以及 Android
对 longarm 和目标函数的授权。
UI action
{
"type": "ui_action",
"params": {
"selector": { "text": "Continue" },
"action": "click",
"fallback": "none"
}
}
Wait for UI
{
"type": "wait_for_ui",
"params": {
"selector": { "text": "Welcome" },
"condition": "exists",
"timeoutMs": 5000,
"stableForMs": 0
}
}
变量
在字符串参数中使用 {{name}} 替换:
{
"variables": {
"packageName": "com.android.settings"
},
"steps": [
{
"type": "open_app",
"params": { "packageName": "{{packageName}}" }
}
]
}
如果一个参数的完整值就是单个 {{name}} 占位符,会保留该变量原本的 JSON
类型(数字、布尔值、对象),而不是转换为字符串。同时支持嵌套查找,例如
{{user.name}}。
循环
loop 步骤会执行其 children,支持四种模式:
固定次数:
{
"type": "loop",
"params": { "count": 3 },
"children": [
{ "type": "tap", "params": { "x": 540, "y": 1800 } }
]
}
数值范围:
{
"type": "loop",
"params": { "var": "i", "from": 1, "to": 5, "step": 1 },
"children": [
{ "type": "delay", "params": { "ms": 250 } }
]
}
遍历列表:
{
"type": "loop",
"params": {
"var": "pkg",
"in": ["com.android.settings", "com.android.chrome"]
},
"children": [
{ "type": "open_app", "params": { "packageName": "{{pkg}}" } }
]
}
类 while 循环:
{
"type": "loop",
"params": { "whileVar": "keepGoing", "max": 10 },
"children": [
{ "type": "delay", "params": { "ms": 500 } }
]
}
说明:循环嵌套深度有限制,step: 0 的循环无效,whileVar 循环必须提供
max。
完整示例
{
"name": "Open Google News and scroll",
"variables": {
"packageName": "com.google.android.apps.magazines"
},
"steps": [
{
"type": "open_app",
"params": { "packageName": "{{packageName}}" },
"delayAfterMs": 2500
},
{
"type": "swipe",
"params": {
"startX": 540,
"startY": 1900,
"endX": 540,
"endY": 650,
"duration": 700
}
},
{
"type": "screenshot",
"params": { "gridSize": 1, "gridUnit": "cm", "scale": true }
}
]
}
REST 操作
保存和列出任务:
GET /api/batchPOST /api/batchGET /api/batch/<id>PUT /api/batch/<id>DELETE /api/batch/<id>
任务校验要求提供 name 以及非空的 steps 数组。
运行任务 —— 已保存的任务使用 POST /api/batch/<id>/run,未保存的内联任务
使用 POST /api/batch/run。两者都接受可选的布尔参数
keepScreenOn(JSON 请求体或 ?keepScreenOn=true 查询参数)。为 true
时,longarm 会在整个运行期间保持屏幕常亮,并在运行结束、失败或被停止后
立即释放 —— 适用于原本会触发设备息屏超时的长时间运行。按电源键仍会关闭
屏幕。这与应用中任务 ⋯ 菜单里的 Screen on 选项一致;对于通过 API
触发的运行,默认值为 false。
{ "runId": "run_123", "status": "processing" }
如果已有其他运行处于活动状态,服务器会返回 HTTP 409 Conflict,内容为
{ "error": "Another batch task is already running" }。
运行器状态 —— GET /api/batch/status:
{
"state": "running",
"currentTaskId": "bt_123",
"currentRunId": "run_123",
"currentStepIndex": 2,
"totalSteps": 5
}
state 取值为 idle、running、stopping 之一。
批处理历史
使用 GET /api/batch/history 列出历史记录,或使用
GET /api/batch/history/<runId> 获取单次运行:
{
"runId": "run_123",
"taskId": "bt_123",
"taskName": "Open Google News and scroll",
"status": "finished",
"startedAt": "2026-07-13T00:00:00.000Z",
"endedAt": "2026-07-13T00:00:05.000Z",
"totalSteps": 3,
"executedSteps": 3,
"message": "Completed",
"screenshots": [
{
"id": "shot_1",
"stepId": "step_3",
"stepIndex": 3,
"capturedAt": "2026-07-13T00:00:04.000Z"
}
]
}
运行状态取值:processing、finished、failed、aborted。
删除历史记录:DELETE /api/batch/history/<runId>(单次运行)或
DELETE /api/batch/history(全部运行)。
截图导出需要 Plus:
GET /api/batch/history/<runId>/screenshots/<screenshotId>—— 单张截图GET /api/batch/history/<runId>/export—— 所有截图打包为 zip
对应的 MCP 工具
相同的批处理能力也可以通过 MCP 工具使用:batch_list、batch_get、
batch_save、batch_delete、batch_run、batch_run_inline、
batch_status、batch_history_list、batch_history_get、
batch_history_export、batch_history_delete。