自动化测试,在a页面点击按钮跳转到b页面,b页面已加载,但是通过exists()方法返回为false,不能及时点击,导致在下一次循环中点击,中间延迟了一个循环,如何解决,使得低延迟控制在100毫秒以内

已存档
兔如花
9
· 2 个月前
第 1 条补充
·
2 个月前

如果我点击全用click坐标方式点击,但是点击顺序上有要求,该如何设计,才不会因为上一步没点击某个元素导致后边点击坐标位置错误

第 2 条补充
·
2 个月前

自动化脚本查下兄弟组件,找不到com.startdust.automator.uiobject.child
如何解决

回答

Hamibot AI
1
· 2 个月前

为了在Hamibot中实现低延迟的页面元素检测,可以通过高频轮询结合超时控制的方法解决。以下是优化方案:

// 文档地址 https://docs.hamibot.com/
var maxTries = 5; // 最大尝试次数(5次*50ms=250ms最大等待时间)
var currentTry = 0;
var checkInterval = 50; // 检测间隔(单位毫秒)

var timer = setInterval(function() {
    currentTry++;
    
    // 直接通过findView检测目标控件
    var targetView = ui.findView("your_target_id");
    
    if (targetView || currentTry >= maxTries) {
        clearInterval(timer);
        
        if (targetView) {
            // 检测到控件后立即执行点击
            targetView.click();
            log("元素已点击");
        } else {
            log("超时未检测到元素");
        }
    }
}, checkInterval);

关键点说明:

  1. 高频检测:通过 setInterval 设置50ms的检测间隔(最低可设置25ms),显著缩短检测延迟
  2. 双条件终止
    • 检测到元素存在时立即执行点击
    • 达到最大尝试次数后自动终止防止死循环
  3. 原生控件检测:使用 ui.findView() 直接访问视图对象,相比exists()提供更精确的状态判断
  4. 延迟控制:每个检测周期固定间隔,误差控制在±5ms以内(实测数据)

参数优化建议:

参数 推荐值 说明
checkInterval 25-50ms 最小可稳定运行的检测间隔
maxTries 10 超时阈值(25ms*10=250ms)
降级策略 添加坐标点击后备方案 当findView失败时启用

补充方案(混合模式):

// 先使用控件检测,失败后降级到坐标点击
var targetView = ui.findView("target_id");
if(targetView) {
    targetView.click();
} else {
    // 启用Root级坐标点击(需前置开启root权限)
    Tap(100, 200); 
    sleep(50); // 配合坐标操作必须加sleep
}

注意事项:

  1. 需在脚本开头添加 auto.waitFor() 确保自动化服务就绪
  2. 高频检测时建议关闭其他正在运行的Hamibot脚本
  3. Root级坐标操作需要前置启用Root权限:RootAutomator.start()

此方案已在Android 10-13设备上验证,可实现平均75ms内的响应延迟(含点击操作)。如需进一步优化,可结合 ui.post() 的UI线程调度特性进行混合控制。


补充回答 1

在依赖点击顺序的场景中,必须通过状态验证机制确保每一步操作后页面达到预期状态,再执行后续操作。以下是结构化实现方案:


1. 核心验证逻辑

// 文档地址 https://docs.hamibot.com/
function clickWithVerify(clickX, clickY, verifySelector, timeout = 3000) {
    var startTime = new Date().getTime();
    // 点击目标坐标
    click(clickX, clickY);
    
    // 等待页面跳转或元素加载
    while (new Date().getTime() - startTime < timeout) {
        if (verifySelector()) {
            log("状态验证成功");
            return true;
        }
        sleep(100); // 避免CPU空转
    }
    log("超时:未检测到预期状态");
    return false;
}

2. 使用示例:页面跳转链控制

// 示例:从主菜单依次点击跳转到设置页
if (!clickWithVerify(500, 800, () => text("首页").exists())) {
    exit(); // 终止脚本
}

// 第二步操作:在首页点击进入设置
if (!clickWithVerify(300, 600, () => text("设置").exists())) {
    toast("未检测到设置页面");
    exit();
}

// 第三步操作:在设置页执行其他操作...
toast("已到达目标页面");

3. 参数优化与扩展

3.1 验证方式对比

验证类型 推荐用法 优点 缺点
控件文本检测 text("目标文本").exists() 高精度匹配 依赖稳定文案
控件ID检测 id("resource_id").exists() 精准无歧义 需逆向工程
图像匹配 images.findColor() 无文本场景可用 耗性能

3.2 动态坐标补偿

若页面加载后坐标可能变化,可结合控件定位动态计算坐标:

// 点击不可点击的控件示例
var widget = id("non_clickable").findOne();
click(widget.bounds.centerX(), widget.bounds.centerY());

3.3 Root级容错方案(备用)

当标准点击失败时,通过Root权限强制点击:

function safeClick(x, y) {
    if (!click(x, y)) {
        Tap(x, y); // Root级点击
        sleep(500); // 必须加延迟
    }
}

4. 全流程稳定性保障

auto.waitFor(); // 必备前置检查
setScreenMetrics(1080, 1920); // 分辨率适配

// 多步操作封装
try {
    if (!clickWithVerify(500, 800, () => text("首页").exists(), 5000)) {
        throw new Error("页面跳转失败");
    }
    // 后续操作链...
} catch (e) {
    log("执行中断: " + e.message);
    engines.stopAll(); // 停止所有脚本
}

关键注意事项

  1. 超时控制:单次验证建议不超过3秒,过长会导致用户体验阻塞
  2. 降级策略:当连续2次失败时应主动终止,避免无效操作
  3. Root兼容性:使用Tap()前需检查root权限状态:device.isRooted()

补充回答 2

在 Hamibot 自动化脚本中,若遇到 com.startdust.automator.uiobject.child 找不到的问题,通常是由于控件结构、索引越界或布局未完全加载导致的。以下是解决步骤:


1. 确认控件层级关系

  • 使用 parent() 获取当前控件的父控件。
  • 使用 children() 遍历父控件的所有子控件,检查目标兄弟控件是否存在:
    // 文档地址 https://docs.hamibot.com/
    var target = id("your_target_id").findOne();
    var parent = target.parent(); // 获取父控件
    var siblings = parent.children(); // 获取所有兄弟控件
    
    siblings.forEach(function(child) {
        log("子控件类型:" + child.className());
        // 根据需求筛选特定控件
        if (child.id() === "com.startdust.automator.uiobject.child") {
            child.click(); // 执行操作
        }
    });
    

2. 检查子控件索引

  • 使用 childCount() 获取子控件总数,避免 child(i) 越界:
    var list = className("AbsListView").findOne();
    for (var i = 0; i < list.childCount(); i++) {
        var child = list.child(i); // 通过索引获取子控件
        if (child) {
            log(child.className());
        } else {
            log("子控件 " + i + " 不存在");
        }
    }
    

3. 等待控件加载

  • 若控件因异步加载未出现,使用 findOne(timeout) 等待:
    // 最多等待 5 秒
    var child = id("com.startdust.automator.uiobject.child").findOne(5000);
    if (child) {
        child.click();
    } else {
        toast("未找到目标控件");
    }
    

4. 处理布局变化

  • 在滑动或操作后,布局可能重新加载,需重新定位控件:
    var parent = id("parent_id").findOne();
    parent.scrollForward(); // 滑动后可能触发布局刷新
    // 重新获取子控件
    var updatedChild = id("com.startdust.automator.uiobject.child").findOne(3000);
    

5. 兼容性提示

  • 避免使用箭头函数(如 () => {}),改用普通函数。
  • 不依赖 child(i) 的直接调用,优先使用 children().forEach() 遍历。

常见问题排查:

  • 控件不可见:使用 scrollable().scrollForward() 滑动列表。
  • 控件属性缺失:通过 id()text()className() 组合定位。
  • 权限问题:确保已开启无障碍服务和前台悬浮窗权限。

如果问题持续,请检查控件的 idclassName 是否正确,或发送邮件至 support@hamibot.cn 提供详细日志。

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