press 在操作时总是挂起是什么原因,如何解决这个问题
while(true){
if(text('确定').exists()&&!text('确认信息').exists()){
try{var a= text('确定').findOne();press(a.bounds().centerX(),a.bounds().centerY(),1);sleep(10);log("点击确定");}catch(e){log("1-1")}
}else if(text('确认信息').exists()&&!text('是').exists()&&!text('我知道了').exists()&&!text('无误').exists()){
log("w1")
try{var a= text('确认并支付').findOne();press(a.bounds().centerX(),a.bounds().centerY(),1);sleep(10);log("点击确定");}catch(e){log("1-2")}
}else if(text('是').exists()&&!text('我知道了').exists()&&!text('无误').exists()){
log("w2")
try{var a= text('是').findOne();press(a.bounds().centerX(),a.bounds().centerY(),1);sleep(10);log("点击确定");}catch(e){log("1-3")}
}else if(text('我知道了').exists()&&!text('无误').exists()){
log("w3")
try{var a= text('我知道了').findOne();press(a.bounds().centerX(),a.bounds().centerY(),1);sleep(10);log("点击确定");}catch(e){log("1-4")}
}else if (text('无误').exists()) {
log("w4")
try{
log(12)
text('无误').findOne().click()
break;
}catch(e){log(5)}
}
log("1")
sleep(100)
// try {
// // 检查确定按钮
// text('确定').findOne(10).click()
// } catch (e) {
// }
// try {
// // 检查确认信息并支付按钮
// text('确认信息并支付').findOne(10).click()
// } catch (e) {
// }
// try {
// // 检查就是这家按钮
// text('就是这家').findOne(10).click()
// } catch (e) {
// }
// try {
// // 检查自提门店不存在或未营业提示
// text('我知道了').findOne(10).click()
// continue
// } catch (e) {
// }
// try {
// // 检查确认无误按钮
// text('确认无误').findOne(10).click()
// } catch (e) {
// }
// log("1")
} 我在做这么一个循环点击操作,因为click点击动作有延时,想用press加快操作,但是脚本页面在没有人为干扰的情况下,press总是挂起,帮我找找原因
click的点击速度比press快么
回答
press 操作总是挂起可能由以下几个原因造成:
-
操作被中断:如果在执行 press 的过程中,用户自行触摸屏幕或触发了其他与屏幕交互的操作,会导致 press 执行失败并挂起。确保脚本运行时设备没有外部干扰。
-
长时间未完成:如果 press 设置的 duration 时间过长,而系统由于某些限制(如响应延迟)未能及时完成操作,也可能导致挂起。可以尝试减少 duration 值,确保其合理(例如 600ms 左右是常见推荐值)。
-
脚本逻辑问题:因为 press 是同步操作,只有在其完成时才会继续执行后续代码。如果你在 press 后依赖某些状态或操作,但这些内容未能正确满足条件,可能导致脚本看起来像是“挂起”。检查脚本逻辑是否需要异步处理或者添加超时机制。
-
设备性能或兼容性问题:部分设备或 Android 版本可能对自动化操作的支持有限。确保你的设备和 Hamibot 兼容,并且已按照文档要求开启所有必要权限(例如无障碍服务、悬浮窗等)。
-
RootAutomator 或驱动问题:如果你使用 RootAutomator,请确认它已经正确启动并处于就绪状态。
解决方案
- 确保 press 运行期间没有人为干预或外部事件。
- 检查脚本逻辑,确认没有死锁或无限等待的情况。
- 尝试缩短 duration 时间或换用 swipe/gesture 等替代操作。
- 更新 Hamibot 到最新版本,以获得最新的功能和修复。
- 如果问题持续存在,建议发送邮件到 support@hamibot.cn 提供详细信息,以便获取进一步支持。
你可以参考以下示例来测试 press 的基本行为:
// 文档地址 https://docs.hamibot.com/
press(500, 1000, 600); // 在 (500, 1000) 处按住 600 毫秒
toast("Press completed");
如果该测试能正常完成,则说明 press 功能本身没有问题,问题可能出在脚本逻辑或其他环境因素上。
补充回答 1
你的脚本中使用了 press
操作来替代 click
,但发现 press
在执行时经常“挂起”,这通常是由以下几个原因造成的:
1. 坐标获取问题
你在代码中通过 bounds().centerX()
和 bounds().centerY()
获取控件中心点。如果控件不可见(比如被其他控件遮挡)或已经被移除,那么获取的坐标可能是无效的,导致 press
无法正确执行。
建议:
- 确保控件存在且可见。
- 添加日志输出查看坐标值是否合理:
var a = text('确定').findOne(); log(`点击坐标: ${a.bounds().centerX()}, ${a.bounds().centerY()}`);
2. press 是同步操作,可能阻塞主线程
press(x, y, duration)
是一个同步操作,只有在按下完成之后才会继续执行后续代码。如果你设置的 duration
过长(比如 1000ms),或者系统响应较慢,会导致看起来像是“挂起”。
建议:
- 缩短
duration
时间,例如设置为100
毫秒即可模拟一次点击行为。 - 如果需要更快速的操作,可以尝试直接使用
click()
:a.click();
3. RootAutomator 未启用或驱动不兼容
如果你没有使用 RootAutomator 或者 RootAutomator 没有正常运行,某些设备上 press
操作可能会失败或卡住。
建议:
- 确保你已经调用
auto.waitFor()
并启用了 RootAutomator。 - 在脚本开头添加:
auto.waitFor(); if (!RootAutomator.isRunning()) { toast("请确保 RootAutomator 已启动"); exit(); }
4. 线程阻塞或休眠时间不合理
你在每个循环中都加了 sleep(100)
,这个时间相对合理,但如果在关键路径上有过多 sleep
或 findOne()
超时等待,可能导致整体流程变慢甚至卡住。
建议:
- 使用
findOne(timeout)
设置超时时间,避免无限等待:var a = text('确定').findOne(100); // 最多等待 100ms if (a) { press(a.centerX(), a.centerY(), 100); }
- 避免在主线程频繁执行大量查找和操作逻辑,必要时可以拆分到子线程处理。
5. 脚本结构优化建议
你可以将重复逻辑封装成函数,减少冗余代码,并提高可读性:
// 文档地址 https://docs.hamibot.com/
function clickTextIfExist(textToClick, excludeTexts) {
if (text(textToClick).exists()) {
for (let exclude of excludeTexts) {
if (text(exclude).exists()) return;
}
try {
let target = text(textToClick).findOne(100);
target.click(); // 或者使用 press
log(`点击了: ${textToClick}`);
} catch (e) {
log(`点击失败: ${textToClick}`);
}
}
}
while (true) {
if (text('确定').exists() && !text('确认信息').exists()) {
clickTextIfExist('确定', []);
} else if (text('确认信息').exists() && !text('是').exists() && !text('我知道了').exists() && !text('无误').exists()) {
clickTextIfExist('确认并支付', []);
} else if (text('是').exists() && !text('我知道了').exists() && !text('无误').exists()) {
clickTextIfExist('是', []);
} else if (text('我知道了').exists() && !text('无误').exists()) {
clickTextIfExist('我知道了', []);
} else if (text('无误').exists()) {
clickTextIfExist('无误', []);
break;
}
sleep(100);
}
总结
原因 | 解决方案 |
---|---|
控件不可见或已失效 | 添加日志检查控件状态和坐标 |
press 同步操作导致阻塞 |
改用更小的 duration 或使用 click() |
RootAutomator 未启用 | 检查并确保其正常运行 |
查找控件耗时过长 | 使用 ` |
补充回答 2
click()
的点击速度通常比 press(x, y, duration)
快,原因如下:
✅ 1. click()
是异步操作
click()
是控件级别的操作,它由系统直接处理,通常是异步的。- 调用
click()
后脚本会立即继续执行下一行代码,不需要等待点击动画或系统反馈完成。
⚠️ 2. press()
是同步操作
press(x, y, duration)
是基于坐标的模拟点击,它是同步操作。- 脚本必须等待整个
duration
时间结束后才会继续执行下一行代码。 - 即使你设置
duration
为 1ms,仍然会有一定的线程调度和系统响应延迟。
✅ 3. 性能表现
- 在大多数情况下,
click()
更加高效,因为它更贴近 Android 的原生控件事件。 - 如果控件是可点击的(如按钮、文字等),并且你可以通过控件查找 API 找到它,推荐优先使用
click()
。
🧪 示例对比
// 文档地址 https://docs.hamibot.com/
var btn = text('确定').findOne();
// 使用 click(),速度快,异步执行
btn.click();
log("click 已触发");
// 使用 press(),需要等待 100ms 才会继续执行
var x = btn.bounds().centerX();
var y = btn.bounds().centerY();
press(x, y, 100);
log("press 已触发");
✅ 推荐使用场景
方法 | 推荐使用场景 |
---|---|
click() |
控件存在且支持 .click() ,例如按钮、TextView 等 |
press() |
控件不可点击、无法通过控件方式操作时,或需要长按模拟 |
🔧 如果你想提升效率:
- 优先使用
click()
。 - 若必须使用
press()
,可以尝试减小duration
(比如设为50
ms)以减少阻塞时间。 - 如果你在循环中频繁调用
press()
,考虑是否可以通过多线程或 RootAutomator 提升效率。