回答
在 Hamibot 中,获取当前页面 UI 结构的标准方式是通过无障碍服务(Accessibility Service)遍历界面节点树。你可以编写脚本获取节点信息,将其格式化为 XML 并保存到手机存储中。
以下是实现该功能的完整脚本及操作步骤。
前置准备
- 无障碍权限:确保 Hamibot 助手已开启无障碍服务权限。
- 存储权限:确保 Hamibot 助手已获取文件存储权限,以便写入文件。
- 目标应用:运行脚本前,请先打开你需要获取 UI 结构的应用页面。
脚本代码
将以下代码保存为脚本并运行。脚本会遍历当前页面的所有控件,生成 XML 文件并保存至 /sdcard/hamibot_ui_dump.xml。
// 文档地址 https://docs.hamibot.com/
auto.waitFor();
var root = auto.root();
if (root == null) {
log("无法获取根节点,请检查无障碍权限是否已开启");
hamibot.exit();
}
var xmlContent = dumpNode(root, 0);
var path = "/sdcard/hamibot_ui_dump.xml";
// 确保目录存在并写入文件
files.createWithDirs(path);
files.write(path, xmlContent);
log("UI 结构已导出至:" + path);
hamibot.exit();
// 递归遍历节点生成 XML
function dumpNode(node, indent) {
var sb = "";
var spaces = "";
for (var i = 0; i < indent; i++) {
spaces += " ";
}
sb += spaces + "<node";
// 获取常见属性
var className = safeGet(node, "className");
var text = safeGet(node, "text");
var desc = safeGet(node, "contentDesc");
var bounds = safeGet(node, "bounds");
var visible = safeGet(node, "visibleToUser");
var checkable = safeGet(node, "checkable");
var checked = safeGet(node, "checked");
var clickable = safeGet(node, "clickable");
var scrollable = safeGet(node, "scrollable");
var longClickable = safeGet(node, "longClickable");
var enabled = safeGet(node, "enabled");
var password = safeGet(node, "password");
var selected = safeGet(node, "selected");
var id = safeGet(node, "viewIdResourceName");
// 添加属性到 XML
if (className) sb += " class=\"" + escapeXml(className) + "\"";
if (text) sb += " text=\"" + escapeXml(text) + "\"";
if (desc) sb += " content-desc=\"" + escapeXml(desc) + "\"";
if (bounds) sb += " bounds=\"" + escapeXml(bounds) + "\"";
if (id) sb += " resource-id=\"" + escapeXml(id) + "\"";
if (visible !== null) sb += " visible=\"" + visible + "\"";
if (checkable !== null) sb += " checkable=\"" + checkable + "\"";
if (checked !== null) sb += " checked=\"" + checked + "\"";
if (clickable !== null) sb += " clickable=\"" + clickable + "\"";
if (scrollable !== null) sb += " scrollable=\"" + scrollable + "\"";
if (longClickable !== null) sb += " long-clickable=\"" + longClickable + "\"";
if (enabled !== null) sb += " enabled=\"" + enabled + "\"";
if (password !== null) sb += " password=\"" + password + "\"";
if (selected !== null) sb += " selected=\"" + selected + "\"";
var childCount = node.childCount();
if (childCount > 0) {
sb += ">\n";
for (var i = 0; i < childCount; i++) {
var child = node.child(i);
if (child != null) {
sb += dumpNode(child, indent + 1);
}
}
sb += spaces + "</node>\n";
} else {
sb += "/>\n";
}
return sb;
}
// 安全获取属性,防止报错
function safeGet(node, methodName) {
try {
var func = node[methodName];
if (typeof func == "function") {
return func.call(node);
}
return null;
} catch (e) {
return null;
}
}
// 转义 XML 特殊字符
function escapeXml(str) {
if (str == null) return "";
var s = str.toString();
s = s.replace(/&/g, "&");
s = s.replace(/</g, "<");
s = s.replace(/>/g, ">");
s = s.replace(/"/g, """);
s = s.replace(/'/g, "'");
return s;
}
使用说明
- 运行脚本:在 Hamibot 控制台或 APP 中运行上述脚本。
- 查看文件:脚本运行结束后,使用文件管理器打开
/sdcard/hamibot_ui_dump.xml。 - 数据解读:
class:控件类名,用于定位。text:控件显示的文本。content-desc:控件的内容描述,常用于无障碍定位。bounds:控件在屏幕上的坐标范围。resource-id:控件的资源 ID,是最稳定的定位方式。
注意事项
- 兼容性:代码已适配 Rhino 1.7.15 引擎,未使用箭头函数或默认参数。
- 性能:如果页面控件数量极大,生成过程可能需要几秒钟。
- 权限:如果文件写入失败,请检查 Hamibot 是否拥有存储权限。
- 动态内容:获取的是脚本运行瞬间的页面结构,动态变化的内容需要重新运行脚本获取。
通过这种方式,你可以获得结构清晰、可读性强的 XML 数据,便于后续编写自动化脚本时定位元素。
ℹ️ 本回答由 AI 生成,内容仅供参考