Harmony学习之分布式能力入门
Harmony学习之分布式能力入门
一、场景引入
小明正在开发一个智能家居控制应用,他希望用户能在手机上控制客厅的智能灯,同时将音乐从手机流转到智能音箱播放。传统开发需要分别处理设备发现、连接建立、数据同步等复杂逻辑,而HarmonyOS的分布式能力让这些变得简单。
二、核心概念
1. 分布式架构概览
HarmonyOS的分布式能力基于分布式软总线技术,将多个物理设备虚拟化为一个"超级终端"。核心组件包括:
- 分布式软总线:设备间的通信基座,提供自动发现、连接建立和数据传输能力
- 分布式数据管理:实现跨设备数据同步,支持键值对和关系型数据库
- 分布式任务调度:智能分配任务到最适合的设备执行
- 分布式设备虚拟化:将多设备硬件资源抽象为统一的能力池
2. 分布式软总线工作原理
分布式软总线采用分层架构设计:
- 物理传输层:支持Wi-Fi、蓝牙、NFC等多种连接方式
- 设备发现与连接层:基于mDNS协议实现设备自动发现
- 核心通信机制:支持点对点通信、发布订阅、请求响应等多种模式
设备间通信延迟可控制在10ms以内,吞吐量可达100MB/s以上,支持1000+设备同时连接。
三、关键实现
1. 设备发现与连接
使用DeviceManager发现附近设备:
// entry/src/main/ets/pages/DeviceDiscoveryPage.ets
import deviceManager from '@ohos.distributedHardware.deviceManager';
import common from '@ohos.app.ability.common';
@Component
struct DeviceDiscoveryPage {
@State deviceList: deviceManager.DeviceInfo[] = [];
private deviceManager: deviceManager.DeviceManager | null = null;
// 初始化设备管理
async initDeviceManager() {
try {
this.deviceManager = deviceManager.createDeviceManager('com.example.app');
// 监听设备状态变化
this.deviceManager.on('deviceStateChange', (data) => {
console.log('设备状态变化:', data);
this.updateDeviceList();
});
// 开始设备发现
this.startDeviceDiscovery();
} catch (error) {
console.error('设备管理初始化失败:', error);
}
}
// 启动设备发现
async startDeviceDiscovery() {
if (!this.deviceManager) {
return;
}
const subscribeInfo = {
subscribeId: 'discovery_subscribe',
mode: deviceManager.DiscoverMode.DISCOVER_MODE_ACTIVE,
medium: deviceManager.ExchangeMedium.COMMON,
freq: deviceManager.ExchangeFreq.LOW,
isSameAccount: true, // 仅发现同账号设备
isWakeRemote: false
};
await this.deviceManager.startDeviceDiscovery(subscribeInfo);
this.updateDeviceList();
}
// 更新设备列表
async updateDeviceList() {
if (!this.deviceManager) {
return;
}
const devices = await this.deviceManager.getTrustedDeviceListSync();
this.deviceList = devices;
}
// 连接到指定设备
async connectToDevice(deviceId: string) {
try {
const device = this.deviceList.find(d => d.deviceId === deviceId);
if (device) {
console.log('连接到设备:', device.deviceName);
// 这里可以执行跨设备操作
}
} catch (error) {
console.error('连接设备失败:', error);
}
}
build() {
Column() {
Button('发现设备')
.onClick(() => this.startDeviceDiscovery())
.margin(10)
if (this.deviceList.length > 0) {
List() {
ForEach(this.deviceList, (item: deviceManager.DeviceInfo) => {
ListItem() {
Column() {
Text(item.deviceName)
.fontSize(16)
Text(`设备ID: ${item.deviceId}`)
.fontSize(12)
.fontColor(Color.Gray)
}
.padding(10)
}
.onClick(() => this.connectToDevice(item.deviceId))
})
}
.height(300)
}
}
.onAppear(() => this.initDeviceManager())
}
}
2. 跨设备启动应用
使用分布式能力启动远程设备上的应用:
// entry/src/main/ets/pages/RemoteStartPage.ets
import featureAbility from '@ohos.ability.featureAbility';
import common from '@ohos.app.ability.common';
@Component
struct RemoteStartPage {
@State targetDeviceId: string = '';
// 跨设备启动Ability
async startRemoteAbility() {
if (!this.targetDeviceId) {
console.error('请先选择目标设备');
return;
}
try {
const intent = {
deviceId: this.targetDeviceId,
bundleName: 'com.example.remoteapp',
abilityName: 'MainAbility',
parameters: {
message: 'Hello from another device',
timestamp: Date.now()
}
};
await featureAbility.startAbility(intent);
console.log('远程应用启动成功');
} catch (error) {
console.error('启动远程应用失败:', error);
}
}
build() {
Column() {
TextInput({ placeholder: '输入目标设备ID' })
.onChange((value) => this.targetDeviceId = value)
.width('80%')
.margin(10)
Button('启动远程应用')
.onClick(() => this.startRemoteAbility())
.width('80%')
.height(50)
.margin(10)
}
}
}
3. 分布式数据同步
使用分布式数据对象实现跨设备数据同步:
// entry/src/main/ets/pages/DataSyncPage.ets
import distributedData from '@ohos.data.distributedData';
import common from '@ohos.app.ability.common';
@Component
struct DataSyncPage {
@State message: string = '';
@State receivedMessages: string[] = [];
private dataObject: distributedData.DataObject | null = null;
// 初始化分布式数据对象
async initDataObject() {
try {
const context = getContext(this) as common.UIAbilityContext;
// 创建分布式数据对象
this.dataObject = distributedData.createDataObject({
bundleName: context.abilityInfo.bundleName,
objectName: 'chatMessage',
initialValue: {
messages: []
}
});
// 监听数据变化
this.dataObject.on('dataChange', (newValue) => {
console.log('数据变化:', newValue);
this.receivedMessages = newValue.messages || [];
});
} catch (error) {
console.error('初始化数据对象失败:', error);
}
}
// 发送消息
async sendMessage() {
if (!this.message.trim() || !this.dataObject) {
return;
}
try {
await this.dataObject.update((oldValue) => {
const messages = oldValue.messages || [];
return {
messages: [...messages, {
content: this.message,
timestamp: Date.now(),
sender: '当前设备'
}]
};
});
this.message = '';
} catch (error) {
console.error('发送消息失败:', error);
}
}
build() {
Column() {
// 消息输入区
Row() {
TextInput({ placeholder: '输入消息...', text: this.message })
.onChange((value) => this.message = value)
.width('70%')
.height(40)
.margin(5)
Button('发送')
.onClick(() => this.sendMessage())
.width('25%')
.height(40)
.margin(5)
}
.padding(10)
// 消息列表
List() {
ForEach(this.receivedMessages, (item, index) => {
ListItem() {
Column() {
Text(item.content)
.fontSize(16)
Text(`来自: ${item.sender}, 时间: ${new Date(item.timestamp).toLocaleTimeString()}`)
.fontSize(12)
.fontColor(Color.Gray)
}
.padding(10)
.width('100%')
}
})
}
.height(400)
}
.onAppear(() => this.initDataObject())
}
}
4. 权限配置
在module.json5中配置分布式权限:
// entry/src/main/module.json5
{
"module": {
"name": "entry",
"type": "entry",
"requestPermissions": [
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC",
"reason": "用于跨设备数据同步",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
},
{
"name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO",
"reason": "用于获取分布式设备信息",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
}
],
"distributedCapabilities": [
{
"name": "com.example.app.distributed",
"description": "分布式能力配置"
}
]
}
}
四、实战案例:跨设备音乐控制
下面实现一个完整的跨设备音乐控制应用:
// entry/src/main/ets/pages/MusicControlPage.ets
import distributedData from '@ohos.data.distributedData';
import deviceManager from '@ohos.distributedHardware.deviceManager';
import common from '@ohos.app.ability.common';
interface MusicState {
isPlaying: boolean;
currentTrack: string;
progress: number;
duration: number;
}
@Component
struct MusicControlPage {
@State musicState: MusicState = {
isPlaying: false,
currentTrack: '未知歌曲',
progress: 0,
duration: 0
};
@State deviceList: deviceManager.DeviceInfo[] = [];
@State selectedDeviceId: string = '';
private dataObject: distributedData.DataObject | null = null;
private deviceManager: deviceManager.DeviceManager | null = null;
// 初始化
async onInit() {
await this.initDeviceManager();
await this.initDataObject();
}
// 初始化设备管理
async initDeviceManager() {
try {
this.deviceManager = deviceManager.createDeviceManager('com.example.music');
this.deviceManager.on('deviceStateChange', () => {
this.updateDeviceList();
});
await this.startDeviceDiscovery();
} catch (error) {
console.error('设备管理初始化失败:', error);
}
}
// 初始化数据对象
async initDataObject() {
try {
const context = getContext(this) as common.UIAbilityContext;
this.dataObject = distributedData.createDataObject({
bundleName: context.abilityInfo.bundleName,
objectName: 'musicControl',
initialValue: {
musicState: this.musicState
}
});
// 监听音乐状态变化
this.dataObject.on('dataChange', (newValue) => {
this.musicState = newValue.musicState || this.musicState;
});
} catch (error) {
console.error('初始化数据对象失败:', error);
}
}
// 开始设备发现
async startDeviceDiscovery() {
if (!this.deviceManager) {
return;
}
const subscribeInfo = {
subscribeId: 'music_discovery',
mode: deviceManager.DiscoverMode.DISCOVER_MODE_ACTIVE,
medium: deviceManager.ExchangeMedium.COMMON,
freq: deviceManager.ExchangeFreq.LOW,
isSameAccount: true,
isWakeRemote: false
};
await this.deviceManager.startDeviceDiscovery(subscribeInfo);
this.updateDeviceList();
}
// 更新设备列表
async updateDeviceList() {
if (!this.deviceManager) {
return;
}
const devices = await this.deviceManager.getTrustedDeviceListSync();
this.deviceList = devices;
}
// 播放/暂停音乐
async togglePlay() {
if (!this.dataObject) {
return;
}
await this.dataObject.update((oldValue) => {
const newState = {
...oldValue.musicState,
isPlaying: !oldValue.musicState.isPlaying
};
return {
musicState: newState
};
});
}
// 切换歌曲
async changeTrack(trackName: string) {
if (!this.dataObject) {
return;
}
await this.dataObject.update((oldValue) => {
const newState = {
...oldValue.musicState,
currentTrack: trackName,
progress: 0
};
return {
musicState: newState
};
});
}
// 流转到其他设备
async transferToDevice(deviceId: string) {
if (!this.dataObject) {
return;
}
const device = this.deviceList.find(d => d.deviceId === deviceId);
if (device) {
console.log('流转音乐到设备:', device.deviceName);
this.selectedDeviceId = deviceId;
// 这里可以执行跨设备迁移逻辑
}
}
build() {
Column() {
// 设备列表
if (this.deviceList.length > 0) {
Text('可用设备:')
.fontSize(16)
.margin(10)
List() {
ForEach(this.deviceList, (item: deviceManager.DeviceInfo) => {
ListItem() {
Text(item.deviceName)
.fontSize(14)
}
.onClick(() => this.transferToDevice(item.deviceId))
})
}
.height(100)
.margin(10)
}
// 音乐控制面板
Column() {
Text(this.musicState.currentTrack)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin(10)
Text(`${this.musicState.isPlaying ? '播放中' : '已暂停'}`)
.fontSize(14)
.fontColor(this.musicState.isPlaying ? Color.Green : Color.Gray)
.margin(5)
Row() {
Button(this.musicState.isPlaying ? '暂停' : '播放')
.onClick(() => this.togglePlay())
.width(80)
.height(40)
.margin(5)
Button('下一首')
.onClick(() => this.changeTrack('下一首歌曲'))
.width(80)
.height(40)
.margin(5)
}
.margin(10)
}
.border({ width: 1, color: Color.Gray })
.borderRadius(10)
.padding(15)
.margin(10)
}
.onAppear(() => this.onInit())
}
}
五、最佳实践
1. 网络状态检测
在分布式应用中,网络状态至关重要:
// entry/src/main/ets/utils/NetworkUtil.ets
import network from '@ohos.network.net';
import common from '@ohos.app.ability.common';
export class NetworkUtil {
// 检查网络连接状态
static async checkNetworkStatus(): Promise<boolean> {
try {
const netManager = network.getDefault();
const netCapabilities = await netManager.getNetCapabilities();
return netCapabilities.hasCap(network.NetCap.NET_CAPABILITY_INTERNET);
} catch (error) {
console.error('检查网络状态失败:', error);
return false;
}
}
// 监听网络变化
static registerNetworkListener(callback: (isConnected: boolean) => void) {
const netManager = network.getDefault();
netManager.on('netStatusChange', (data) => {
callback(data.isConnected);
});
}
}
2. 错误处理与重试机制
分布式操作需要健壮的错误处理:
// entry/src/main/ets/utils/RetryUtil.ets
export class RetryUtil {
// 带重试的异步操作
static async withRetry<T>(
operation: () => Promise<T>,
maxRetries: number = 3,
delay: number = 1000
): Promise<T> {
let lastError: Error | null = null;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
lastError = error;
console.warn(`操作失败,第${attempt}次重试:`, error);
if (attempt < maxRetries) {
await new Promise(resolve => setTimeout(resolve, delay * attempt));
}
}
}
throw lastError || new Error('操作失败');
}
}
3. 数据冲突解决策略
在分布式环境中,数据冲突不可避免:
// entry/src/main/ets/utils/ConflictResolver.ets
import distributedData from '@ohos.data.distributedData';
export class ConflictResolver {
// 基于时间戳的冲突解决
static timestampResolver(oldValue: any, newValue: any): any {
const oldTimestamp = oldValue?.timestamp || 0;
const newTimestamp = newValue?.timestamp || 0;
return newTimestamp > oldTimestamp ? newValue : oldValue;
}
// 自定义业务逻辑冲突解决
static customResolver(oldValue: any, newValue: any): any {
// 根据业务规则解决冲突
if (oldValue?.priority > newValue?.priority) {
return oldValue;
}
return newValue;
}
}
六、总结与行动建议
通过本篇文章,我们学习了HarmonyOS分布式能力的核心概念和基本用法。在实际开发中,建议:
- 权限管理要规范:严格按照权限管理规范申请分布式权限
- 网络状态要检测:在分布式操作前检查网络连接状态
- 错误处理要健壮:实现重试机制和错误降级策略
- 数据冲突要解决:根据业务场景选择合适的冲突解决策略
- 性能优化要考虑:避免频繁的跨设备数据同步,合理使用本地缓存
建议读者在掌握基础功能后,继续学习分布式数据管理和分布式任务调度等进阶内容,构建更强大的跨设备应用。

浙公网安备 33010602011771号