DevEco CLI 工具链实战(5):设备管理 device

系列: DevEco CLI 工具链实战 · 第 5 篇


引言

devecocli device 看似简单------只有 listview 两个子命令------但它是 runlog 等命令的基础设施。理解 DeviceManager 的发现引擎、属性获取方式和设备类型覆盖机制,有助于排查设备连接问题。

本文将带你掌握:

  • device list / device view 的使用与输出
  • ✅ DeviceManager 发现引擎的工作原理
  • ✅ hdc 交互细节与设备类型覆盖

核心实现

Step 1: device list

目标: 列出当前活跃的设备

bash 复制代码
devecocli device list

输出示例:

复制代码
Name              Serial             Kind       Device Type
───────────────── ────────────────── ────────── ────────────
HUAWEI Mate 70    SGDUV12345678901   device     phone
Pixel_8_API_26    127.0.0.1:5555     emulator   phone
字段 说明
Name 设备名称(真机为型号,模拟器为实例名)
Serial 序列号(真机为设备序列号,模拟器为 127.0.0.1:<port>
Kind device(真机)或 emulator(模拟器)
Device Type 产品形态:phone / tablet / wearable / tv / 2in1 等

说明 : device list 仅显示当前活跃 设备。要查看所有模拟器实例(含已停止的),使用 devecocli emulator list

Step 2: device view

目标: 查看设备详细信息

bash 复制代码
# 单设备环境
devecocli device view

# 多设备环境(必须 -t 指定)
devecocli device view -t SGDUV12345678901
devecocli device view -t 127.0.0.1:5555

输出包含:序列号、设备名称、设备类型、操作系统版本等。

Step 3: DeviceManager 发现引擎

目标: 理解设备发现的底层机制

typescript 复制代码
// src/service/device-manager.ts (简化)
export class DeviceManager {
  static async listDevices(): Promise<ConnectedDeviceEntry[]> {
    // 1. hdc list targets → 获取所有连接的序列号
    const targets = await execa(hdcPath, ['list', 'targets']);

    // 2. 对每个序列号,批量获取设备属性
    const entries = await Promise.all(
      targets.map(serial => this.queryDeviceProperties(serial))
    );

    // 3. 区分真机与模拟器(模拟器序列号匹配 127.0.0.1:*)
    // 4. 用 emulator list 覆盖模拟器的 deviceType
    return entries;
  }
}

发现流程:

  1. hdc list targets ------ 获取所有已连接设备的序列号
  2. hdc shell param get ------ 批量获取设备属性(名称、类型、OS 版本)
  3. 模拟器识别 ------ 序列号匹配 127.0.0.1:* 的为模拟器
  4. 设备类型覆盖 ------ 用 emulator list 的信息覆盖模拟器的 deviceType

Step 4: hdc shell param get 批量属性

目标: 理解设备属性获取方式

typescript 复制代码
// src/utils/hdc-param.ts (简化)
export class HdcParam {
  // 单个属性获取
  static async get(serial: string, key: string): Promise<string>;

  // 批量属性获取(减少 hdc 调用次数)
  static async getBatch(serial: string, keys: string[]): Promise<Record<string, string>>;
}

获取的关键属性:

参数 Key 用途
const.secure.prod.name 设备产品名称
const.secure.dev.type 设备类型
hw_sc.build.os.version 操作系统版本

说明 : hdc shell param get 有时会返回 "channel-still-establishing" 等连接建立中的信息,HdcParam 会自动重试。

Step 5: 模拟器设备类型覆盖

目标: 理解为什么模拟器的 deviceType 需要覆盖

hdc shell param get 返回的模拟器 deviceType 可能不准确(如所有模拟器都返回 phone)。DeviceManager 会调用 emulator list 获取模拟器的真实 deviceType,并用 applyEmulatorDeviceTypeOverrides() 覆盖:

typescript 复制代码
// src/commands/device.ts (简化)
function applyEmulatorDeviceTypeOverrides(
  entries: ConnectedDeviceEntry[],
  emulatorDeviceTypeByName: Map<string, string>
): void {
  for (const entry of entries) {
    if (entry.isEmulator && entry.name) {
      const fine = emulatorDeviceTypeByName.get(entry.name);
      if (fine) entry.deviceType = fine;  // 覆盖为真实类型
    }
  }
}

这确保了 device list 中模拟器的 Device Type 准确反映其配置(phone / tablet / wearable / tv 等)。

关键指令

  • device list 展示活跃设备,区分真机与模拟器
  • device view 查看详细信息
  • DeviceManager 通过 hdc 自动发现设备并获取属性
  • 模拟器 deviceType 通过 emulator list 覆盖,确保准确

关键代码解读

TextTable ------ 固定宽度表格

typescript 复制代码
// src/utils/text-table.ts (简化)
export function renderTable(headers: string[], rows: TableRow[]): string {
  // 计算每列最大宽度
  // 对齐填充
  // 返回格式化字符串
}

device listemulator listemulator image list 都使用 TextTable 渲染输出。

常见问题排查

问题 原因 解决方案
No active devices 无设备连接 连接真机或启动模拟器
设备名称显示为序列号 param get 失败 检查 hdc 连接,重启 hdc
模拟器 deviceType 不准确 覆盖逻辑未生效 检查 emulator list 输出

总结

  1. device list 显示活跃设备(真机 + 运行中模拟器),device view 查看详情
  2. DeviceManager 通过 hdc list targets 发现设备,hdc shell param get 批量获取属性
  3. 模拟器识别 :序列号匹配 127.0.0.1:*,deviceType 通过 emulator list 覆盖
  4. 多设备时 device view-t 指定,run / log--device 指定

下篇预告

第 6 篇 : 模拟器全生命周期 emulator ------ 深入 devecocli emulator 的 9 个子命令:实例管理、系统镜像、虚拟设备与许可证。