尧图精选

鸿蒙HDC模拟操作实战:从tap、swipe到自动化脚本

🕒 发布时间:2026/10/1 18:51:29 📁 来源:尧图网络
做鸿蒙开发的人应该都经历过这种状态功能改完了要验证流程结果同一套点击、滑动、输入在真机上手动点了一遍又一遍。后来我把这套重复工作交给HDC命令行工具的模拟操作一句命令代替一个手指动作配合脚本能跑完整条链路。这篇就是我在鸿蒙设备上折腾HDC模拟操作的完整记录包括每条指令的用法、连设备时踩过的坑以及常见的失效排查方法适合刚接触鸿蒙开发或者想把手动测试自动化的人参考。1. HDC模拟操作是什么解决了什么真实问题1.1 从ADB时代过来的联想早年做安卓开发时我已经习惯用ADB调试设备。第一次接触鸿蒙的HDC我第一反应是翻命令清单发现它和ADB的很多思路是共通的。HDC全称是HarmonyOS Device Connector本质是电脑与鸿蒙设备之间的调试桥。它负责把电脑上的命令送到设备执行也能把设备日志、状态回传回来。对开发者来说最常用的功能无非是安装HAP、列出设备、进入Shell、模拟输入操作等。我特别想强调一点HDC不是ADB的简单改名。鸿蒙的设备协议、权限模型和应用安装机制都有自己的一套逻辑。比如安装包是HAP拉起Ability用aa start很多命令参数跟Android不完全一样。所以你不能想当然地把ADB命令直接套过来最好的方式是先看一遍HDC支持的完整命令列表再针对性使用。模拟操作就是其中让我觉得价值最大的一块。它的本质很简单让设备系统接收一个输入事件比如坐标点击、滑动手势、物理按键、文本输入。对App来说这些事件跟在屏幕上用手指操作没有本质区别。应用并不感知是谁在点只感知到触摸事件流。这也就意味着你可以在不侵入应用代码的前提下用一个外部命令行工具驱动整个界面流程非常适合回归测试、演示录屏、批量验证。1.2 HDC能模拟哪些操作我在实际项目里最常用的模拟能力包括这几类点击指定屏幕坐标模拟一次手指按下和抬起。滑动从起点滑到终点支持设置时长也能模拟长按。按键模拟返回键、Home键、音量键、电源键等物理按键。文本输入向当前焦点输入框发送ASCII文本。屏幕相关亮屏、息屏、锁屏状态切换。配合辅助截图、查看当前窗口、获取布局信息等。这些能力单独看都不复杂但组合起来能完成很多事。比如我刚接手一个鸿蒙应用时需要在不同账号下跑一遍完整的用户路径。手动操作一次大概三分钟十几个账号就是快一个小时而且人很容易点错。用HDC模拟操作之后我把账号信息放进循环跑一组大约十分钟就能完事中途还能去做别的事。1.3 它和你手动操作有什么区别最大的区别是“状态感知能力”。人手点界面时眼睛能看到界面变化知道该等页面加载完再点下一步。HDC模拟操作没有眼睛它只管发指令不管界面是否已经响应。所以你用HDC做模拟操作时必须自己负责节奏控制等待、延时、校验页面状态。这也是新手最常翻车的地方。另一个区别是“坐标系”。人眼看到的是一个控件手指点的是控件中间。HDC不知道控件在哪只认识屏幕上的像素坐标。所以你要先把“我想点那个按钮”翻译成“屏幕横向第540像素、纵向第1200像素的位置”。这就引出后续坐标获取和动态计算的问题。我的结论是HDC模拟操作是一个极其好用的“假手指”但它不是“智能大脑”。它胜在轻量、稳定、不受应用代码限制适合做流程性、重复性的操作模拟。如果你需要智能断言、元素识别、复杂逻辑应该上自动化测试框架但那套体系要维护的东西也多得多。两者不是替代关系是互补关系。2. 搭建环境HDC下载、连接设备与版本血泪坑2.1 HDC从哪里来HDC不是系统自带的命令行工具需要单独准备。最常见的来源有两个一个是安装DevEco Studio时随IDE一起提供的一般在SDK目录下另一个是华为开发者官网提供的Command Line Tools包。我建议开发机直接把 hdc 所在路径加进系统环境变量否则每次都得带着全路径敲命令时间长了非常烦躁。Windows下我记得默认路径类似C:\Program Files\Huawei\DevEco Studio\sdk\default\openharmony\toolchains\hdc.exemacOS下一般是*/sdk/default/openharmony/toolchains/hdc。装好后在终端里敲hdc -v能看到版本号就说明路径没问题。这里有个小提醒命令行工具包分不同平台Windows、macOS、Linux各有对应版本别下错。Linux环境如果提示权限不足记得先chmod x hdc。2.2 USB连接和设备发现有线连接仍然是最可靠的连接方式。首先在鸿蒙手机上开启开发者模式打开“设置”应用进入“关于本机”或者“关于手机”找到HarmonyOS版本号连续点击多次直到系统提示“已进入开发者模式”。然后进入“开发者选项”打开“USB调试”。用数据线把设备和电脑连起来在终端执行hdc list targets如果输出里出现了一串设备序列号说明连接成功。如果列表为空我一般按这个顺序排查先确认数据线是不是只能充电不能传数据尽早换一根原装线或品牌线再检查开发者选项里的“USB调试”是否确实打开最后看电脑的驱动有没有识别到设备。Windows下如果系统提示“未知设备”需要安装设备驱动很多第三方助手工具也能顺手装驱动但注意别装捆绑软件。我实测下来USB连接最隐蔽的坑其实是锁屏。设备息屏锁着HDC虽然能识别设备但部分操作会不响应最好在调试期间把锁屏方式改为“无”或者“滑动解锁”或者至少在跑模拟操作前手动亮屏解锁一次。2.3 无线连接的两种姿势调试自动化时我不能一直插着线所以无线连接用得越来越多。鸿蒙的HDC无线连接有个让我一开始绕晕的地方它有两种路径。第一种是先用USB连接电脑在设备上确认无线调试端口后执行hdc tconn 192.168.1.100:5555执行成功后可以拔掉USB线后续命令都走局域网。第二种是设备已经开启了“无线调试”选项界面会显示一个IP和端口直接在电脑上执行hdc tconn 设备IP:端口。只要电脑和设备在同一个局域网一般都能连上。无线连接有个前提防火墙别拦着端口。Windows电脑偶尔会出现connect failed的报错关掉第三方防火墙或者加白名单就能解决。另外无线环境不如USB稳定跑长时间自动化时如果出现掉线可以写一个简单的重连逻辑发现hdc list targets结果为空就再执行一次hdc tconn。2.4 版本不匹配的坑版本问题是我这次要重点说的。HDC和鸿蒙系统之间有严格的版本适配关系旧版HDC连新版系统经常出现莫名其妙的怪问题。最典型的表现有设备能识别但hdc shell input tap执行后无响应。部分命令提示unknown command或者invalid parameter。安装HAP时报错但应用在设备上明明能正常安装。我之前踩过一次很典型的坑电脑里装过一个较老版本的HDC连上一台新版本的鸿蒙设备tap命令一直没反应但list targets和shell都正常。折腾很久才意识到是版本问题换成与设备匹配的新版HDC后立刻恢复。所以我的建议是尽量从官方渠道下载和鸿蒙系统版本配套的HDC别为了图方便用历史遗留的旧版本也别从第三方渠道随意拿。命令行工具这种基础组件踩坑成本远高于下载成本。3. 模拟操作四大金刚tap、swipe、keyevent、text3.1 tap点坐标而不是点控件最基本的模拟点击命令是这样hdc shell input tap 540 1200这条命令的含义是在屏幕横坐标540、纵坐标1200的位置执行一次点击。坐标系以屏幕左上角为原点单位是物理像素。你需要知道目标控件在屏幕上的大概位置而不是它的控件ID。获取坐标的方法有很多。最原始但在调试阶段最有效的一种是先用HDC截一张图然后在图片工具里查看目标位置坐标。HDC截图命令是hdc shell snapshot_display -f /data/local/tmp/screen.png hdc file recv /data/local/tmp/screen.png ./screen.png截图之后用系统自带画图工具打开鼠标放在想点的位置就能看到像素坐标。这个办法笨但管用。鸿蒙的开发者选项里也有“指针位置”功能开启后屏幕上会实时显示手指触摸的坐标这也是一种辅助获取坐标的方式。值得注意的是tap 命令发出去之后没有任何回显。它不会告诉你“点击成功”或“点击失败”所以你必须在点击之后自己验证界面变化。我一般会在关键操作后用hdc shell snapshot_display再截一张图对比前后差异。3.2 swipe滑动和长按都靠它滑动手势用这条命令hdc shell input swipe x1 y1 x2 y2 duration前四个参数是起始点和结束点的坐标最后一个可选参数是滑动持续时间单位毫秒。它不只是用来翻页拖动进度条、下拉刷新、长按图标这些手势都能靠它模拟。举几个我实际用过的场景模拟下拉刷新从屏幕中间偏上位置滑到偏下位置例如hdc shell input swipe 540 800 540 1800 200。拖动滑块亮度条或者视频播放进度条可以从起点滑块位置滑到目标位置时间放长到500毫秒以上动作更接近真人。长按操作比如长按桌面图标进入编辑模式用同一坐标作为起点和终点把duration设置为1000毫秒以上。长按其实就是swipe的一个特殊情况这点容易被人忽略。我最早还以为长按需要单独的命令后来才发现只要把起点和终点设成同一个点再拉长执行时间即可。3.3 keyevent按键也能模拟按键模拟的命令格式hdc shell input keyevent 4数字4代表返回键。除了数字编码有些HDC版本也支持直接传按键名称比如hdc shell input keyevent BACK。我用过一段时间的常用KeyCode整理成表格方便查阅KeyCode含义说明3HOME键回到桌面4BACK键返回上一级26电源键亮屏/息屏切换82菜单键打开上下文菜单85播放/暂停多媒体控制87下一曲多媒体控制111ESC键退出当前操作220亮度调低部分设备支持221亮度调高部分设备支持keyevent 的用法和真实按键几乎等价。比如我想回到桌面再重新进入应用就可以先hdc shell input keyevent 3再执行hdc shell aa start -b 包名 -a Ability名。这种方式比模拟滑动手势更稳定因为不依赖坐标任何时候执行都会触发系统返回行为。这里提一个容易踩的坑不同鸿蒙版本对某些按键的映射可能存在差异。比如菜单键在部分版本上不响应音量键的KeyCode在不同设备上也可能不一样。建议在真机上先手动执行一遍确认行为符合预期再写进脚本。3.4 text输入中文的特殊处理文本输入命令是这样的hdc shell input text hello这条命令的核心限制是默认只支持ASCII字符不支持中文、日文、韩文等多字节语言。如果你直接往命令里塞中文大概率会失败或者输入乱码。另外空格也不能直接传需要用%s代替比如hdc shell input text hello%sWorld如果确实需要输入中文怎么办我实践下来的可行方案有两个方向。方向一把要输入的内容放到系统剪贴板然后在输入框里长按点击“粘贴”。但HDC本身没有标准的剪贴板写入命令所以这个方案依赖额外工具不是开箱即用。方向二换用支持ADB/HDC输入中文的第三方输入法或测试输入法这类输入法一般自带监听通道能把文本通过特殊协议塞进输入框。文本输入还有一个细节焦点问题。input text只往当前获得焦点的输入框发送内容如果界面上没有输入框获得焦点命令执行了也白执行。所以我在一套操作里会先点一下目标输入框等一秒再发 text 命令。3.5 获取真实坐标的辅助手段模拟操作的坐标是最容易出问题的地方所以我单独说一块。除了截图看坐标还有两个命令很有用hdc shell wm size hdc shell wm density第一条输出当前屏幕的物理分辨率比如Physical size: 1080x2340第二条输出像素密度比如Physical density: 480。这两个值能帮我做坐标比例换算。假设我写脚本时用的基准设备是1080x2340点击位置是540x1200现在换到一台720x1600的设备简单按比例缩放就能得到新设备的点击坐标新x 540 * 720 / 1080 360新y 1200 * 1600 / 2340 ≈ 821这个比例换算不是绝对精确因为不同的屏幕比例和系统栏高度会影响最终点中的位置但至少能把“完全点歪”变成“大概正确”后续微调就快很多。如果有条件还可以尝试hdc shell uiautomator dump导出当前界面的控件树然后解析XML里每个控件的bounds属性从而拿到目标控件的中心点坐标。不过这类命令在鸿蒙不同版本上的支持程度不一样有些版本路径和格式有差异。我一般在开发调试阶段用截图和指针位置在写脚本阶段用wm size做动态换算控件树只在有空的时候用。4. 组合起来才是真本事还原一个真实业务场景4.1 场景设计与前置准备前面全是单条命令的拆解但实际工作里没人会只敲一条。我拿一个真实场景来说验证一个鸿蒙应用的“登录-首页-退出”流程。前置条件有几个一是应用已经安装到设备上我一般用hdc install xxx.hap安装二是有一个测试账号注意不要用真实敏感账号因为自动化脚本里可能会明文记录密码三是设备保持解锁状态最好关闭自动锁屏。在执行模拟操作之前我会先手动进一次应用记住登录页的几个关键坐标账号输入框坐标、密码输入框坐标、登录按钮坐标。这次手动操作花不了几分钟但能省下脚本调试阶段反复猜测坐标的时间。4.2 完整命令串演一遍下面是这个场景的完整命令串我用的是bash环境Windows下可以放进.bat脚本# 检查设备在线 hdc list targets # 安装应用如果已经安装可以跳过 hdc install ./demo.hap # 启动应用包名和Ability名根据实际替换 hdc shell aa start -b com.example.demo -a MainAbility # 等待应用启动 sleep 3 # 点击账号输入框 hdc shell input tap 540 1100 # 输入账号 hdc shell input text testuser01 # 点击密码输入框 hdc shell input tap 540 1300 # 输入密码仅ASCII hdc shell input text Passw0rd # 点击登录按钮 hdc shell input tap 540 1600 # 等待首页加载 sleep 5 # 模拟返回键退出到桌面 hdc shell input keyevent 4这串命令每一步都有注释核心逻辑就是“点、等、输入、点”。执行完之后我再截一张图确认最终状态hdc shell snapshot_display -f /data/local/tmp/result.png hdc file recv /data/local/tmp/result.png ./result.png打开截图看到首页元素出现说明整条流程跑通了。如果发现卡在中间某一步我会在对应步骤前后各加一次截图快速定位是哪一步没生效。4.3 延时与等待不要裸奔执行在上面命令串里我反复用了sleep这不是随便写的而是模拟操作最容易被低估的点。真实用户点击登录按钮之后眼睛会看到加载动画等到页面跳转完才进行下一步。但HDC命令是按顺序执行的上一秒点完登录下一秒可能直接发返回键结果应用还没来得及跳转返回键就把应用退了。我的经验是不同操作之间必须给足缓冲时间。启动应用后至少等3秒页面跳转至少等3到5秒网络请求频繁的场景建议等更久。更稳妥的方式是轮询。比如想确认登录后的首页是否出现可以写一个循环每隔1秒查一次当前顶层窗口直到出现目标页面或者超时。例如可以尝试这样的思路用hdc shell hidumper -s WindowManager查看当前窗口信息在循环里解析关键字段匹配到目标页面就继续超时就报错退出。这种方式比固定sleep更可靠但代码量会大一些。我个人的习惯是脚本前期用固定sleep快速跑通流程流程稳定后再把关键节点改成轮询等待提高整条自动化链路的稳定性。5. 模拟操作失效时我的排查链路5.1 命令返回错误码但没有具体提示最让人头疼的情况是命令执行了可是界面纹丝不动。这时候我第一步会检查HDC是不是还连着设备。无线连接偶尔会悄悄断开但命令仍然能下发设备却没响应。先跑一下hdc list targets如果输出为空执行hdc tconn 设备IP:端口重连再跑一次。如果设备在线接着检查设备是不是熄屏了。可别笑我至少有两三次在设备息屏状态下跑自动化命令全部“成功”了但屏幕一直是黑的后来才意识到是设备自动锁屏。检查方法也很简单执行hdc shell power-shell wakeup让设备亮屏然后重新解锁再跑。这个问题暴露了模拟操作的盲区它只会发事件不会等待屏幕状态变化所以你在脚本里要主动管理亮屏状态。5.2 点击了但界面没反应如果设备在线、屏幕亮着、命令也执行了但页面没有预期变化我一般怀疑三个原因。第一个原因是点击位置被其他元素遮挡。常见的遮挡源是系统弹窗、悬浮球、下拉通知栏。尤其是悬浮球很多设备开着三指截屏或悬浮导航透明触控层会在某些区域吃掉点击事件。我调试时习惯把这类辅助功能全部关掉。第二个原因是控件实际响应区域和视觉位置不一致。有些自定义控件、WebView里的元素视觉上在上方实际可点击区域却在另一个位置。遇到这种情况我会用开发者选项里“指针位置”功能手动点一次目标看系统上报的坐标是多少再对比HDC里填的坐标就知道偏差了多少。第三个原因是时序问题。点击真的发出去了但当时页面还在加载目标控件还没渲染出来点击落在了空白区域。这种问题很好判断把点击前的sleep加长或者改成轮询等待页面元素出现而不是等固定秒数。5.3 坐标漂移换个设备就偏固定坐标的脚本换个分辨率设备就跑偏这是坐标模拟的天生弱点。前面我提到过用hdc shell wm size做比例换算这里再补充一个细节比例换算对设备的“可用显示区域”很敏感。有些设备的屏幕比例是19.5:9有些是20:9单单按分辨率等比缩放底部导航栏、状态栏的高度占比不一样导致换算后的坐标在竖屏页面上接近正确但页面偏下部分的按钮会发生明显偏移。我在项目里给过一条曲线救国的方案先在同一型号设备上写死基准坐标用脚本启动时自动读取当前设备分辨率只对同一比例范围的设备做换算如果相差太大干脆用单独一套坐标配置。5.4 系统限制安全输入、锁屏和隐私保护不是所有操作都能用HDC模拟搞定这一点必须提前知道。鸿蒙和所有主流移动操作系统一样对敏感输入有保护机制。典型例子是锁屏密码、支付密码这类安全输入框系统会拦截来自非物理输入设备的模拟输入。我测试过在锁屏密码界面用input text输入数字事件可以发出但密码框根本收不到这是系统层面的安全策略不是命令写错了。另外一个容易踩的坑是应用自行实现的“防自动化”逻辑。有些金融、风控类应用会检测触摸事件的来源如果发现输入事件不是来自真实屏幕触摸会弹出安全提示或踢出登录状态。遇到这种情况HDC模拟操作就不是合适的工具应该考虑使用官方提供的自动化测试框架通过系统授权的方式完成输入。排查完这些之后我一般会重新读一遍自己脚本的每个动作设备状态检查、亮屏唤醒、屏幕解锁、点击、等待、校验。这套链路上任何一个环节断开都可能导致“命令成功但实际没操作”。6. 从单条命令到自动化脚本把模拟操作变成生产力6.1 用批处理/Shell串起来模拟操作要真正提升效率必须从“手工敲”变成“脚本跑”。最简单的形式就是Shell脚本把命令串成一串。我在Shell里习惯先定义一个公共函数避免到处重复function tap() { hdc shell input tap $1 $2 sleep 1 } function type_text() { hdc shell input text $1 sleep 1 } tap 540 1100 type_text testuser01这样做的价值有两个一是统一处理延时不会漏写sleep二是如果以后命令变了只需要改函数内部不用满世界找命令。Windows下的.bat脚本也差不多不过语法更受限我建议Windows用户直接装一个Git Bash或者使用Python跨平台。脚本跑起来之后建议在关键节点加上日志输出比如echo [$(date)] 点击登录按钮。自动化脚本一旦跑得时间长没有日志就完全不知道执行到哪一步挂了加日志虽然土但排查效率翻倍。6.2 用Python的subprocess统一管理当脚本变得复杂判断分支变多Shell脚本就不太好维护了我一般切到Python。Python的优势是异常处理、数据解析、循环和重试都更好写。调用HDC的命令很直接import subprocess import time def hdc(*args): 统一执行hdc命令返回stdout文本 result subprocess.run( [hdc, *args], capture_outputTrue, textTrue, encodingutf-8 ) return result.stdout.strip() def tap(x, y): hdc(shell, input, tap, str(x), str(y)) time.sleep(1) def is_device_online(): targets hdc(list, targets) return bool(targets) if not is_device_online(): print(设备不在线开始重连...) hdc(tconn, 192.168.1.100:5555) time.sleep(2) tap(540, 1100)这个封装的好处是以后换命令、加重试都只改函数不用动业务流程。我甚至会在tap函数里加一个简单的重试逻辑点击后截图对比前后像素差异判定是否需要再点一次。这种“点击-截图-校验”的模式能让自动化脚本稳定不少不过实现复杂度也高一些适合需要长时间跑回归的场景。6.3 结合控件树让坐标不再硬编码如果说HDC模拟操作有什么让我觉得可惜的那就是纯坐标驱动太脆UI一变全崩。后来我尝试把它和控件树结合起来才算稍微缓解了这个问题。思路是在执行模拟操作前先导出当前界面的控件树XML然后在XML里找到目标文本比如“登录按钮”读取它的bounds属性算出中心点坐标再调用tap。这样就算按钮在界面上移动了位置只要文本文案不变脚本也能找到新坐标。实现大致是hdc shell uiautomator dump导出的XML可能在不同鸿蒙版本上路径不同我用的时候会先执行一次看输出路径再用hdc shell cat 对应路径查看内容。解析XML用Python的xml.etree.ElementTree或者正则都行。这个方法不是万能的有些自绘控件、Canvas渲染的界面不会暴露标准控件树那就只能退回坐标方案。但它确实能处理很大一部分常规按钮、文本框值得一试。6.4 真实自动化中的几个小习惯最后聊几个我在长期实践中沉淀下来的习惯都不是什么高级技巧但能实实在在减少踩坑次数。第一脚本开头一定要写设备与分辨率校验。很多自动化跑挂不是用例写错了而是连接设备变了或者分辨率变了。先确认环境再开始执行能省下一半的排错时间。第二危险操作前加日志和确认。比如脚本要删除数据、退出登录、或者执行频率很高的循环我都会在日志里打印当前执行位置必要时在执行前加一个人工确认的交互。第三敏感信息不要硬编码在脚本里。测试账号和密码最好从环境变量或单独的配置文件中读取脚本本身可以提交到代码仓库但敏感信息不要跟着提交。第四每个关键动作后给足等待时间但也不要为了追求稳妥把所有sleep都拉满。我通常先用3到5秒的sleep跑通流程稳定后再逐步减小等待时间优化到“刚好够用”的程度。第五跑完自动化一定要留证据。至少截一张最终屏幕图有条件就录屏。这样出了问题回看证据比猜原因高效得多。这些习惯让我的HDC模拟操作脚本从“能跑一次”进化到“每天跑几轮也不容易挂”这才是自动化真正产生价值的地方。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →