ADB 调试Pico头显设备:从连接到高效调试

# ADB 调试Pico头显设备:从连接到高效调试

> 参考文档: https://developer.android.com/studio/command-line/adb?hl=zh-cn

## (一) 工作原理

Android 调试桥 (adb) 是一种功能多样的命令行工具,可让您与设备进行通信。adb 命令可用于执行各种设备操作,例如安装和调试应用。adb 提供对 Unix shell(可用来在设备上运行各种命令)的访问权限。它是一种客户端-服务器程序,包括以下三个组件:

- **客户端**:用于发送命令。客户端在开发机器上运行。您可以通过发出 adb 命令从命令行终端调用客户端。
- **守护程序 (adbd)**:用于在设备上运行命令。守护程序在每个设备上作为后台进程运行。
- **服务器**:用于管理客户端与守护程序之间的通信。服务器在开发机器上作为后台进程运行。

当您启动某个 adb 客户端时,该客户端会先检查是否有 adb 服务器进程已在运行。如果没有,它会启动服务器进程。服务器在启动后会与本地 TCP 端口 5037 绑定,并监听 adb 客户端发出的命令。

> **注意**:所有 adb 客户端均使用端口 5037 与 adb 服务器通信。

然后,服务器会与所有正在运行的设备建立连接。它通过扫描 5555 到 5585 之间(该范围供前 16 个模拟器使用)的奇数号端口查找模拟器。服务器一旦发现 adb 守护程序 (adbd),便会与相应的端口建立连接。

每个模拟器都使用一对按顺序排列的端口:一个用于控制台连接的偶数号端口,另一个用于 adb 连接的奇数号端口。例如:

| 模拟器 | 控制台端口 | adb 端口 |
|--------|------------|----------|
| 模拟器 1 | 5554 | 5555 |
| 模拟器 2 | 5556 | 5557 |
| ... | ... | ... |

如上所示,在端口 5555 处与 adb 连接的模拟器与控制台监听端口为 5554 的模拟器是同一个。

服务器与所有设备均建立连接后,您便可以使用 adb 命令访问这些设备。由于服务器管理与设备的连接,并处理来自多个 adb 客户端的命令,因此您可以从任意客户端或从某个脚本控制任意设备。

---

## (二) adb 连接

有线设备连接:插线即可使用,具体步骤就不详细说明了。

### (1) adb 无线头显设备连接(针对 Android 10 及更低版本)

> 测试单台设备:Pico neo3 / Quest2

将头显设备(开发者选项已开)和 adb 主机电脑放置于同一个局域网里面。

#### 步骤一:使用 USB 线连接设备并检查连接

```powershell
E:\CloudXR\platform-tools> adb devices
* daemon not running; starting now at tcp:5037
* daemon started successfully
List of devices attached
PA7H10MGFA040034W device
```

#### 步骤二:获取设备的网络 IP

```powershell
E:\CloudXR\platform-tools> adb shell ip addr show wlan0
10: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 3000
link/ether 2c:4d:79:fe:42:49 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.244/24 brd 192.168.1.255 scope global wlan0
valid_lft forever preferred_lft forever
inet6 240e:379:20af:ae00:98a0:47cb:3eb9:d5b2/64 scope global temporary dynamic
valid_lft 250313sec preferred_lft 85766sec
inet6 240e:379:20af:ae00:b738:9b6:9417:cb67/64 scope global dynamic mngtmpaddr stable-privacy
valid_lft 250313sec preferred_lft 163913sec
inet6 fe80::485e:562c:9b4d:7298/64 scope link stable-privacy
valid_lft forever preferred_lft forever
```

#### 步骤三:设置头显设备 TCP/IP 连接的监听端口

```powershell
E:\CloudXR\platform-tools> adb tcpip 5555
restarting in TCP mode port: 5555
```

设置完毕后,可以拔除连接头显设备的 USB 线。

#### 步骤四:通过 IP 地址连接到头显设备

```powershell
E:\CloudXR\platform-tools> adb connect 192.168.1.244:5555
connected to 192.168.1.244:5555
```

#### 步骤五:确认连接状态

```powershell
E:\CloudXR\platform-tools> adb devices
List of devices attached
192.168.1.244:5555 device
```

头显设备已连接到 adb 主机。

#### 常见问题:连接断开

如果出现 adb 主机与头显设备的连接断开:

1. 确保主机仍与 Android 设备连接到同一 Wi-Fi 网络
2. 通过再次执行 adb connect 步骤重新连接

如果这样无法解决问题,请重置您的 adb 主机:

```bash
# 关闭 adb 服务
adb kill-server
# 启动 adb 服务
adb start-server
# 重试 adb 连接
adb connect 192.168.1.244:5555
```

然后,从头开始操作。

---

## (三) 普通型常用命令

### (1) 查询设备详情

日常查询设备的命令为 `adb devices`,查询设备详情的命令为 `adb devices -l`。

adb 会针对每个设备输出以下状态信息:

- **序列号**:adb 会创建一个字符串,用于通过端口号唯一标识设备。下面是一个序列号示例:`emulator-5554`
- **状态**:设备的连接状态可以是以下几项之一:
  - `offline`:设备未连接到 adb 或没有响应
  - `device`:设备已连接到 adb 服务器。请注意,此状态并不表示 Android 系统已完全启动并可正常运行,因为在设备连接到 adb 时系统仍在启动。系统完成启动后,设备通常处于此运行状态。
  - `no device`:未连接任何设备

> **说明**:如果您加入 `-l` 选项,devices 命令会告知您设备是什么。当您连接了多个设备时,此信息会很有用,方便您区分这些设备。

### (2) 多台设备连接主机 PC 时,如何发送命令给特定设备?

先获取设备信息,输入命令 `adb devices -l`,可以得到对应设备的设备号或者 IP。

使用 adb 命令结合 `-d` / `-e` / `-s` 来指定特定设备:

```bash
-d  使用USB设备(如果连接多个设备则出错)
-e  使用TCP/IP设备(如果有多个 TCP/IP 设备可用,则会出错)
-s  SERIAL 使用具有给定序列号的设备(覆盖 $ANDROID_SERIAL)
```

### (3) 给连接设备安装/卸载应用程序

#### 安装应用程序

```bash
adb install <附加参数> <APK路径>
```

**附加参数:**
- `-r`:替换已存在的应用程序,强制安装
- `-d`:允许降级安装
- `-t`:允许安装 debug 版测试包
- `-l`:锁定应用程序
- `-s`:将应用程序安装到 sd 卡上
- `-g`:安装后自动授予所有权限

> **注意**:`<APK路径>` 不能含有空格,若存在空格需使用英文引号 `"`

#### 卸载应用程序

```bash
adb uninstall <附加参数> <软件包名>
```

**附加参数:**
- `-k`:保留数据卸载

### (4) 接收/推送文件

- **推送**:通过 ADB 将电脑中的文件发送到头显
- **接收**:通过 ADB 将头显中的文件传输到电脑

```bash
adb push/pull <源路径> <目标路径>

# 推送:adb push <电脑路径> <设备路径>
# 接收:adb pull <设备路径> <电脑路径>
```

> **注意**:若推送的文件名中含有中文,需在 `<设备路径>` 中填入或指定文件名。

### (5) 其他常见命令

| 命令 | 说明 |
|------|------|
| `adb reboot` | 重启设备 |
| `adb reboot recovery` | 恢复出厂设置 |
| `adb reboot -p` | 关机 |
| `adb kill-server` | 停止 adb 服务器 |
| `adb --help` | 查询帮助文档 |

---

## (四) Shell 型常用命令

可以使用 shell 命令通过 adb 发出设备命令,也可以使用该命令启动交互式 shell。

- **方式①**: `adb [-d |-e | -s serial_number] shell shell_command`
- **方式②**: `adb [-d | -e | -s serial_number] shell`

如需退出交互式 shell,请按 `Control+D` 或输入 `exit`。

### (1) 日志查看 - logcat

如需通过 adb shell 运行 logcat,一般用法如下:

```bash
[adb] shell logcat [<option>] ... [<filter-spec>] ...
```

此外,还有一种 adb logcat 的简写形式,但它仅会扩展为 `adb shell logcat`。

> **选项**:logcat 提供了很多选项。具体有哪些可用选项取决于您使用的设备的操作系统版本。如需查看特定于所用设备的 logcat 帮助,请执行以下命令:
> ```bash
> adb logcat --help
> ```

> **注意**:由于 logcat 是面向操作系统开发者和应用开发者的工具(预计应用开发者会使用 Android Studio),因此许多选项只有在取得 root 权限的情况下才可使用。

#### 常用命令

```bash
# 直接打印 log 的详情日志
adb logcat -v time

# 把日志输出到电脑本地查看
adb logcat -v time > D:\log.txt

# 把过滤日志输出到电脑本地查看 (Windows)
adb logcat -v time | findstr "packageName" > D:\log.txt

# 把过滤日志输出到电脑本地查看 (Linux)
adb logcat -v time | grep 'packageName' > D:\log.txt

# 清除之前的日志信息(一般在看日志前都会执行这个命令)
adb logcat -c
```

#### 过滤规则

##### 日志级别过滤

```bash
adb logcat <tag>[:priority]
```

`tag` 表示感兴趣的标签,`priority` 表示输出的日志级别。

> **注意**:如果是要根据级别查看时 tag 必须指定内容,或者 tag 直接输入 `*` 号即可。

日志级别说明(默认级别为 V):

| 级别 | 说明 |
|------|------|
| V | 详细(最低优先级) |
| D | 调试 |
| I | 信息 |
| W | 警告 |
| E | 错误 |
| F | 严重错误 |
| S | 静默(最高优先级,绝不会输出任何内容) |

**举例**:比如查看头显设备级别为 Error 的日志

```bash
adb logcat *:E
```

##### tag 级别过滤

查看手机日志的 tag:

```bash
adb logcat -v tag
###########################
I/JNI_PART: PC_Services: 20230828B_For_Neo3_5.3.0
I/JNI_PART: SENSOR version: SENSOR 1.0.0.184 d123329
I/JNI_PART: PClog_StatusInfo:12631.615377,Static:5,OutDoor:0,BrightNessCam3:3.944271,Frq:60.000000,pid:961,cpu:7
W/JNI_PART: PC3_Calib_Pata_Wrong_No_Calib:left 0, right 1
```

输出后格式会是:`<priority>/<tag>: <message>`

```bash
adb logcat JNI_PART:I
```

##### 使用管道进程来查看日志

```bash
# Linux 系统
adb logcat | grep packageName >> log.txt

# Windows 系统
adb logcat | findstr packageName >> log.txt
```

### (2) 性能查看 - dumpsys

> **参考文档**:https://developer.android.com/tools/dumpsys?hl=zh#ui

> **注意事项**:所有 dumpsys 命令获取性能数据,如果 adb shell 进入终端执行,均要求执行有 shell 权限,如果 PC 端进入终端执行,则无此要求。

```bash
# 查看设备当前运行进程的资源使用信息
adb shell top

# 持续监视,每隔一秒输出当前 CPU 占用最高的 10 个进程的信息
adb shell top -m 10 -s

# 查看当前运行的进程
adb shell ps
```

### (3) 截图录屏

#### 截图操作

screencap 命令是一个用于对设备显示屏截取屏幕截图的 shell 实用程序。

```bash
# 截取屏幕截图
adb shell screencap /sdcard/screen.png

# 将设备的屏幕截图拉取到本地电脑
adb pull /sdcard/screen.png <目标路径>
```

#### 录屏操作

screenrecord 命令是一个用于录制设备(搭载 Android 4.4 [API 级别 19] 及更高版本)显示屏的 shell 实用程序。该实用程序将屏幕 activity 录制为 MPEG-4 文件。您可以使用此文件创建宣传视频或培训视频,或将其用于调试或测试。

```bash
# 开始录屏
adb shell screenrecord /sdcard/demo.mp4

# 结束录屏(按 Ctrl + C)
# 在 macOS 中,按 Command+C

# 将设备的录屏文件拉取到本地电脑
adb pull /sdcard/demo.mp4 <目标路径>
```

按 `Ctrl+C`(在 macOS 中,按 `Command+C`)可停止屏幕录制。否则,到三分钟或 `--time-limit` 设置的时间限制时,录制会自动停止。

screenrecord 实用程序能以您要求的任何支持的分辨率和比特率进行录制,同时保持设备显示屏的宽高比。默认情况下,该实用程序以本机显示分辨率和屏幕方向进行录制,时长不超过三分钟。

**screenrecord 实用程序的局限性:**

- 音频不与视频文件一起录制。
- 无法在搭载 Wear OS 的设备上录制视频。
- 某些设备可能无法以它们的本机显示分辨率进行录制。如果在录制屏幕时出现问题,请尝试使用较低的屏幕分辨率。
- 不支持在录制时旋转屏幕。如果在录制期间屏幕发生了旋转,则部分屏幕内容在录制时将被切断。

**screenrecord 命令选项:**

| 选项 | 说明 |
|------|------|
| `--help` | 显示命令语法和选项 |
| `--size widthxheight` | 设置视频大小:1280x720。默认值为设备的本机显示屏分辨率(如果支持);如果不支持,则为 1280x720。为获得最佳效果,请使用设备的 Advanced Video Coding (AVC) 编码器支持的大小。 |
| `--bit-rate rate` | 设置视频的视频比特率(以 MB/秒为单位)。默认值为 4Mbps。您可以增加比特率以提升视频质量,但这样做会导致视频文件变大。以下示例将录制比特率设为 6Mbps:`screenrecord --bit-rate 6000000 /sdcard/demo.mp4` |
| `--time-limit time` | 设置最长录制时间(以秒为单位)。默认情况下,最大值为 180(3 分钟)。 |
| `--rotate` | 将输出旋转 90 度。此功能处于实验阶段。 |
| `--verbose` | 在命令行屏幕显示日志信息。如果您不设置此选项,则该实用程序在运行时不会显示任何信息。 |

### (4) 其他命令

#### 1. 调用 Activity 管理器

活动(Activity):可理解为 App 的各个界面的名称,类似 Windows 中的窗口,Android 软件可通过 Activity 直接跳转到指定的界面而无需经过启动界面。

> **参考文档**:https://developer.android.com/tools/adb?hl=zh#am

```bash
# 启动某个 APP 服务
adb shell am start <package>/<activity>

# 强行停止 package 相关的进程
adb shell am force-stop <package>

# 终止与 package 关联的所有进程(此命令仅终止可安全终止且不会影响用户体验的进程)
adb shell am kill [<options>] <package>

# 终止所有后台进程
adb shell am kill-all
```

> **注意**:若活动名中含有包名,包名也可使用 `.` 替代。

#### 2. 调用软件包管理器 (pm)

在 adb shell 中,您可以使用软件包管理器 (pm) 工具发出命令,以对设备上安装的应用软件包执行操作和查询。

> **参考文档**:https://developer.android.com/tools/adb?hl=zh#pm

##### 输出软件包列表

```bash
adb shell pm list packages [options] [filter]
```

输出所有软件包,或者视需要仅输出软件包名称包含 filter 中文字的软件包。

**具体选项:**
- `-f`:查看关联文件
- `-d`:进行过滤以仅显示已停用的软件包
- `-e`:进行过滤以仅显示已启用的软件包
- `-s`:进行过滤以仅显示系统软件包
- `-3`:进行过滤以仅显示第三方软件包
- `-i`:查看软件包的安装程序
- `-u`:包括已卸载的软件包
- `--user user_id`:要查询的用户空间

```bash
# 查看含有"android"字段的应用的包名
adb shell pm list packages android
```

##### 将软件包(通过 path 指定)安装到系统

```bash
adb shell pm install [options] <path>
```

**具体选项:**
- `-r`:重新安装现有应用,并保留其数据
- `-t`:允许安装测试 APK。仅当您运行或调试了应用或者使用了 Android Studio 的 Build > Build APK 命令时,Gradle 才会生成测试 APK。如果是使用开发者预览版 SDK 构建的 APK,那么安装测试 APK 时必须在 install 命令中包含 `-t` 选项
- `-i installer_package_name`:指定安装程序软件包名称
- `--install-location location`:使用以下某个值设置安装位置:
  - `0`:使用默认安装位置
  - `1`:在设备内部存储空间中安装
  - `2`:在外部介质上安装
- `-f`:在内部系统内存上安装软件包
- `-d`:允许版本代码降级
- `-g`:授予应用清单中列出的所有权限
- `--fastdeploy`:通过仅更新已更改的 APK 部分来快速更新安装的软件包
- `--incremental`:仅安装 APK 中启动应用所需的部分,同时在后台流式传输剩余数据。如要使用此功能,您必须为 APK 签名,创建一个 APK 签名方案 v4 文件,并将此文件放在 APK 所在的目录中。只有部分设备支持此功能。此选项会强制 adb 使用该功能,如果该功能不受支持,则会失败,并提供有关失败原因的详细信息。附加 `--wait` 选项,可等到 APK 完全安装完毕后再授予对 APK 的访问权限
- `--no-incremental` 可阻止 adb 使用此功能

##### 从系统中移除软件包

```bash
adb shell pm uninstall [options] <package>
```

**具体选项:**
- `-k`:移除软件包后保留数据和缓存目录
- `--user user_id`:指定要为哪位用户移除软件包
- `--versionCode version_code`:仅在应用具有给定的版本代码时卸载

##### 删除与软件包关联的所有数据

```bash
adb shell pm clear <package>
```

#### 3. 设置头显息屏时长

在命令行窗口中,输入下面的命令:

```bash
# 设置屏幕常亮
adb shell settings put system screen_off_timeout 0
```

这会将屏幕超时设置为 0,因此屏幕将保持常亮状态。

如果您想恢复默认设置,可以输入下面的命令:

```bash
# 恢复默认设置(15秒)
adb shell settings put system screen_off_timeout 15000
```

#### 4. 其他命令

```bash
# -----------设备信息查看---------------------
# 查看设备CPU架构和内核个数
adb shell cat /proc/cpuinfo

# 查看系统的详细内存信息
adb shell cat /proc/meminfo

# 获取设备磁盘空间
adb shell df

# 获取机器MAC地址
adb shell cat /sys/class/net/wlan0/address

# 获取设备系统版本
adb shell getprop ro.build.version.release

# ----------------进程查看---------------------
# 各进程内存使用情况
adb shell procrank

# 查看应用的进程信息
adb shell ps | grep <packageName>

# 杀死进程
adb shell kill <pid>

# ------------------文件操作-----------------------
# 移动文件/文件夹
adb shell mv <path>/<file> <newpath>/<file>

# 新建文件夹
adb shell mkdir <path>

# 新建文件
adb shell touch <filename>

# 重命名文件
adb shell rename <path>/<filename> <newpath>/<newFilename>

# 查看文件内容
adb shell cat <file>
```

---

## (五) 问题补充

(待补充)

评论