鸿蒙 ArkTS 分布式设备管理实战:从发现设备到跨端协同全攻略
前言
2026 年,鸿蒙 NEXT 的分布式能力已经成为中高端应用的标配。想象一下:手机扫码、平板预览、手表震动——三个设备无缝接力完成一个任务。这种「设备合体」体验,正是分布式设备管理带来的革命。
但很多开发者在实际项目中遇到这些问题:
- 设备发现失败,DiscoveryAgent 怎么配都不生效
- 跨设备调用报 401/116 错误,不知道哪里配错了
- 想做一个"手机控制电视"的 demo,却不知道从哪下手
今天这篇文章,用一个智能家居控制中枢的完整实战,带你彻底搞懂鸿蒙的分布式设备管理。
一、分布式架构核心概念
1.1 设备管理三层架构
鸿蒙的分布式设备管理分为三层:
本文聚焦设备发现层,这是所有分布式能力的基础。
1.2 设备类型与权限体系
// 设备类型枚举enum DeviceType { DEVICE_TYPE_PHONE = 0x00, // 手机 DEVICE_TYPE_TABLET = 0x01, // 平板 DEVICE_TYPE_TV = 0x02, // 智慧屏 DEVICE_TYPE_Wearable = 0x06, // 智能手表 DEVICE_TYPE_CAR = 0x09, // 车机 DEVICE_TYPE_OTHER = 0xFF // 其他设备}// 设备可信状态enum TrustDeviceFlag { FLAG_DEFAULT = 0, // 仅同华为账号设备 FLAG_ABILITY = 1, // 同应用设备 FLAG_ALL = 2 // 所有设备}
关键点:分布式能力需要设备间建立信任关系。同华为账号自动信任,同应用通过 bindTarget 建立临时信任。
二、项目实战:智能家居控制中枢
2.1 项目结构
entry/src/main/ets/├── entryability/│ └── EntryAbility.ets // 应用入口├── pages/│ └── Index.ets // 主控制页面├── model/│ ├── DeviceManager.ts // 设备管理封装│ ├── HomeDevice.ets // 家居设备数据模型│ └── RemoteService.ets // 跨设备服务调用└── utils/ └── Logger.ts // 日志工具
2.2 权限配置
首先在 module.json5 中声明权限:
{ "module": { "requestPermissions": [ { "name": "ohos.permission.DISTRIBUTED_DEVICE_INFO_ACCESS", "reason": "string:network_reason" } ] }}
2.3 家居设备数据模型
// HomeDevice.ets - 智能家居设备模型// 支持空调、灯、窗帘、门锁四类设备// 设备类型export enum DeviceCategory { AC = 'air_conditioner', LIGHT = 'light', CURTAIN = 'curtain', LOCK = 'smart_lock'}// 设备状态export interface DeviceState { online: boolean; powerOn?: boolean; // 空调/灯 temperature?: number; // 空调温度 (16-30°C) brightness?: number; // 灯光亮度 (0-100) curtainLevel?: number; // 窗帘开度 (0-100) locked?: boolean; // 门锁状态}// 家居设备export class HomeDevice { deviceId: string; deviceName: string; deviceType: DeviceCategory; state: DeviceState; constructor( deviceId: string, deviceName: string, deviceType: DeviceCategory, state: DeviceState ) { this.deviceId = deviceId; this.deviceName = deviceName; this.deviceType = deviceType; this.state = state; } // 获取设备图标 getIcon(): ResourceStr { switch (this.deviceType) { case DeviceCategory.AC: return r('app.media.ic_light'); case DeviceCategory.CURTAIN: return r('app.media.ic_locked') : r('app.media.ic_device'); } }}
三、设备管理核心封装
3.1 设备发现服务
// DeviceManager.ts - 分布式设备管理封装import deviceManager from '@ohos.distributedDeviceManager';import bundle from '@ohos.bundle.bundleManager';import hilog from '@ohos.hilog';// 日志域 IDconst DOMAIN_ID = 0xFF00;const TAG = 'DeviceManagerService';export class DeviceManagerService { private dmInstance: deviceManager.DeviceManager | null = null; private deviceList: deviceManager.DeviceBasicInfo[] = []; private stateCallback: ((devices: deviceManager.DeviceBasicInfo[]) => void) | null = null; // 初始化设备管理实例 async init(): Promise<void> { try { // 获取本地设备的 bundleName(用于匿名设备管理) const bundleName = await bundle.getBundleNameForUid(AppStorage.get('uid') || 1000); // 创建设备管理实例 this.dmInstance = deviceManager.createDeviceManager(bundleName); hilog.info(DOMAIN_ID, TAG, 'DeviceManager initialized successfully'); // 注册设备状态监听 this.registerDeviceStateCallback(); } catch (err) { hilog.error(DOMAIN_ID, TAG, `Init failed: {(err as Error).message}`); } } // 注册设备状态变化回调 private registerDeviceStateCallback(): void { if (!this.dmInstance) return; // 定义设备状态变化回调 const callback: deviceManager.DeviceStateCallback = { onDeviceOnline: (device: deviceManager.DeviceBasicInfo) => { hilog.info(DOMAIN_ID, TAG, `Device online: {device.deviceName}`); this.refreshDeviceList(); }, onDeviceChanged: (device: deviceManager.DeviceBasicInfo) => { hilog.info(DOMAIN_ID, TAG, `Device changed: {device.deviceName}`); } }; // 注册回调(使用匿名设备管理实例的参数) this.dmInstance.registerDeviceStateCallback('local', callback, (err) => { if (err) { hilog.error(DOMAIN_ID, TAG, `Register callback failed: {err}`); reject(new Error(`获取设备列表失败: {this.deviceList.length} devices`); resolve(this.deviceList); }); }); } // 获取本地设备信息 getLocalDeviceInfo(): deviceManager.DeviceBasicInfo | null { if (!this.dmInstance) return null; try { const localInfo = this.dmInstance.getLocalDeviceInfoSync(); hilog.info(DOMAIN_ID, TAG, `Local device: {err}`); return null; } } // 获取指定设备信息 getDeviceInfo(deviceId: string): deviceManager.DeviceBasicInfo | null { if (!this.dmInstance) return null; try { return this.dmInstance.getDeviceInfoSync(deviceId); } catch (err) { hilog.error(DOMAIN_ID, TAG, `Get device info failed: {err}`); } }); this.dmInstance.release(); this.dmInstance = null; hilog.info(DOMAIN_ID, TAG, 'DeviceManager released'); } }}// 单例导出export const deviceManagerService = new DeviceManagerService();
四、跨设备服务调用
4.1 分布式调度服务
// RemoteService.ts - 跨设备服务调用import distributedSchedule from '@ohos.distributedSchedule';import deviceManager from '@ohos.distributedDeviceManager';import hilog from '@ohos.hilog';const DOMAIN_ID = 0xFF01;const TAG = 'RemoteService';// 调用选项interface StartOptions { deviceId: string; bundleName: string; abilityName: string; wantParams?: Record<string, Object>;}// 跨设备调用结果interface RemoteCallResult { success: boolean; data?: Record<string, Object>; error?: string;}export class RemoteService { private dmService: deviceManager.DeviceManager | null = null; // 启动远程 Ability async startRemoteAbility(options: StartOptions): Promise<boolean> { const { deviceId, bundleName, abilityName, wantParams } = options; try { // 构造 Want const want = { deviceId: deviceId, bundleName: bundleName, abilityName: abilityName, parameters: wantParams || {} }; // 启动远程 Ability const result = await distributedSchedule.startAbility(want); hilog.info(DOMAIN_ID, TAG, `Start remote ability success: {JSON.stringify(err)}`); // 常见错误码处理 const errCode = (err as Error).message; if (errCode.includes('401')) { throw new Error('设备未授权,请先在目标设备确认配对请求'); } else if (errCode.includes('116')) { throw new Error('设备不在线,无法建立连接'); } throw err; } } // 跨设备数据传递(通过 AppStorage + 分布式数据) async sendDataToDevice( deviceId: string, key: string, data: Object ): Promise<boolean> { try { // 存储到 AppStorage(跨设备自动同步) AppStorage.setOrCreate(key, data); // 通过 Want 参数传递(同步方式) const want = { deviceId: deviceId, parameters: { 'remote_data_key': key, 'remote_data_value': data } }; hilog.info(DOMAIN_ID, TAG, `Data sent to device: {err}`); return false; } } // 获取在线设备 async getOnlineDevices(): Promise<deviceManager.DeviceBasicInfo[]> { return new Promise((resolve) => { // 从设备管理服务获取列表 const devices = this.dmService?.getTrustedDeviceListSync('local') || []; const online = devices.filter(d => d.networkStatus === 1); // networkStatus=1 表示在线 resolve(online); }); }}export const remoteService = new RemoteService();
五、完整控制页面实战
5.1 主控制页面
// Index.ets - 智能家居控制中枢主页面import deviceManager from '@ohos.distributedDeviceManager';import { deviceManagerService } from '../model/DeviceManager';import { HomeDevice, DeviceCategory, DeviceState } from '../model/HomeDevice';import Logger from '../utils/Logger';const TAG = 'HomeControlPage';@Entry@Componentstruct HomeControlPage { @State deviceList: HomeDevice[] = []; @State selectedDevice: HomeDevice | null = null; @State isLoading: boolean = false; @State localDeviceName: string = ''; // 控制器 private dmService: DeviceManagerService = deviceManagerService; async aboutToAppear() { // 初始化设备管理 try { await this.dmService.init(); // 获取本地设备名称 const localInfo = this.dmService.getLocalDeviceInfo(); this.localDeviceName = localInfo?.deviceName || '本设备'; } catch (err) { Logger.error(TAG, `Init failed: {err}`); this.isLoading = false; }); } // 构建设备列表(模拟数据) private buildMockDevices(onlineDevices: deviceManager.DeviceBasicInfo[]): HomeDevice[] { const devices: HomeDevice[] = []; // 添加真实在线设备 onlineDevices.forEach((device, index) => { const types = [ DeviceCategory.AC, DeviceCategory.LIGHT, DeviceCategory.CURTAIN ]; devices.push(new HomeDevice( device.deviceId, device.deviceName, types[index % 3], { online: true, powerOn: false, temperature: 26, brightness: 50, curtainLevel: 0 } )); }); // 如果没有设备,添加模拟设备用于演示 if (devices.length === 0) { devices.push( new HomeDevice('local-ac', '客厅空调', DeviceCategory.AC, { online: true, powerOn: true, temperature: 24 }), new HomeDevice('local-light', '卧室灯', DeviceCategory.LIGHT, { online: true, powerOn: true, brightness: 80 }), new HomeDevice('local-curtain', '阳台窗帘', DeviceCategory.CURTAIN, { online: true, curtainLevel: 50 }) ); } return devices; } // 控制设备 async controlDevice(device: HomeDevice, action: string, value?: number) { const deviceId = device.deviceId; try { switch (device.deviceType) { case DeviceCategory.AC: if (action === 'toggle') { device.state.powerOn = !device.state.powerOn; } else if (action === 'temp' && value !== undefined) { device.state.temperature = value; } break; case DeviceCategory.LIGHT: if (action === 'toggle') { device.state.powerOn = !device.state.powerOn; } else if (action === 'brightness' && value !== undefined) { device.state.brightness = value; } break; case DeviceCategory.CURTAIN: if (action === 'level' && value !== undefined) { device.state.curtainLevel = value; } break; } // 触发 UI 更新 this.deviceList = [...this.deviceList]; // 发送到远程设备(如果是远程设备) if (deviceId !== 'local') { await remoteService.sendDataToDevice(deviceId, 'control_action', { action, value, timestamp: Date.now() }); } Logger.info(TAG, `Device {action}`); } catch (err) { Logger.error(TAG, `Control failed: {device.state.temperature || 26}°`) .fontSize(16) .fontWeight(FontWeight.Bold) .width(50) .textAlign(TextAlign.Center) Text('+') .fontSize(20) .padding(8) .background('#E0E0E0') .borderRadius(8) .onClick(() => this.controlDevice(device, 'temp', Math.min(30, (device.state.temperature || 26) + 1))) } } else if (device.deviceType === DeviceCategory.LIGHT) { Slider({ value: device.state.brightness || 50, min: 0, max: 100, style: SliderStyle.OutSet }) .width(120) .onValueChange((val) => this.controlDevice(device, 'brightness', Math.floor(val))) } else if (device.deviceType === DeviceCategory.CURTAIN) { Slider({ value: device.state.curtainLevel || 0, min: 0, max: 100, style: SliderStyle.OutSet }) .width(120) .onValueChange((val) => this.controlDevice(device, 'level', Math.floor(val))) } } .width('100%') .padding(16) .background('#FFFFFF') .borderRadius(12) .shadow({ radius: 8, color: '#20000000', offsetX: 2, offsetY: 2 }) } // 获取状态文本 private getStatusText(device: HomeDevice): string { if (!device.state.online) return '离线'; switch (device.deviceType) { case DeviceCategory.AC: return device.state.powerOn ? `运行中 {device.state.brightness}%` : '已关闭'; case DeviceCategory.CURTAIN: return `开度 ${device.state.curtainLevel}%`; default: return '正常'; } }}
六、常见问题与避坑指南
| | |
|---|
| | 确保设备登录同一华为账号,在设置中开启"多设备协同" |
| | 调用 bindTarget 配对,或在设备信任列表中添加 |
| | |
| | 第一个参数传入空字符串或本地 bundleName |
| | 使用 DistributedData 替代 AppStorage |
核心坑点
- 设备 ID 混淆:本地设备 ID 与远程设备 ID 格式不同,跨设备调用必须使用远程设备 ID
- 权限时机:设备管理权限需要在 Ability 启动后获取,不能在 UIAbility 构造器中调用
- 释放时机:应用退出时必须调用
release() 释放资源,否则可能导致内存泄漏 - 网络切换:设备网络切换(如 Wi-Fi → 移动数据)可能导致分布式连接断开
七、总结
今天我们通过一个智能家居控制中枢的实战项目,系统学习了鸿蒙 ArkTS 的分布式设备管理:
- 设备发现:使用
DeviceManager 发现周围可信设备 - 状态监听
- 跨设备调用:通过
distributedSchedule 启动远程 Ability - 数据传递:AppStorage + Want 参数实现跨设备数据同步
分布式能力是鸿蒙区别于其他移动端开发框架的核心竞争力。掌握这套设备管理 API,你就能开发出真正的"设备合体"应用——手机、平板、手表、车机,无缝协同。
延伸阅读:
- 进阶主题:分布式数据管理(DistributedData)、分布式文件服务、分布式任务调度
如果觉得这篇文章有帮助,欢迎点赞、收藏!有任何问题欢迎在评论区留言交流。