一、整体架构与使用场景
使用 Hamibot 1.6.7,采用「守护脚本 + 业务脚本」分离架构:
守护脚本:wla_daemon.js,通过轮询读取 /sdcard/Download/wla_command.json 指令文件,接收外部 APP 下发任务;
业务脚本:douyin_follow.js(抖音自动化脚本,含启动 APP、点击等无障碍操作);
调用方式:守护脚本通过 engines.execScriptFile(绝对路径) 拉起抖音业务脚本;
通讯规则:指令字段为 scriptName,脚本统一后缀 .js,全程使用绝对路径加载文件。
二、当前现象
外部 APP 可正常生成指令文件,守护脚本能正常读取、解析指令,日志完整输出,无报错;
守护脚本执行 engines.execScriptFile(完整绝对路径/douyin_follow.js),代码执行无异常、无文件找不到报错;
核心异常:被调用的 douyin_follow.js 完全不运行,无任何日志输出,抖音 APP 不会被唤起;
对比测试:在 Hamibot 前台手动直接运行 douyin_follow.js,脚本全程正常执行,无障碍、点击、启动 APP 等功能全部生效。
三、已完成排查(排除外部环境问题)
权限排查:已开启 Hamibot 无障碍、悬浮窗、后台弹出界面、自启动;手机加入省电白名单、关闭后台应用限制、关闭系统神隐模式,确认MIUI 系统 / 手机后台无拦截;
路径排查:已使用标准绝对路径 /storage/emulated/0/Hamibot/ 拼接脚本名,确认文件路径、文件名完全正确;
代码逻辑排查:守护脚本增加任务锁、指令文件删除、异常捕获、日志打印,代码逻辑无死锁、无语法错误;
文件格式排查:脚本文件为 UTF-8 无 BOM 格式,换行符正常,无格式异常;
重启测试:多次重启手机、重启 Hamibot、重新配置权限,问题依旧。
四、核心疑问
为何前台手动执行业务脚本正常,但守护脚本内部通过 engines.execScriptFile 调用同一份脚本,脚本就完全不执行、无日志、无报错?
是否为 Hamibot 守护运行环境与前台运行环境存在差异?守护线程调用脚本时,是否缺失无障碍 / 界面运行上下文?
当前版本(1.6.7)的 engines.execScriptFile 在守护模式下,是否存在已知的执行兼容问题?
抖音业务脚本的绝对路径是否正确?
抖音业务脚本是否有执行权限?
是否存在其他可能影响抖音业务脚本运行的因素?
回答
针对你描述的架构与现象,核心问题出在 Hamibot 子引擎执行上下文差异、无障碍服务未显式初始化、以及 Android 后台运行机制 上。以下逐条解答你的核心疑问,并提供可直接落地的解决方案。
一、核心疑问解答
1. 为何前台手动执行正常,engines.execScriptFile 调用却静默失败?
前台通过 Hamibot UI 运行脚本时,主服务会自动完成无障碍服务绑定、控制台初始化和运行上下文注入。而 engines.execScriptFile() 会创建一个全新的独立脚本引擎,该引擎默认不继承父脚本的无障碍状态。如果 douyin_follow.js 开头没有显式调用 auto.waitFor() 或 auto(),无障碍 API 会直接失效,脚本因未捕获异常瞬间退出,导致无日志、无操作。
2. 守护环境与前台环境是否存在差异?是否缺失无障碍/界面上下文?
存在显著差异。守护脚本运行在后台服务线程,子引擎同样继承后台属性。子引擎启动时,必须重新声明无障碍依赖。Android 系统对后台进程的 UI 交互和无障碍事件分发有严格限制,若未正确初始化或屏幕处于休眠/锁屏状态,无障碍服务会拒绝执行指令。
3. 当前版本(1.6.7)的 engines.execScriptFile 是否存在已知兼容问题?
API 本身无致命缺陷,但需注意两点机制:
- 异步与静默崩溃:该方法异步执行,返回
Execution对象。若子脚本在解析阶段或初始化阶段崩溃,父脚本不会直接抛出异常,日志可能来不及输出。 - 路径沙箱限制:Hamibot 对非 Hamibot 管理目录的动态执行存在安全校验。使用
/storage/emulated/0/Hamibot/拼接的绝对路径在部分机型上会被子引擎静默拦截。
4. 抖音业务脚本的绝对路径是否正确?是否有执行权限?
路径格式正确,但 Android 11+ 分区存储机制可能导致子引擎读取该路径时权限降级。建议使用 files.path() 进行路径标准化转换,并确保脚本文件存放在 Hamibot 可完全读写的目录内。
5. 是否存在其他影响因素?
- Rhino 引擎兼容性:Hamibot 使用 Rhino 1.7.15,不支持箭头函数、默认参数、部分 ES6+ 语法。若业务脚本包含这些语法,动态加载时会直接解析失败且可能不输出错误日志。
- Android 后台启动限制:Android 10+ 严格限制后台
launchApp()。必须确保屏幕亮起且处于可交互状态,否则系统会直接丢弃启动意图。
二、解决方案与最佳实践
按以下步骤改造,可彻底解决子脚本不执行、无日志的问题。
1. 业务脚本强制初始化无障碍与全局异常捕获
在 douyin_follow.js 最顶部添加以下代码。子引擎必须独立申请无障碍上下文,且全局 try...catch 能捕获解析后运行时的所有异常并打印日志。
// 文档地址 https://docs.hamibot.com/
auto.waitFor();
console.log('douyin_follow.js 引擎已启动');
try {
// 原有业务逻辑放在此处
launchApp('抖音');
sleep(2000);
// 其他无障碍操作...
} catch (e) {
console.error('douyin_follow.js 运行异常: ' + e);
}
2. 守护脚本调用逻辑优化
使用 files.path() 标准化路径,增加引擎启动状态判断,并在调用前确保设备处于可交互状态。
// 文档地址 https://docs.hamibot.com/
var scriptPath = files.path('/storage/emulated/0/Hamibot/douyin_follow.js');
// 确保屏幕亮起且可交互,规避 Android 后台启动限制
if (!device.isScreenOn()) {
device.wakeUp();
sleep(800);
swipe(500, 1500, 500, 800, 300);
sleep(500);
}
var exec = engines.execScriptFile(scriptPath);
if (exec) {
console.log('子引擎拉起成功, EngineID: ' + exec.getEngine().id);
} else {
console.error('子引擎拉起失败,请检查文件路径或脚本语法');
}
3. 严格排查 Rhino 1.7.15 兼容性
检查 douyin_follow.js 全文,确保未使用以下语法:
- 箭头函数:
var fn = () => {}→ 改为var fn = function() {} - 默认参数:
function test(a, b = 1)→ 改为function test(a, b) { b = b || 1; } - 模板字符串:
`text ${var}`→ 改为'text ' + var let/const在复杂循环或闭包中的非常规用法 → 统一使用var
Rhino 解析失败时会直接终止引擎,且不会向父脚本传递错误,这是“无日志”的常见原因。
4. 调试与验证步骤
- 最小化测试:将
douyin_follow.js内容临时替换为仅包含auto.waitFor(); console.log('test ok');的代码。若守护脚本能成功调用并输出日志,说明原业务脚本存在语法兼容或无障碍调用阻塞问题。 - 日志过滤检查:打开 Hamibot 控制台,点击右上角设置,确保“日志级别”为
Verbose或Debug,且未勾选“仅显示当前脚本日志”。子引擎日志默认会合并输出到主控制台。 - 路径验证:在守护脚本中执行
console.log(files.exists(scriptPath));,确认返回true。若为false,说明路径拼接或存储权限存在问题。
按照上述架构调整与代码规范改造后,子脚本即可在守护模式下稳定拉起并执行无障碍操作。如改造后仍出现静默退出,可提供 douyin_follow.js 前 30 行代码,我将进一步定位解析或上下文阻塞点。