问题1: android 通过adb获取某个window的画面
追问:不要用screencap,需要dump没显示或显示一部分内容的window画面
追问:monitor工具里,hierarchy view可以看到一些window的画面,可以通过adb实现吗
回答如下:
是的!Android Studio 的 hierarchy view 实际上是通过 ViewServer 和 Dump View Hierarchy 功能实现的。可以通过 adb 来实现类似的功能。
1. 基础方法:使用 adb shell dumpsys activity
bash
# 获取当前最顶层的 Activity 视图信息
adb shell dumpsys activity top
# 获取特定 Activity 的视图层次
adb shell dumpsys activity activities | grep -A 10 "ActivityRecord"
# 获取所有窗口信息
adb shell dumpsys window
2. 使用 uiautomator dump
这个命令可以获取当前屏幕的 XML 视图层次,类似于 hierarchy view:
bash
# 获取当前屏幕的 UI 层次结构(XML格式)
adb shell uiautomator dump /sdcard/window_dump.xml
# 拉取到本地
adb pull /sdcard/window_dump.xml
# 实时查看(配合 adb shell)
adb shell uiautomator dump && adb shell cat /sdcard/window_dump.xml
更高效的组合命令:
bash
adb shell uiautomator dump /dev/tty
3. 通过 adb shell dumpsys SurfaceFlinger 获取图层信息
bash
# 列出所有图层
adb shell dumpsys SurfaceFlinger --list
# 获取特定图层的详细信息
adb shell dumpsys SurfaceFlinger --display-id 0
# 对于系统应用,可以尝试截取特定应用的图层
adb shell dumpsys SurfaceFlinger --screenshot --display-id 0 --app <package_name>
4. 使用 adb shell dumpsys window 的高级用法
bash
# 获取所有窗口的详细信息
adb shell dumpsys window windows
# 获取特定窗口的信息(需要知道窗口 token)
adb shell dumpsys window windows | grep -A 20 "Window #"
# 获取窗口的 visible/invisible 状态
adb shell dumpsys window visible-apps
# 获取 Surface 信息
adb shell dumpsys window surfaces
5. 结合 adb 和 ViewServer(类似 hierarchy view)
bash
# 启用 ViewServer(需要设备有开发者选项)
adb shell service call window 3 i32 4939
# 连接到 ViewServer(需要网络连接)
adb forward tcp:4939 tcp:4939
# 使用 telnet 或 nc 获取数据
telnet localhost 4939
# 连接后可以发送命令:
# LIST - 列出所有窗口
# DUMP [id] - 获取指定窗口的视图层次
6. 自动化脚本示例
创建一个 Python 脚本来获取窗口层次:
python
#!/usr/bin/env python3
import subprocess
import xml.etree.ElementTree as ET
import sys
def get_ui_hierarchy():
# 执行 uiautomator dump
subprocess.run(["adb", "shell", "uiautomator", "dump", "/sdcard/ui_dump.xml"])
# 拉取 XML 文件
subprocess.run(["adb", "pull", "/sdcard/ui_dump.xml", "."])
# 解析 XML
tree = ET.parse('ui_dump.xml')
root = tree.getroot()
# 分析窗口结构
for node in root.iter('node'):
if 'package' in node.attrib:
print(f"包名: {node.attrib.get('package')}")
print(f"类名: {node.attrib.get('class')}")
print(f"文本: {node.attrib.get('text', '')}")
print(f"坐标: {node.attrib.get('bounds', '')}")
print("-" * 40)
if __name__ == "__main__":
get_ui_hierarchy()
7. 获取特定应用/窗口的视图
bash
# 先获取当前焦点窗口
adb shell dumpsys window | grep mCurrentFocus
# 获取特定应用的窗口信息
adb shell dumpsys window | grep -B 5 -A 10 "com.example.app"
# 使用 --dump 参数获取更详细的信息
adb shell dumpsys activity --dump <package_name>
8. 结合多个命令的实用示例
bash
#!/bin/bash
# 获取当前前台应用的窗口信息
# 1. 获取包名
package=$(adb shell dumpsys window | grep mCurrentFocus | awk -F'[/ ]' '{print $5}')
# 2. 获取 Activity 名
activity=$(adb shell dumpsys window | grep mCurrentFocus | awk -F'[/ ]' '{print $6}' | tr -d '}')
# 3. 获取视图层次
echo "包名: $package"
echo "Activity: $activity"
echo "获取视图层次..."
adb shell uiautomator dump --compressed /sdcard/view.xml
# 4. 获取窗口边界
bounds=$(adb shell dumpsys window | grep -A 10 "$activity" | grep "mBounds")
echo "窗口边界: $bounds"
9. 使用 ADB 获取 Window 属性的完整流程
bash
# 步骤 1: 获取所有窗口的层级
adb shell dumpsys window | grep -E "Window #|mCurrentFocus|package="
# 步骤 2: 获取 SurfaceFlinger 的图层信息
adb shell dumpsys SurfaceFlinger | grep -A 5 -B 5 "Layer"
# 步骤 3: 获取 Activity 栈信息
adb shell dumpsys activity activities | grep -A 20 "Hist"
# 步骤 4: 获取 View 的布局信息(需要应用支持)
adb shell am instrument -w -e class com.android.test.InstrumentationTestRunner
10. 注意事项
-
权限要求:
- 大部分命令不需要特殊权限
- 某些命令需要
android.permission.DUMP - 生产版本的应用可能限制信息泄露
-
性能影响:
uiautomator dump可能导致界面卡顿- 建议在非生产环境下使用
-
版本兼容性:
- Android 4.3+ 支持
uiautomator dump - Android 5.0+ 提供更详细的窗口信息
- Android 10+ 对窗口管理有较大变化
- Android 4.3+ 支持
11. 推荐工具链
bash
# 组合使用多个工具
# 1. 使用 hierarchyviewer 的替代品
pip install uiautomator2
# 2. 使用 Python 脚本获取和分析
python -m uiautomator2 init
adb shell uiautomator2 dump
# 3. 使用 weditor 查看(类似 hierarchy view)
weditor
这些方法虽然不能直接获取完整的位图图像(像 hierarchy view 那样显示每个 View 的预览),但可以获取窗口的完整结构信息,包括:
- View 的层次结构
- 每个 View 的属性和边界
- 窗口的可见性状态
- Surface 的图层信息
对于需要实际图像的情况,你可能需要结合前面提到的截图方法,或者使用专门的测试框架如 Appium、Espresso 等。