hmos-ui-align
HarmonyOS-Android UI 自动对齐流水线。
它解决什么问题
以往对齐鸿蒙和安卓 UI 的流程需要:
- 人工把设备点到目标页面
- 手动跑 parse 脚本截图 + dump view tree
- 肉眼对比差异
- 手写改鸿蒙源码
每多一个页面/弹窗/tab,上述步骤都要重复一遍,非常费时。
本 skill 做了三件事:
- 用智谱 GLM 驱动的 phone-agent 自动寻路(根据自然语言点到指定页面)
- 自动采集 view tree + 截图(安卓走 adb、鸿蒙走 hdc)
- 自动对比 + 改码,并按 MVVM 模式把 mock 数据放到 Model 层
用户只需要一句自然语言 + 点击路径。
⚠️ 当前只保证 UI 对齐,不保证功能行为对齐。
前置条件
-
设备连接
- 安卓设备:已装目标 App,
adb devices能看到 - 鸿蒙设备:已装目标 App,
hdc list targets能看到 - 两台设备建议都保持亮屏解锁
- 安卓设备:已装目标 App,
-
Python 依赖
pip install openpyxl phone-agent -
智谱 GLM API Key(phone-agent 调用的模型) 到 https://open.bigmodel.cn/ 申请,有免费额度,填到
config.json的glm_api_key。 -
鸿蒙 SDK 路径(给改码阶段查 API 用) 例如 DevEco Studio 自带的
E:\DevEco Studio\sdk\default。
配置 config.json
首次使用前必须改 Agents/hmos-ui-align/config.json。字段说明:
| 字段 | 说明 | 示例 |
|---|---|---|
android.app_name |
安卓端 App 显示名(桌面上看到的名字,phone-agent 打开 app 时用) | "Salt Player" |
android.package |
安卓包名 | "com.salt.music" |
android.project_dir |
安卓源码根目录 | "E:\\SaltPlayerAndroid-main\\SuvineMusicX" |
harmony.app_name |
鸿蒙端 App 显示名 | "Salt Player" |
harmony.package |
鸿蒙包名 | "com.xuncorp.sp2" |
harmony.project_dir |
鸿蒙工程根目录(会被直接修改) | "E:\\SPH" |
hmos_sdk_dir |
鸿蒙 SDK 路径 | "E:\\DevEco Studio\\sdk\\default" |
glm_api_key |
智谱 GLM API Key | "xxx.yyy" |
capture_output_dir |
采集产物输出目录(截图/view tree/分析报告都在这) | "./tmp_saltplayer" |
可以直接参考同目录下的 config-example.json。
使用方式
在 Claude Code 里直接调用 skill:
/hmos-ui-align <自然语言需求,描述要对齐的页面+点击路径>
写需求的三个要点
-
页面路径写清楚 用「→」或「-」标注一级一级的点击步骤,比如
首页 → 点击"AI智能填报" → 点击"专业"筛选按钮。路径越具体,phone-agent 寻路成功率越高。 -
说明是否要覆盖交互态 默认会自动扫描 tab、弹窗、下拉等交互元素并逐个采集。如果只想对齐主页面,请明确说「只对齐主页面,不管弹窗和 tab」。
-
说明是否用 Mock 数据 默认用 mock 数据。如果想调真实后台,在需求里写「不要 mock 数据,调用真实后台」。
例子
例 1(单个弹窗对齐)
/hmos-ui-align 鸿蒙版本app(登录状态下,进入首页-点击"AI智能填报"-点击"专业"筛选按钮)
得到的弹窗样式和安卓同样路径得到的页面不一致,请修改鸿蒙源码将上述页面与安卓版本完全对齐
例 2(补齐缺失页面 + 调真实后台)
/hmos-ui-align 鸿蒙版本app(点击我的-超级会员组件)显示与安卓不一致,且安卓版本在超级会员
上点击"会员中心"会跳到超级会员弹窗页,鸿蒙也没有这页。请修改鸿蒙源码将这些页面与安卓版本
完全对齐,不要mock数据,调用真实后台数据
例 3(多级路径 + 多个页面)
/hmos-ui-align 鸿蒙版本(点击底部高考按钮 -> 带年纪查专业 -> 点击某一具体专业(如临床医学)
-> 点击就业分析,到达"专业就业健康度"展示页面)以及在"专业就业健康度"页面上点击"完整数
据指标"到达的就业健康度详情页都和安卓同一路径的不一致。比较这些页面的差别并将他们在视觉
效果上完全对齐,不要用mock数据,调用后台真实逻辑
运行过程中会发生什么
skill 会严格按 SKILL.md 里的 5 步流水线跑:
Step 0 · 加载 config
读 config.json,解析出所有路径和 API Key。
Step 1 · 双端页面采集
1.1 解析你的需求,拆成一组「基础页」,每个基础页有 android_nav_path 和 hmos_nav_path
1.2 对每个基础页,两端分别:phone-agent 寻路 → 成功后 page_capture.py 截图 + dump view tree
1.3 扫描基础页 view tree,发现 tab、弹窗、下拉等交互元素,自动对每个子状态再采集一遍
1.4 鸿蒙端页面不存在时,寻路会失败,对应目录留空(Step 2 会改从源码读)
产物目录结构:
{capture_output_dir}/
task_{timestamp}/
android_page_1_{name}/
screenshot.png
view_tree.xml
hmos_page_1_{name}/
screenshot.png
view_tree.xml
android_page_1_{name}_popup_filter/
...
Step 2 · UI 差异分析
主 agent 串行执行,不会下放给子 agent(保证质量):
- 2.1 读安卓 screenshot + view tree,写
android_page_*/UI_Analysis.md(组件清单 + 位置 / 颜色 / icon / 尺寸 / 对齐方式等) - 2.2 读鸿蒙 screenshot + view tree,写
hmos_page_*/UI_Analysis.md;鸿蒙页不存在时改读源码写UI_Analysis_from_code.md - 2.3 两份 Analysis 对比,按
references/Comparison_Template.md生成UI_comparison.md(markdown diff 表) - 2.4 验证所有
UI_Analysis*.md和UI_comparison.md都已写全
所有尺寸都会以 126px (3x → 42vp) 的格式同时给出原始 px、设备密度、换算后的 vp。
Step 3 · 改鸿蒙源码
- 把每个
UI_comparison.md里的 diff 项汇总到{task_dir}/fix_checklist.md(唯一 source of truth) - 读
references/MVVM开发文档/学习 MVVM 模式 - 读
page_align.md学习转换规则 - 逐条修 diff,每修一个把
- [ ]改成- [x] - 每个尺寸 / icon / alignment 都要回溯到安卓源码的 XML 或资源值,不允许"看起来差不多"
Step 4 · 编译校验
若可用,调 hmos-fix-build-errors skill 确保工程能编过。不会自动部署。
目录结构
Agents/hmos-ui-align/
├── SKILL.md # 流水线定义(主 agent 执行逻辑)
├── readme.md # 本文档
├── config.json # 用户配置
├── config-example.json # 配置样例
├── page_align.md # Step 3 的转换规则
├── diff_analysis.md # 内部说明
├── scripts/
│ ├── app_feature_verify.py # phone-agent 寻路工具
│ ├── page_capture.py # view tree + 截图采集工具
│ └── navigation-capure.md # 两个脚本的调用约定
└── references/
├── UI_Analysis_Template.md # Step 2 分析模板
├── Comparison_Template.md # Step 2.3 对比模板
├── MVVM开发文档/ # 鸿蒙 MVVM 参考
├── android-to-harmonyOS-ui-layout-mapping-reference.md
├── android-to-harmonyOS-ui-atomic-component-mapping-reference.md
└── android-to-harmonyOS-ui-interaction-mapping-reference.md
单独运行脚本(调试用)
跳过 skill 手动跑采集:
# 安卓寻路
$env:PYTHONIOENCODING="utf-8"
python Agents/hmos-ui-align/scripts/app_feature_verify.py `
--device adb `
--app "Salt Player" `
--package "com.salt.music" `
--prompt "进入首页-点击AI智能填报-点击专业筛选按钮" `
--api-key "$env:GLM_API_KEY" `
--max-steps 15
# 安卓采集
python Agents/hmos-ui-align/scripts/page_capture.py --device adb -o ./tmp/android_page_1_xxx
# 鸿蒙同理,把 --device adb 换成 --device hdc
注意:
--prompt模式会自动在前面加「打开{app_name},」,所以 prompt 里不要再写"打开"。
常见问题
Q: phone-agent 寻路失败怎么办? A: skill 默认重试两次。流水线的内部规则:①先看页面是否存在;②路径错了就 force-stop 重试;③路径对但工具报错就让 agent 自己看截图判断是否到了。超过两次仍失败才会跳过该页。
Q: 鸿蒙端页面根本不存在,能新建吗?
A: 可以。Step 2.2 会改从鸿蒙源码读,Step 3 会按安卓的实现规格新建 .ets 文件到 entry/src/main/ets/pages/,并登记路由。
Q: 为什么同一次任务会采集多个页面? A: Step 1.3 默认扫描交互元素(tab / 弹窗 / 展开收起等)并递归采集。想关掉请在需求里写「只对齐主页面」。
Q: 改完会自动部署吗?
A: 不会。Step 4 只跑编译验证(如果 hmos-fix-build-errors skill 可用)。部署自己来。
Q: 能不能只做差异分析、不改码?
A: 目前流水线是端到端的。如果只想要分析产物,跑完 Step 2 后手动中断即可,所有 UI_Analysis.md 和 UI_comparison.md 都会落盘在 {capture_output_dir}/task_{timestamp}/ 下。
已知限制
- 只对齐 UI,不对齐功能/数据流
- phone-agent 寻路依赖 GLM 模型对页面文本的识别,小字体或非标准控件可能识别不准
- 双端设备的分辨率/密度差异会影响像素到 vp 的换算,流水线已显式带上 density,但同一个 Figma 规格下仍可能出现 ±1vp 偏差