UiAutomatorViewer无法适配多显示器场景,如何通过Appium实现多显示器下多应用的元素识别与测试?
解决多显示器场景下Appium/UiAutomatorViewer无法识别副屏元素的问题
我之前做Android多显示器测试的时候也碰到过一模一样的问题——UiAutomatorViewer和默认的Appium会话只能抓到主屏内容,副屏的应用完全看不到。结合我的实践经验,给你几个可行的方案,都是不需要局限于单应用的系统级方案:
方案1:利用UiAutomator2的原生多显示器API(推荐)
Appium底层依赖的UiAutomator2本身是支持多显示器识别的,只是默认只聚焦主显示器。你可以通过Appium的executeScript调用UiAutomator2的原生接口来获取所有显示器的内容:
步骤1:获取所有显示器的ID
首先需要确认系统里的所有显示器ID,主屏一般是0,副屏可能是1或其他数字。你可以用adb命令快速查询:
adb shell dumpsys display | grep -E "DisplayDeviceInfo: .*displayId="
或者通过Appium的脚本调用获取:
// Java客户端示例 List<Integer> displayIds = (List<Integer>) driver.executeScript("mobile: uiautomator2Command", Map.of("command", "device.getDisplayIds()"));
步骤2:针对副屏获取UI层级并定位元素
拿到副屏的display ID后,就可以调用UiAutomator2的接口dump该屏幕的UI层级,或者直接针对副屏定位元素:
- 方法A:dump副屏的UI层级树
String secondaryHierarchy = (String) driver.executeScript("mobile: uiautomator2Command", Map.of( "command", "device.dumpWindowHierarchy", "params", Map.of("displayId", 1) // 替换成你的副屏ID ));
你可以把这个层级内容保存成xml文件,用UiAutomatorViewer打开查看,或者自己解析里面的元素信息。
- 方法B:直接针对副屏定位元素
如果需要直接操作副屏元素,你可以在定位时指定display ID。不过Appium的默认定位API不支持直接传这个参数,你可以用UiAutomatorSelector的扩展方式,比如:
// 用UiAutomatorSelector定位副屏上的YouTube元素 MobileElement youtubeElement = (MobileElement) driver.findElement(MobileBy.AndroidUIAutomator( "new UiSelector().displayId(1).packageName(\"com.google.android.youtube\")" ));
注意这个displayId()方法是UiAutomator2新增的,需要确保你的Appium和UiAutomator2 Server版本是最新的(至少Appium 1.22+)。
方案2:修改UiAutomatorViewer源码(适合自定义需求)
如果需要用UiAutomatorViewer直观查看多屏幕内容,可以修改它的源码,让它支持枚举所有显示器:
- 下载Android SDK里UiAutomatorViewer的源码(路径一般是
$ANDROID_HOME/tools/lib/uiautomatorviewer.jar,可以反编译或者找开源的源码) - 找到负责dump UI层级的方法(比如
DumpWindowTask类),修改它的调用逻辑,遍历所有display ID,分别dump每个屏幕的层级 - 修改UI部分,添加切换显示器的选项,或者同时显示多个屏幕的层级树
这个方法需要一定的Java开发能力,但能完美解决UiAutomatorViewer只能看主屏的问题。
关键注意事项
- 确保模拟器的多显示器是扩展模式(Extend)而不是镜像模式(Mirror),镜像模式下副屏只是主屏的复制,系统不会把它当成独立显示器
- 尽量使用Android 10(API 29)及以上的模拟器,Android对多显示器的支持在这个版本后才更完善
- 保持Appium和UiAutomator2 Server的版本更新,旧版本可能没有完整的多显示器API支持
内容的提问来源于stack exchange,提问作者Christopher
相关产品推荐
相关产品推荐

