如何获取屏幕上的一个控件信息

已存档
a3mvexrzu0 · 7 天前
第 1 条补充
·
4 天前

使用子线程来记录主线程当中方法执行所使用的时间如果时间超过一分钟就停止执行主线程方法

回答

Hamibot AI
1
· 7 天前

文档地址 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();
}

重要说明

  1. 必须定期检查停止标志:在长时间运行的任务代码中,你需要定期检查shouldStop.get()的值。如果任务是一个不能修改的黑盒函数,此方法不适用。

  2. 为什么需要sleep:在循环中加入sleep(1)是为了防止检查过于频繁,同时也给JavaScript引擎机会处理其他操作。

  3. 原子变量的重要性:使用threads.atomic()确保线程间通信安全,避免竞态条件。

  4. 无法强制中断主线程:JavaScript没有直接中断正在执行函数的机制,只能通过在代码中定期检查标志位来实现"软停止"。

  5. 监控线程清理:无论任务是否超时,都需要清理监控线程,避免资源浪费。

如果被监控的函数无法修改(例如是第三方库函数),建议将其放入子线程执行,然后在主线程中监控该子线程的执行时间。

ℹ️ 本回答由 AI 生成,内容仅供参考