智绘鸿蒙 · 如 7 而至端侧 AI 能力实战手记

让 AI Agent 自己把鸿蒙工程跑到真机上

智绘鸿蒙·如 7 而至

前言

先说结论:在鸿蒙 7 这一代,"改代码 → 编译 → 装机 → 点开 → 看效果"这条链,已经可以完整交给一个不会看屏幕的 Agent 去跑。人手只需要出现在两个地方——第一次登录 AGC,和最后确认那两张真机截图。

我把这条链在 MatePad Pro 上重跑了一遍,每一步的真实输出都留了图。为什么要留图?因为这条链上有三个地方,退出码会骗人:

  1. create 缺参数时不告诉你合法格式;
  2. build 没签名照样 BUILD SUCCESSFUL
  3. --hotreload-apply 会静静地卡死。

如果你打算让 CI 或者 Agent 替你干活,这三处就是必须写断言的地方。下面按执行顺序走。

先做环境自检

三条命令,顺序无所谓,但必须都在。

命令 看什么 我这次的输出
devecocli --version CLI 是否够新 1.3.2(提示可升级到 1.3.4)
devecocli device list 序列号 + Kind + Device Type 平板 device/tablet、nova 12 device/phone
devecocli auth team list 团队 ID 四个团队,挑自己的那个

两个细节:

  • device listKinddevice 才算授权完成。出现 unauthorized 就是签名 Profile 里没有这台机器的 UDID,跟 USB 线没关系,别去插拔。
  • team list 请自己看清楚,别把输出贴进文章或仓库。团队 ID 后面会用到,我这里一律写成 30**********70

第 1 步:create,先在参数上摔两次

create 的两次失败

第一次失败:Error: --app-name is required--bundle-name 可以省(自动推导成 com.example.<app-name>),--app-name 反而是必填的。这个反直觉,因为大家习惯先想包名。

第二次失败:cli-demo 不合法。App 名只允许字母开头 + 字母/数字/下划线,连字符不行。这条报错值得夸一句——它把正则用文字写全了,看一眼就能改对。

改成 cli_demo 之后一次过:

create 成功

生成的骨架只有 6 个顶层条目(AppScope/entry/build-profile.json5code-linter.json5hvigor/hvigorfile.tsoh-package.json5),没有 .gitignoreAgent 在这里要主动补一个,原因马上就会看到。

第 2 步:build 成功,但包是空的

先跑一次 build,故意不配签名。

build 成功但没签名

上半段全是绿的:BUILD SUCCESSFUL in 3 s 167 msBuild completed successfully.。真正的判据在最后单独一行:

Target device is a real device, but the artifact for 'entry' is not signed.
Real devices cannot install unsigned packages.

所以写脚本时,不要拿 build 的退出码当"能装机"的依据。要判断的是 run 的最后一行有没有 start ability successfully。同理,hvigor WARN: Will skip sign 'hos_hap' 这条 WARN 是唯一的早期信号,值得在日志里 grep 一次。

第 3 步:signature generate,一次性的事

devecocli signature generate --product default --team-id 30**********70

输出是四行进度 + 两行结果:p12 → csr → certificate → profile,然后 Signing config written to ...\build-profile.json5

签名生成 + 真正跑通

这里有三条硬约束,踩过一次就会记住:

  • **Profile 绑 bundleName,也绑设备 UDID 列表。**换一台真机、或者换包名,都要 --force 重签。
  • **它把密钥口令明文写进 build-profile.json5。**生成完立刻检查 .gitignore 是否覆盖到签名材料;仓库里绝对不要出现这个文件的 material 段。
  • **材料落在 C:\Users\<你>\.ohos\config\ 下,配置里是绝对路径。**换台机器、换个用户名,这套签名直接失效。别指望把 build-profile.json5 提交给同事就能跑。

补完签名再 run,这一次才真的落到屏幕上:

Installing artifacts to device 59HYD***2258...
App installed successfully
Launching com.example.hmos7series/EntryAbility...
Application 'com.example.hmos7series': start ability successfully.

第 4 步:让 Agent 自己看屏幕

devecocli ui 是这条链上真正的价值所在。它给的不是像素,是一棵带坐标的节点树:

devecocli ui layout --device 59HYD***2258
[0,0,1840,2800]
  Stack#ContainerModalStack [0,83,1840,2800]
    Text#HelloWorld [622,1349,1218,1474] "Hello World" clickable

id、边界框、文本、clickable 全在里面。Agent 拿到的是一句"把 (622,1349)-(1218,1474) 这个可点击节点的中心点敲一下",也就是 ui click 920 1411。敲完再 dump 一次,文本变了、框也变窄了——闭环成立,全程不需要 OCR 一张图。

layout → click → layout 闭环

对应的两张真机截图,这是这条链唯一需要人眼确认的地方:

点击前

点击后

ui 家族完整能力:layout / screenshot / window / click / doubleclick / longclick / swipe / fling / dircfling / drag / text。三个坑:

  1. screenshot 的参数是 --path,不是 --output;目标文件已存在会拒绝覆盖,脚本里先 rm -f
  2. 多台设备在线时 --device 是必填,不填它会自己猜。
  3. fling 只吃 4 个坐标参数,速度得走 hdc shell uitest uiInput fling ...

第 5 步:热重载,能用但别依赖它

CLI 有 --hotreload / --hotreload-apply 一对,看着是给 Agent 量身定做的:起一个 watch 会话,之后只推增量。

热重载实测

实测结果分两半。

--hotreload 起会话是好的:BUILD SUCCESSFUL in 5 s 894 msHotReloadArkTS 4 s 230 ms,最后明确打印"写 .hvigor/<file> 再到另一个终端 apply"。

--hotreload-apply 我没跑通。第一次报 Hot reload requires --module <name>——它前面刚打印完 Auto-selected module: entry,却又要求你显式传,这个自相矛盾值得留意。补上 --module entry 之后,卡在:

[DaemonClient] Compiling, waiting for hot compile to finish...

七分钟没有任何进展,最后我终止了守护进程。顺带在它的构建参数里看到 requiredDeviceType=phone——脚手架生成的 module.json5deviceTypes 默认只有 phone,而目标是一台平板。这条线索我没有继续挖,不能断定是它导致的。

结论很实用主义:**Agent 批量迭代时直接重跑 run。**增量编译只占 3~7 秒,比一个会卡死的守护进程好维护得多。热重载留给"改一行文案反复看"这种人手场景。

把这条链写成断言

上面五步串起来,Agent 侧真正需要的其实只有四条判断。我把它们按"错了会怎样"排在一起,方便直接抄进脚本:

断言 通过条件 失败时的真实现象
工程存在 createoh-package.json5 可见 Error 后目录根本不创建,ls 才是唯一可靠判断
包名合法 --app-name 匹配 [A-Za-z][A-Za-z0-9_]* 只打印一句 Failed to create project.
产物已签名 日志里不出现 Will skip sign 装机时最后一行才告诉你没签名
应用已拉起 run 输出含 start ability successfully 退出码 1,但前面的 build 段全是绿的

第四条之后还可以再加一条业务断言:ui layout 里目标节点的文本等于预期值。这一步是整条链唯一能证明"功能真的对了"的判据,前面四条只证明"装上了"。

顺带一条经验:ui layout 输出的边界框是 [left,top,right,bottom],不是 x,y,w,h。第一次拿到就把第三个数字当宽度用,点击坐标会飘到屏幕外,而且不报错——只会得到一棵纹丝不动的树,很容易误判成"应用卡死了"。

真机数据

环节 首次 后续(增量)
create 未计时,生成 6 项骨架
build BUILD SUCCESSFUL in 20 s 805 ms,33 tasks 全执行
CompileArkTS 11 s 433 ms 424 ms
PackageHap 1 s 785 ms 993 ms
run(含装机 + 拉起) 签名后那次编译 6 s 869 ms,26 executed / 7 up-to-date 未签名那次 3 s 167 ms,18 executed / 15 up-to-date
ui layout 未计时,人感"秒回" 同左
--hotreload 会话 5 s 894 ms,34 tasks(20 executed) apply 未完成

测试机:MatePad Pro(API 26,1840×2800,序列号已打码)。对照机 nova 12 仅用于验证 device list 的多设备行为。

总结

这条链适合两类活:一是夜间批量回归——Agent 自己 create、自己签名、自己装机、自己点完一圈再截图;二是多设备适配验证,ui layout 的坐标树比人眼快得多。

不适合的是首次接手一台新机器:签名材料绑机器、绑包名、绑 UDID 列表,这一段必须有人登录一次 AGC。把这条规则写进流程,剩下的都可以交给命令。

💡 一句话build 的退出码不代表能装机,run 最后一行的 start ability successfully 才是;剩下的判断交给 ui layout 的坐标树,而不是截图。

参考文献

  1. DevEco Studio 工具概览:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-tools-overview
  2. @deveco/deveco-cli(npm 包页):https://www.npmjs.com/package/@deveco/deveco-cli
  3. DevEcoCode 鸿蒙专属 AI 智能体:https://atomgit.com/openharmony-sig/deveco-code