OpenHarmony 分布式设备管理基本用法

本文介绍 OpenHarmony 分布式组网的核心入口 DeviceManager 的基本用法,覆盖组件架构、核心 API、代码实战与常见问题,帮助开发者快速实现设备发现、PIN 码认证与跨设备交互。

flowchart LR
    A[创建DeviceManager实例] --> B[注册设备状态监听]
    B --> C[获取可信设备列表]
    C --> D[扫描发现周边设备]
    D --> E[PIN码配对认证]
    E --> F[设备加入可信列表]
    F --> G[跨设备拉起Ability]
    G --> H[分布式数据交互]

一、核心概述

1.1 能力定位

OpenHarmony 所有分布式能力(分布式相机、分布式屏幕、分布式数据管理、跨设备拉起应用等)的前置基础是设备配对与鉴权组网,所有跨设备交互必须建立在可信设备组网的基础上。

1.2 核心组件:DeviceManager(设备管理模块)

DeviceManager 是鸿蒙分布式组网的核心入口,具备无账号依赖的设备组网能力,是开发者实现设备发现、设备监听、设备认证、跨设备交互的核心工具。

核心能力 说明
设备上下线监听 on('deviceStateChange') 实时感知设备状态
周边设备发现 扫描同一网络下的可信/不可信设备
设备 PIN 码鉴权 系统原生配对认证,无需自研页面
可信设备管理 认证通过设备持久化保存,直接获取列表

1.3 完整核心工作流程

创建DeviceManager实例
 └─ 注册设备状态监听
     └─ 获取本地可信设备列表
         └─ 扫描发现周边设备
             └─ PIN码配对认证
                 └─ 设备加入可信列表
                     └─ 跨设备拉起Ability / 分布式交互

二、DeviceManager 组件架构

2.1 源码核心路径

foundation/distributedhardware/devicemanager

2.2 核心目录及功能说明

foundation/distributedhardware/devicemanager
 ├─ common/                      ← 公共头文件、通用工具类
 ├─ display/                     ← PIN码显示HAP页面JS代码
 ├─ interfaces/
 │   ├─ inner_kits/              ← 系统内部接口(Native、IPC、消息通知)
 │   └─ kits/                    ← 对外暴露的JS API(核心接口层)
 └─ services/
     ├─ devicemanagerservice/    ← 设备管理核心服务
     ├─ ability/                 ← PIN码显示FA拉起与生命周期管理
     ├─ auth/                    ← 设备配对认证交互逻辑
     ├─ ipc/                     ← 跨进程通信
     ├─ message/                 ← 设备交互消息解析封装
     ├─ requestauth/             ← 设备认证请求核心逻辑
     ├─ softbus/                 ← 对接分布式软总线
     └─ timer/                   ← 扫描超时、心跳、认证超时定时器

三、核心 API 速查手册(API 9)

3.1 实例管理接口

API 方法 功能说明
createDeviceManager(bundleName, callback) 异步创建设备管理实例,所有分布式操作的前置入口
release() 释放 DeviceManager 实例,销毁监听与任务

3.2 设备状态与监听接口

API 方法 功能说明
getTrustedDeviceListSync() 同步获取当前系统中所有已配对的可信设备列表
on('deviceStateChange', cb) 监听设备上线、下线状态变更事件
on('serviceDie', cb) 监听设备管理服务异常退出、崩溃回调,用于异常兜底

3.3 设备发现与认证接口

API 方法 功能说明
startDeviceDiscovery(info) 开启周边设备扫描,需传入唯一 subscribeId
stopDeviceDiscovery(subscribeId) 停止设备扫描,必须与开启接口成对调用
authenticateDevice(device, param, cb) 发起设备 PIN 码认证,配对陌生设备
on('deviceFound', cb) 扫描到周边设备的结果回调
on('discoverFail', cb) 设备扫描失败、超时、权限不足的失败回调

重要注意事项:startDeviceDiscovery 与 stopDeviceDiscovery 必须成对使用,且全程共用同一个 subscribeId,否则会出现扫描残留、无法停止等问题。

四、核心代码实战(Stage 模型 + API 9)

4.1 初始化 DeviceManager 实例

在页面 aboutToAppear 生命周期中初始化,全局仅需创建一次:

async createDeviceManager() {
  // 获取当前应用包名
  let bundleName = await globalThis.context.abilityInfo.bundleName;
  // 创建设备管理实例
  deviceManager.createDeviceManager(bundleName, (err, dm) => {
    if (!dm) return;
    this.deviceManager_ = dm;
    // 监听设备上下线状态变化
    dm.on("deviceStateChange", data => {
      let device = data.device;
      this.trustedDeviceList = [{ ...device }];
      this.deviceFoundList = [];
    });
    // 监听服务异常退出
    dm.on("serviceDie", () => {
      console.log("设备管理服务异常退出");
    });
    // 初始化获取本地可信设备列表
    let array = dm.getTrustedDeviceListSync();
    if (array?.length) {
      this.trustedDeviceList = [...array];
    }
  });
}

4.2 周边设备扫描(开启/停止)

前置条件:设备连接同一 WiFi 网络。

// 开启设备发现
startDeviceDiscovery() {
  // 监听发现设备回调
  this.deviceManager_.on('deviceFound', (data) => {
    console.log("发现设备: ", data.device);
  });
  // 监听扫描失败回调
  this.deviceManager_.on('discoverFail', (data) => {
    console.log("设备发现失败: ", data);
  });
  // 生成唯一订阅ID
  this.subscribeId = Math.floor(Math.random() * 10000 + 1000);
  // 扫描参数配置
  var info = {
    "subscribeId": this.subscribeId,
    "mode": 0xAA,
    "medium": 0,
    "freq": 2,
    "isSameAccount": false,
    "isWakeRemote": true,
    "capability": 0
  };
  // 启动扫描
  this.deviceManager_.startDeviceDiscovery(info);
}

// 停止设备发现
stopDeviceDiscovery() {
  // 传入对应订阅ID停止扫描
  this.deviceManager_.stopDeviceDiscovery(this.subscribeId);
}

4.3 PIN 码设备认证

系统自动弹出 PIN 码弹窗,远端设备展示 6 位 PIN 码,本地设备输入验证,认证通过后设备加入可信列表:

authenticateDevice(device, authParam) {
  this.deviceManager_.authenticateDevice(device, authParam, (error, data) => {
    if (!error) {
      console.log("设备认证成功");
    } else {
      console.log("设备认证失败: ", error);
    }
  });
}

4.4 权限配置与动态申请

分布式交互必备权限:ohos.permission.DISTRIBUTED_DATASYNC

1. 模块声明权限(config.json)

{
  "requestPermissions": [
    { "name": "ohos.permission.DISTRIBUTED_DATASYNC" }
  ]
}

2. 动态申请权限代码

async requestPermissions(permissions) {
  const appInfo = await bundle.getApplicationInfo(await this.getBundleName(), 0, 100);
  let tokenId = appInfo.accessTokenId;
  let atManager = abilityAccessCtrl.createAtManager();
  // 校验权限是否已授予
  let results = await Promise.all(
    permissions.map(p => atManager.verifyAccessToken(tokenId, p))
  );
  // 筛选未授予权限并发起申请
  let requestList = permissions.filter((_, i) =>
    results[i] == abilityAccessCtrl.GrantStatus.PERMISSION_DENIED
  );
  if (requestList.length > 0) {
    await this.context.requestPermissionsFromUser(requestList);
  }
}

4.5 跨设备远程拉起 Ability

认证组网成功后,可通过 want 参数指定远端设备,拉起对应应用并传参。

1. 主动拉起端代码

connectStageAbility(device) {
  var want = {
    "deviceId": device.deviceId,                              // 目标远端设备ID
    "bundleName": "com.example.myapplication_distributeddevicemanager", // 目标应用包名
    "abilityName": "MainAbility",                             // 目标页面Ability名
    parameters: { content: "来自远程设备" }                    // 跨设备传递参数
  };
  // 发起远程拉起
  globalThis.context.startAbility(want);
}

2. 远端接收端代码

aboutToAppear() {
  // 接收远程传参
  let parameter = globalThis.content;
  if (parameter) {
    AlertDialog.show({
      title: '当前应用被远程启动',
      message: parameter.content
    });
  }
  // 初始化设备管理能力
  this.createDeviceManager();
}

五、开发前置必备条件

环境/配置项 具体要求
系统版本 OpenHarmony 3.1 Release 及以上
API 版本 API 9(适配 Stage 应用模型)
网络环境 参与组网的设备必须连接同一 WiFi
必备权限 ohos.permission.DISTRIBUTED_DATASYNC(需动态申请)
认证方式 系统原生 PIN 码配对认证,无需自定义页面
设备数量 至少 2 台 OpenHarmony 设备用于联调测试

六、核心学习重难点总结

序号 重难点 说明
1 核心入口唯一性 DeviceManager 是所有分布式能力的唯一前置入口,所有跨设备操作必须先创建并初始化实例
2 固定组网三步曲 设备发现 → PIN码认证 → 可信组网,顺序不可颠倒,未认证设备无法进行跨设备交互
3 极简认证机制 PIN 码配对弹窗、校验逻辑均为系统预置,开发者仅需调用认证 API 即可
4 可信设备持久化 认证通过的设备会被系统持久化保存,后续无需重复配对,可直接获取可信列表
5 权限硬性要求 跨设备拉起、分布式数据同步必须申请 DISTRIBUTED_DATASYNC 权限
6 跨设备传参规则 通过 want.parameters 传递自定义参数,远端页面在 aboutToAppear 中接收解析
7 扫描接口规范 设备启停扫描必须成对、共用同一 subscribeId,避免内存泄漏和扫描任务残留

七、常见问题小结

问题现象 排查要点
扫描不到设备 检查设备是否同 WiFi、权限是否开启、扫描参数是否合法、是否未停止上一次扫描任务
认证失败 核对 PIN 码、设备网络连通性、系统分布式开关是否开启
无法远程拉起应用 检查权限是否授予、包名/Ability 名是否匹配、设备是否在可信列表中
服务异常退出 页面销毁时及时调用 release() 释放实例,避免监听残留导致异常

八、完整交互时序图

sequenceDiagram
    participant App as 应用(App)
    participant DM as DeviceManager服务
    participant Peer as 远端设备

    App->>DM: createDeviceManager(bundleName)
    App->>DM: on('deviceStateChange')
    App->>DM: getTrustedDeviceListSync()
    App->>DM: startDeviceDiscovery(info)
    DM-->>App: on('deviceFound') 发现设备
    App->>DM: stopDeviceDiscovery(subscribeId)
    App->>DM: authenticateDevice(device, param)
    DM->>Peer: PIN码配对认证
    Peer-->>DM: 认证通过
    DM-->>App: 认证成功回调
    App->>Peer: startAbility(want) 跨设备拉起
    Peer-->>App: 远程应用启动并接收参数

欢迎加入Laval社区

社区规范:仅讨论OpenHarmony相关问题。

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐