回答
文档地址 https://docs.hamibot.com/
要获取屏幕上的控件信息,你可以通过以下步骤:
1. 定位控件
使用选择器方法(如 text、id、className 等)找到目标控件:
// 通过文本查找
var widget = text('设置').findOne();
// 通过ID查找
var widget = id('action_log').findOne();
// 通过类名查找
var widget = className('android.widget.Button').findOne();
// 带超时时间的查找(6秒内找不到返回null)
var widget = text('确定').findOne(6000);
2. 获取控件信息
找到控件后,可以调用以下方法获取其属性:
// 获取控件类名
log('类名: ' + widget.className());
// 获取控件文本
log('文本: ' + widget.text());
// 获取控件ID
log('ID: ' + widget.id());
// 获取控件在屏幕上的坐标范围
var bounds = widget.bounds();
log('坐标范围: ' + bounds.toString());
log('中心点坐标: (' + bounds.centerX() + ', ' + bounds.centerY() + ')');
// 获取控件在父控件中的范围
log('父控件内范围: ' + widget.boundsInParent().toString());
// 获取父控件
var parent = widget.parent();
if (parent) {
log('父控件类名: ' + parent.className());
}
// 获取绘制顺序(Android 7.0+)
log('绘制顺序: ' + widget.drawingOrder());
3. 实用示例
以下是一个完整示例,查找"设置"按钮并显示其信息:
// 等待"设置"文本出现
var settingButton = text('设置').findOne(5000);
if (settingButton) {
log('=== 控件信息 ===');
log('类名: ' + settingButton.className());
log('文本: ' + settingButton.text());
log('ID: ' + settingButton.id());
var b = settingButton.bounds();
log('屏幕坐标: ' + b.toString());
log('中心点: (' + b.centerX() + ', ' + b.centerY() + ')');
// 点击该控件
settingButton.click();
// 或者通过坐标点击
// click(b.centerX(), b.centerY());
} else {
log('未找到"设置"按钮');
}
注意事项
findOne()会一直等待直到找到控件,可能导致脚本阻塞- 如需只搜索一次,可以使用
findOnce()方法 - 如果屏幕上有多个匹配控件,
findOne()会返回深度优先搜索找到的第一个 - 使用
exists()可以先检查控件是否存在:if (text('确认').exists()) { ... }
这些方法可以帮助你获取屏幕上任意控件的详细信息,用于后续的自动化操作。
补充回答 1
使用子线程监控主线程执行时间
你可以使用Hamibot的threads模块创建一个监控子线程,当主线程方法执行超过一分钟时停止执行。以下是实现方案:
// 文档地址 https://docs.hamibot.com/
// 创建原子变量用于线程间通信
var shouldStop = threads.atomic(0);
// 启动监控线程(60秒后设置停止标志)
var monitorThread = threads.start(function() {
sleep(60000); // 等待60秒
shouldStop.set(1);
log("执行已超过60秒,设置停止标志");
});
// 要监控的主线程方法
function monitoredFunction() {
log("开始执行长时间任务...");
// 任务代码(必须定期检查停止标志)
for (var i = 0; i < 1000000000; i++) {
// 关键:必须定期检查是否应该停止
if (shouldStop.get() === 1) {
log("收到停止信号,提前结束任务");
return;
}
// 防止检查过于频繁,适当sleep
if (i % 10000000 === 0) {
sleep(1);
}
}
log("任务正常完成");
}
// 执行被监控的方法
monitoredFunction();
// 清理监控线程
if (monitorThread.isAlive()) {
monitorThread.interrupt();
}
重要说明
-
必须定期检查停止标志:在长时间运行的任务代码中,你需要定期检查
shouldStop.get()的值。如果任务是一个不能修改的黑盒函数,此方法不适用。 -
为什么需要sleep:在循环中加入
sleep(1)是为了防止检查过于频繁,同时也给JavaScript引擎机会处理其他操作。 -
原子变量的重要性:使用
threads.atomic()确保线程间通信安全,避免竞态条件。 -
无法强制中断主线程:JavaScript没有直接中断正在执行函数的机制,只能通过在代码中定期检查标志位来实现"软停止"。
-
监控线程清理:无论任务是否超时,都需要清理监控线程,避免资源浪费。
如果被监控的函数无法修改(例如是第三方库函数),建议将其放入子线程执行,然后在主线程中监控该子线程的执行时间。
ℹ️ 本回答由 AI 生成,内容仅供参考