auto.waitFor();
threads.start(function(){
// 悬浮窗权限
requestFloaty();
});
// =全局变量(悬浮窗可改)
var clickX = 540;
var clickY = 1600;
var isRun = false; //启停开关
// =====================================
// 延时参数 可自己改
const t_clickWait = 1200;
const t_payWait = 1500;
const t_backWait = 1000;
// --------创建悬浮窗布局--------
let w = floaty.rawWindow(
<frame bg="#CC000000" w="280" h="180">
<vertical padding="10">
<text text="支付脚本控制台" textSize="16" color="#ffffff" gravity="center"/>
<button id="btnStart" text="开始运行" marginTop="8"/>
<button id="btnPause" text="暂停脚本" marginTop="5"/>
<button id="btnSetXY" text="修改第一步点击坐标" marginTop="5"/>
</vertical>
</frame>
);
//悬浮窗可拖动
w.setPosition(100, 300);
w.exitOnClose();
// --------按钮绑定事件--------
//开始
w.btnStart.click(()=>{
isRun = true;
toast("✅脚本已启动");
});
//暂停
w.btnPause.click(()=>{
isRun = false;
toast("⏸脚本已暂停");
});
//弹窗改XY坐标
w.btnSetXY.click(()=>{
let x = dialogs.input("输入新X坐标", String(clickX));
if(x === null) return;
let y = dialogs.input("输入新Y坐标", String(clickY));
if(y === null) return;
clickX = parseInt(x) || clickX;
clickY = parseInt(y) || clickY;
toast("✅坐标已更新:"+clickX+" , "+clickY);
});
// --------主循环逻辑--------
function mainLoop(){
while(true){
//暂停就卡住
while(!isRun){
sleep(300);
}
console.log("————本轮开始,点击坐标:",clickX,clickY);
click(clickX, clickY);
sleep(t_clickWait);
//识别立即支付
if(text("立即支付").waitFor(2000)){
toast("💰识别到立即支付,自动点击");
text("立即支付").click();
sleep(t_payWait);
}else{
toast("❌未找到,返回上一页");
back();
sleep(t_backWait);
}
sleep(800);
}
}
//启动任务线程
threads.start(mainLoop);我这个脚本有什么问题
回答
脚本存在语法兼容性、API 使用错误及稳定性风险,会导致脚本无法运行或崩溃。主要问题如下:
-
语法兼容性错误
Hamibot 脚本引擎基于 Rhino 1.7.15,不支持 ES6 箭头函数()=>。代码中多处使用箭头函数(如w.btnStart.click(()=>{...})),这会直接导致语法错误,脚本无法启动。必须使用传统function()写法。 -
API 函数不存在
requestFloaty()不是 Hamibot 标准 API 函数。悬浮窗权限需要在手机系统设置中手动授予,或通过代码检查权限状态。调用不存在的函数会抛出ReferenceError。 -
悬浮窗生命周期问题
虽然使用了threads.start保持脚本运行,但为了确保悬浮窗不被系统意外回收,建议按照最佳实践添加空setInterval保活。 -
线程变量可见性风险
isRun变量在主线程和子线程间共享。在 Rhino 引擎中,普通变量在线程间可能存在可见性问题。建议增加日志或使用更明确的控制逻辑。 -
权限检查缺失
脚本未检查悬浮窗权限是否已授予。如果未授权,floaty.rawWindow创建时会崩溃。
以下是修复后的代码及优化建议:
// 文档地址 https://docs.hamibot.com/
auto.waitFor();
// =========全局变量=========
var clickX = 540;
var clickY = 1600;
var isRun = false;
// =========================
// 延时参数
const t_clickWait = 1200;
const t_payWait = 1500;
const t_backWait = 1000;
// 检查悬浮窗权限
if (!android.provider.Settings.canDrawOverlays(context)) {
toastLog("未获得悬浮窗权限,请在设置中开启");
// app.startActivity({ action: "android.settings.action_MANAGE_OVERLAY_PERMISSION" }); // 可选:尝试跳转设置
stop();
}
// --------创建悬浮窗布局--------
let w = floaty.rawWindow(
<frame bg="#CC000000" w="280" h="180">
<vertical padding="10">
<text text="支付脚本控制台" textSize="16" color="#ffffff" gravity="center"/>
<button id="btnStart" text="开始运行" marginTop="8"/>
<button id="btnPause" text="暂停脚本" marginTop="5"/>
<button id="btnSetXY" text="修改第一步点击坐标" marginTop="5"/>
</vertical>
</frame>
);
w.setPosition(100, 300);
w.exitOnClose();
// --------按钮绑定事件 (使用 function 替代箭头函数)--------
w.btnStart.click(function () {
isRun = true;
toast("✅脚本已启动");
});
w.btnPause.click(function () {
isRun = false;
toast("⏸脚本已暂停");
});
w.btnSetXY.click(function () {
let x = dialogs.input("输入新 X 坐标", String(clickX));
if (x === null) return;
let y = dialogs.input("输入新 Y 坐标", String(clickY));
if (y === null) return;
clickX = parseInt(x) || clickX;
clickY = parseInt(y) || clickY;
toast("✅坐标已更新:" + clickX + " , " + clickY);
});
// --------主循环逻辑--------
function mainLoop() {
while (true) {
// 暂停等待
while (!isRun) {
sleep(300);
}
console.log("————本轮开始,点击坐标:", clickX, clickY);
click(clickX, clickY);
sleep(t_clickWait);
// 识别立即支付
if (text("立即支付").waitFor(2000)) {
toast("💰识别到立即支付,自动点击");
text("立即支付").click();
sleep(t_payWait);
} else {
toast("❌未找到,返回上一页");
back();
sleep(t_backWait);
}
sleep(800);
}
}
// 启动任务线程
threads.start(mainLoop);
// 保持悬浮窗不被关闭 (保活)
setInterval(function () {}, 1000);
优化建议:
- 权限管理:确保在手机设置中授予 Hamibot「悬浮窗权限」和「无障碍服务」。
- 线程安全:脚本停止时,建议调用
threads.shutDownAll()清理残留线程,避免影响下次运行。 - 元素定位:
text("立即支付")依赖具体文本,如果 APP 版本更新导致文本变化,脚本会失效。建议使用id或desc定位,或通过「布局分析」工具获取更稳定的特征。 - 异常处理:建议在
mainLoop外层包裹try...catch,防止单次错误导致整个脚本崩溃退出。