本文字数:约3500字 | 预计阅读时间:14分钟 前置知识:建议先学习本系列前七篇,特别是服务卡片开发
实战价值:掌握多端协同技术,打造全场景智慧体验
系列导航:本文是《鸿蒙开发系列》第8篇,下篇将讲解性能优化与调试技巧
一、多端协同概述:鸿蒙的分布式能力 鸿蒙操作系统的核心特性之一就是分布式能力,它通过分布式软总线技术,让多个设备能够像使用一个设备一样协同工作。多端协同允许应用在不同设备间无缝流转,数据在多设备间同步共享。
1.1 多端协同的核心特性 设备虚拟化:多个设备虚拟为一个超级终端
能力互助:设备间共享硬件和软件能力
数据流转:应用和数据在设备间无缝迁移
分布式安全:端到端的安全保障
1.2 典型应用场景 场景 描述 示例 应用接续 应用从一个设备迁移到另一个设备 手机上看的视频流转到平板上继续观看 跨屏协同 多个设备屏幕协同显示 手机作为平板的手写板或控制器 硬件共享 共享其他设备的硬件能力 使用平板的摄像头进行视频通话 数据同步 数据在多设备间实时同步 笔记、日历、联系人实时同步 二、分布式软总线基础 2.1 设备发现与连接 typescript
// ets/utils/DistributedDeviceManager.ts import deviceManager from '@ohos.distributedDeviceManager';
class DistributedDeviceManager { private deviceList: Array<deviceManager.DeviceBasicInfo> = []; private discoverCallback: ((devices: Array<deviceManager.DeviceBasicInfo>) => void) | null = null;
// 初始化设备管理 async initialize() { try { // 创建设备管理器 const deviceManager = await deviceManager.createDeviceManager('com.example.app'); console.log('设备管理器创建成功');
// 注册设备状态监听
deviceManager.on('deviceStateChange', (data) => {
this.handleDeviceStateChange(data);
});
return true;
} catch (error) {
console.error('设备管理器初始化失败:', error);
return false;
}
}
// 开始发现设备 startDiscovery() { try { deviceManager.startDeviceDiscovery({ mode: deviceManager.DiscoveryMode.ACTIVE, medium: deviceManager.ExchangeMedium.AUTO, freq: deviceManager.ExchangeFreq.HIGH });
deviceManager.on('deviceFound', (data) => {
this.handleDeviceFound(data);
});
console.log('开始设备发现');
} catch (error) {
console.error('设备发现失败:', error);
}
}
// 停止发现设备 stopDiscovery() { try { deviceManager.stopDeviceDiscovery(); console.log('停止设备发现'); } catch (error) { console.error('停止设备发现失败:', error); } }
// 处理设备发现 private handleDeviceFound(data: deviceManager.DeviceBasicInfo) { // 检查是否已存在 const exists = this.deviceList.some(device => device.deviceId === data.deviceId); if (!exists) { this.deviceList.push(data); console.log('发现新设备:', data.deviceName);
// 通知监听者
if (this.discoverCallback) {
this.discoverCallback(this.deviceList);
}
}
}
// 处理设备状态变化 private handleDeviceStateChange(data: { deviceId: string, deviceState: number }) { const device = this.deviceList.find(d => d.deviceId === data.deviceId); if (device) { if (data.deviceState === deviceManager.DeviceState.OFFLINE) { // 设备离线 this.deviceList = this.deviceList.filter(d => d.deviceId !== data.deviceId); console.log('设备离线:', device.deviceName); } else if (data.deviceState === deviceManager.DeviceState.ONLINE) { console.log('设备在线:', device.deviceName); }
// 通知监听者
if (this.discoverCallback) {
this.discoverCallback(this.deviceList);
}
}
}
// 设置设备发现回调 setDiscoverCallback(callback: (devices: Array<deviceManager.DeviceBasicInfo>) => void) { this.discoverCallback = callback; }
// 获取设备列表 getDevices(): Array<deviceManager.DeviceBasicInfo> { return [...this.deviceList]; }
// 连接设备 async connectDevice(deviceId: string): Promise { try { await deviceManager.authenticateDevice(deviceId, { authType: deviceManager.AuthType.PIN, token: '123456' // 实际使用时需要更安全的认证方式 });
console.log('设备连接成功:', deviceId);
return true;
} catch (error) {
console.error('设备连接失败:', error);
return false;
}
} }
export default new DistributedDeviceManager(); 2.2 设备信息获取 typescript
// ets/utils/DeviceInfoUtil.ts import deviceInfo from '@ohos.deviceInfo';
class DeviceInfoUtil { // 获取设备基本信息 static getDeviceInfo() { return { deviceId: deviceInfo.deviceId, deviceType: deviceInfo.deviceType, deviceName: deviceInfo.deviceName, manufacturer: deviceInfo.manufacturer, brand: deviceInfo.brand, marketName: deviceInfo.marketName, productSeries: deviceInfo.productSeries, productModel: deviceInfo.productModel, softwareModel: deviceInfo.softwareModel, hardwareModel: deviceInfo.hardwareModel, hardwareProfile: deviceInfo.hardwareProfile, bootloaderVersion: deviceInfo.bootloaderVersion, abiList: deviceInfo.abiList, securityPatchTag: deviceInfo.securityPatchTag, displayVersion: deviceInfo.displayVersion, incrementalVersion: deviceInfo.incrementalVersion, osReleaseType: deviceInfo.osReleaseType, osFullName: deviceInfo.osFullName, majorVersion: deviceInfo.majorVersion, seniorVersion: deviceInfo.seniorVersion, featureVersion: deviceInfo.featureVersion, buildVersion: deviceInfo.buildVersion, sdkApiVersion: deviceInfo.sdkApiVersion, firstApiVersion: deviceInfo.firstApiVersion }; }
// 获取设备能力信息 static getDeviceCapabilities() { return { // 屏幕信息 screen: { width: window.innerWidth, height: window.innerHeight, density: window.devicePixelRatio },
// 设备类型
type: this.getDeviceType(),
// 支持的功能
capabilities: {
camera: this.hasCapability('camera'),
microphone: this.hasCapability('microphone'),
gps: this.hasCapability('gps'),
nfc: this.hasCapability('nfc'),
bluetooth: this.hasCapability('bluetooth'),
wifi: this.hasCapability('wifi')
}
};
}
// 判断设备类型 private static getDeviceType(): string { const deviceType = deviceInfo.deviceType; switch (deviceType) { case 'phone': return '手机'; case 'tablet': return '平板'; case 'tv': return '电视'; case 'wearable': return '穿戴设备'; case 'car': return '车机'; default: return '未知设备'; } }
// 检查设备能力 private static hasCapability(capability: string): boolean { // 这里根据设备类型和能力进行判断 const deviceType = deviceInfo.deviceType;
switch (capability) {
case 'camera':
return deviceType !== 'wearable'; // 穿戴设备可能没有摄像头
case 'microphone':
return deviceType !== 'wearable';
case 'gps':
return deviceType === 'phone' || deviceType === 'tablet';
default:
return true;
}
} }
export default DeviceInfoUtil; 三、应用流转:跨设备无缝体验 3.1 流转能力配置 json
// module.json5 { "module": { "name": "entry", "type": "entry", "continuable": true, // 启用流转能力 "abilities": [ { "name": "MainAbility", "srcEntry": "./ets/entryability/MainAbility.ts", "description": "media:icon", "label": "media:icon", "startWindowBackground": "$color:start_window_background", "exported": true, "skills": [ { "actions": [ "action.system.home" ], "entities": [ "entity.system.home" ] } ], "continuationFilter": { "deviceTypes": ["phone", "tablet", "tv"], // 支持的设备类型 "abilityTypes": ["page"], "bundleName": "com.example.multideviceapp", "supportDimensions": ["12", "22", "24", "44"] } } ] } } 3.2 流转管理器 typescript
// ets/utils/ContinuationManager.ts import continuation from '@ohos.continuation.continuationManager';
class ContinuationManager { private continuationToken: number = 0; private deviceList: Array = [];
// 注册流转能力 async registerContinuation() { try { this.continuationToken = await continuation.registerContinuation({ deviceType: ['phone', 'tablet', 'tv'], abilityType: ['page'], bundleName: 'com.example.multideviceapp' });
console.log('流转能力注册成功, token:', this.continuationToken);
return true;
} catch (error) {
console.error('流转能力注册失败:', error);
return false;
}
}
// 显示设备选择器 async showDevicePicker(): Promise<string | null> { try { const extraParams = { title: '选择流转设备', deviceType: ['phone', 'tablet'], filter: 'online' };
const result = await continuation.startDeviceSelection(this.continuationToken, extraParams);
if (result && result.length > 0) {
return result[0]; // 返回选择的设备ID
}
return null;
} catch (error) {
console.error('设备选择失败:', error);
return null;
}
}
// 更新流转状态 updateContinuationState(state: continuation.ContinuationState) { try { continuation.updateContinuationState(this.continuationToken, state); } catch (error) { console.error('更新流转状态失败:', error); } }
// 取消流转 unregisterContinuation() { if (this.continuationToken > 0) { try { continuation.unregisterContinuation(this.continuationToken); console.log('流转能力取消注册'); } catch (error) { console.error('取消流转注册失败:', error); } } }
// 获取流转数据 saveContinuationData(): any { // 保存需要流转的数据 return { timestamp: Date.now(), pageData: this.getCurrentPageData(), userState: this.getUserState() }; }
// 恢复流转数据 restoreContinuationData(data: any) { // 恢复流转的数据 if (data && data.pageData) { this.restorePageData(data.pageData); } }
private getCurrentPageData(): any { // 获取当前页面数据 return { pageIndex: 0, scrollPosition: 0, formData: {} }; }
private getUserState(): any { // 获取用户状态 return { userId: 'user123', preferences: {} }; }
private restorePageData(data: any) { // 恢复页面数据 console.log('恢复页面数据:', data); } }
export default new ContinuationManager(); 3.3 流转页面实现 typescript
// ets/pages/MainPage.ets @Entry @Component struct MainPage { @State currentVideo: { id: string, title: string, url: string, progress: number } = { id: 'video001', title: '鸿蒙开发教程', url: 'example.com/video.mp4', progress: 0.35 };
@State connectedDevices: Array<{id: string, name: string, type: string}> = []; @State isPlaying: boolean = false;
private continuationManager = ContinuationManager;
aboutToAppear() { // 注册流转能力 this.continuationManager.registerContinuation();
// 监听设备连接
DistributedDeviceManager.setDiscoverCallback((devices) => {
this.connectedDevices = devices.map(device => ({
id: device.deviceId,
name: device.deviceName,
type: this.getDeviceTypeName(device.deviceType)
}));
});
}
aboutToDisappear() { // 取消流转注册 this.continuationManager.unregisterContinuation(); }
build() { Column({ space: 20 }) { // 视频播放器 Column({ space: 12 }) { Text(this.currentVideo.title) .fontSize(20) .fontWeight(FontWeight.Bold)
// 视频播放区域
Column()
.width('100%')
.height(200)
.backgroundColor('#000000')
.justifyContent(FlexAlign.Center) {
Row() {
if (this.isPlaying) {
Image($r('app.media.pause'))
.width(48)
.height(48)
.onClick(() => {
this.isPlaying = false;
})
} else {
Image($r('app.media.play'))
.width(48)
.height(48)
.onClick(() => {
this.isPlaying = true;
})
}
}
}
// 进度条
Column() {
Row()
.width(`${this.currentVideo.progress * 100}%`)
.height(4)
.backgroundColor('#007DFF')
}
.width('100%')
.height(4)
.backgroundColor('#EEEEEE')
// 播放时间
Row() {
Text('12:30')
.fontSize(12)
.fontColor('#666666')
Blank()
Text('35:45')
.fontSize(12)
.fontColor('#666666')
}
.width('100%')
}
.padding(20)
.backgroundColor(Color.White)
.borderRadius(16)
.shadow({ radius: 8, color: '#00000010' })
// 流转控制
Column({ space: 12 }) {
Text('流转到其他设备')
.fontSize(16)
.fontWeight(FontWeight.Medium)
if (this.connectedDevices.length === 0) {
Text('未发现可用设备')
.fontSize(14)
.fontColor('#999999')
} else {
Column({ space: 8 }) {
ForEach(this.connectedDevices, (device) => {
Row({ space: 12 }) {
Image(this.getDeviceIcon(device.type))
.width(24)
.height(24)
Column({ space: 4 }) {
Text(device.name)
.fontSize(14)
.fontColor('#333333')
Text(device.type)
.fontSize(12)
.fontColor('#666666')
}
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
Button('流转')
.width(80)
.height(32)
.fontSize(12)
.onClick(() => {
this.transferToDevice(device.id);
})
}
.padding(12)
.backgroundColor('#F8F8F8')
.borderRadius(12)
})
}
}
Button('发现更多设备')
.width('100%')
.height(40)
.fontSize(14)
.backgroundColor('#007DFF')
.fontColor(Color.White)
.onClick(() => {
this.discoverDevices();
})
}
.padding(20)
.backgroundColor(Color.White)
.borderRadius(16)
.shadow({ radius: 8, color: '#00000010' })
}
.width('100%')
.height('100%')
.padding(20)
.backgroundColor('#F5F5F5')
}
// 流转到指定设备 async transferToDevice(deviceId: string) { // 保存当前状态 const continuationData = { video: this.currentVideo, isPlaying: this.isPlaying, progress: this.currentVideo.progress, timestamp: Date.now() };
// 开始流转
const selectedDeviceId = await this.continuationManager.showDevicePicker();
if (selectedDeviceId) {
console.log('开始流转到设备:', selectedDeviceId);
// 更新流转状态
this.continuationManager.updateContinuationState('started');
// 这里实际会触发系统流转流程
// 流转成功后,应用会在目标设备上恢复
}
}
// 发现设备 discoverDevices() { DistributedDeviceManager.startDiscovery(); }
// 获取设备图标 getDeviceIcon(type: string): Resource { switch (type) { case '手机': return r('app.media.tablet'); case '电视': return r('app.media.watch'); default: return $r('app.media.device'); } }
// 获取设备类型名称 getDeviceTypeName(deviceType: number): string { switch (deviceType) { case 0: return '手机'; case 1: return '平板'; case 3: return '电视'; case 4: return '穿戴设备'; case 5: return '车机'; default: return '未知设备'; } } } 四、分布式数据管理 4.1 分布式数据存储 typescript
// ets/utils/DistributedDataManager.ts import distributedData from '@ohos.data.distributedData';
class DistributedDataManager { private kvManager: distributedData.KVManager | null = null; private kvStore: distributedData.KVStore | null = null; private storeId: string = 'multidevice_data_store';
// 初始化分布式KV存储 async initialize() { try { // 创建KVManager配置 const config: distributedData.KVManagerConfig = { bundleName: 'com.example.multideviceapp', userInfo: { userId: 'globalUser', userType: distributedData.UserType.SAME_USER_ID }, context: getContext(this) };
// 创建KVManager
this.kvManager = distributedData.createKVManager(config);
// 创建KVStore配置
const options: distributedData.Options = {
createIfMissing: true,
encrypt: true,
backup: false,
autoSync: true,
kvStoreType: distributedData.KVStoreType.DEVICE_COLLABORATION,
securityLevel: distributedData.SecurityLevel.S2
};
// 创建KVStore
this.kvStore = await this.kvManager.getKVStore(this.storeId, options);
console.log('分布式数据存储初始化成功');
return true;
} catch (error) {
console.error('分布式数据存储初始化失败:', error);
return false;
}
}
// 保存数据 async save(key: string, value: any): Promise { if (!this.kvStore) return false;
try {
await this.kvStore.put(key, JSON.stringify(value));
return true;
} catch (error) {
console.error('保存数据失败:', error);
return false;
}
}
// 获取数据 async get<T = any>(key: string): Promise<T | null> { if (!this.kvStore) return null;
try {
const value = await this.kvStore.get(key);
if (value) {
return JSON.parse(value.toString()) as T;
}
return null;
} catch (error) {
console.error('获取数据失败:', error);
return null;
}
}
// 删除数据 async delete(key: string): Promise { if (!this.kvStore) return false;
try {
await this.kvStore.delete(key);
return true;
} catch (error) {
console.error('删除数据失败:', error);
return false;
}
}
// 同步数据到其他设备 async sync(deviceIds?: Array): Promise { if (!this.kvStore) return false;
try {
const mode = distributedData.SyncMode.PULL_ONLY;
const delay = 0; // 立即同步
if (deviceIds && deviceIds.length > 0) {
// 同步到指定设备
await this.kvStore.sync(deviceIds, mode, delay);
} else {
// 同步到所有设备
await this.kvStore.sync(mode, delay);
}
return true;
} catch (error) {
console.error('数据同步失败:', error);
return false;
}
}
// 监听数据变化 onDataChange(callback: (data: { key: string, value: any, deviceId: string }) => void) { if (!this.kvStore) return;
this.kvStore.on('dataChange', (data) => {
const changeData = data as distributedData.ChangeNotification;
changeData.insertEntries.forEach(entry => {
try {
const value = JSON.parse(entry.value.toString());
callback({
key: entry.key,
value: value,
deviceId: changeData.deviceId
});
} catch (error) {
console.error('解析变更数据失败:', error);
}
});
});
} }
export default new DistributedDataManager(); 4.2 分布式数据同步示例 typescript
// ets/pages/CollaborationPage.ets @Entry @Component struct CollaborationPage { @State todoList: Array<{ id: string, text: string, completed: boolean, device: string }> = []; @State newTodoText: string = ''; @State connectedDevices: Array = [];
private distributedDataManager = DistributedDataManager; private deviceId: string = '';
async aboutToAppear() { // 初始化分布式数据 await this.distributedDataManager.initialize();
// 获取设备ID
this.deviceId = DeviceInfoUtil.getDeviceInfo().deviceId;
// 监听数据变化
this.distributedDataManager.onDataChange((data) => {
this.handleDataChange(data);
});
// 加载数据
await this.loadTodoList();
}
async loadTodoList() { const savedList = await this.distributedDataManager.get<Array>('todo_list'); if (savedList) { this.todoList = savedList; } }
handleDataChange(data: { key: string, value: any, deviceId: string }) {
if (data.key === 'todo_list') {
this.todoList = data.value;
console.log(数据从设备 ${data.deviceId} 同步);
}
}
async addTodo() { if (!this.newTodoText.trim()) return;
const newTodo = {
id: Date.now().toString(),
text: this.newTodoText,
completed: false,
device: this.deviceId,
timestamp: Date.now()
};
this.todoList = [...this.todoList, newTodo];
this.newTodoText = '';
// 保存到分布式存储
await this.distributedDataManager.save('todo_list', this.todoList);
// 同步到其他设备
await this.distributedDataManager.sync();
}
async toggleTodo(id: string) { this.todoList = this.todoList.map(todo => todo.id === id ? { ...todo, completed: !todo.completed } : todo );
// 保存并同步
await this.distributedDataManager.save('todo_list', this.todoList);
await this.distributedDataManager.sync();
}
async deleteTodo(id: string) { this.todoList = this.todoList.filter(todo => todo.id !== id);
// 保存并同步
await this.distributedDataManager.save('todo_list', this.todoList);
await this.distributedDataManager.sync();
}
build() { Column({ space: 20 }) { Text('协同待办') .fontSize(24) .fontWeight(FontWeight.Bold)
// 添加待办
Row({ space: 12 }) {
TextInput({ placeholder: '添加新待办...' })
.width('70%')
.height(48)
.value(this.newTodoText)
.onChange((value: string) => {
this.newTodoText = value;
})
Button('添加')
.width('30%')
.height(48)
.fontSize(14)
.backgroundColor('#007DFF')
.fontColor(Color.White)
.onClick(() => {
this.addTodo();
})
}
.width('100%')
// 待办列表
List({ space: 12 }) {
ForEach(this.todoList, (todo) => {
ListItem() {
Row({ space: 12 }) {
// 完成状态
Column()
.width(20)
.height(20)
.border({ width: 2, color: todo.completed ? '#34C759' : '#CCCCCC' })
.borderRadius(10)
.backgroundColor(todo.completed ? '#34C759' : 'transparent')
.onClick(() => {
this.toggleTodo(todo.id);
})
// 待办文本
Text(todo.text)
.fontSize(16)
.fontColor(todo.completed ? '#999999' : '#333333')
.textDecoration(todo.completed ? { type: TextDecorationType.LineThrough } : null)
.layoutWeight(1)
// 设备标识
Text(todo.device === this.deviceId ? '本机' : '其他设备')
.fontSize(12)
.fontColor('#666666')
.padding({ left: 8, right: 8, top: 4, bottom: 4 })
.backgroundColor('#F0F0F0')
.borderRadius(12)
// 删除按钮
Image($r('app.media.delete'))
.width(20)
.height(20)
.onClick(() => {
this.deleteTodo(todo.id);
})
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(12)
.shadow({ radius: 4, color: '#00000010' })
}
})
}
.layoutWeight(1)
// 同步控制
Row({ space: 12 }) {
Button('手动同步')
.width('50%')
.height(48)
.fontSize(14)
.backgroundColor('#34C759')
.fontColor(Color.White)
.onClick(() => {
this.distributedDataManager.sync();
})
Button('清空列表')
.width('50%')
.height(48)
.fontSize(14)
.backgroundColor('#FF3B30')
.fontColor(Color.White)
.onClick(async () => {
this.todoList = [];
await this.distributedDataManager.save('todo_list', []);
await this.distributedDataManager.sync();
})
}
.width('100%')
}
.width('100%')
.height('100%')
.padding(20)
.backgroundColor('#F5F5F5')
} } 五、硬件能力共享 5.1 摄像头共享 typescript
// ets/utils/CameraSharingManager.ts import camera from '@ohos.multimedia.camera'; import image from '@ohos.multimedia.image';
class CameraSharingManager { private cameraManager: camera.CameraManager | null = null; private cameraInput: camera.CameraInput | null = null; private previewOutput: camera.PreviewOutput | null = null; private photoOutput: camera.PhotoOutput | null = null;
// 初始化摄像头 async initialize() { try { this.cameraManager = camera.getCameraManager(getContext(this));
// 获取摄像头列表
const cameras = this.cameraManager.getSupportedCameras();
if (cameras.length === 0) {
throw new Error('没有可用的摄像头');
}
// 使用第一个摄像头
const cameraDevice = cameras[0];
// 创建相机输入
this.cameraInput = this.cameraManager.createCameraInput(cameraDevice);
await this.cameraInput.open();
// 创建预览输出
const surfaceId = await this.createPreviewSurface();
this.previewOutput = this.cameraManager.createPreviewOutput(surfaceId);
// 创建拍照输出
this.photoOutput = this.cameraManager.createPhotoOutput();
// 创建会话
const session = this.cameraManager.createCaptureSession();
// 配置会话
session.beginConfig();
session.addInput(this.cameraInput);
session.addOutput(this.previewOutput);
session.addOutput(this.photoOutput);
await session.commitConfig();
// 启动会话
await session.start();
console.log('摄像头初始化成功');
return true;
} catch (error) {
console.error('摄像头初始化失败:', error);
return false;
}
}
// 创建预览表面 private async createPreviewSurface(): Promise { // 这里需要创建XComponent来显示预览 return 'preview_surface'; }
// 拍照 async takePhoto(): Promise<image.PixelMap | null> { if (!this.photoOutput) return null;
try {
const photoSettings = {
rotation: camera.ImageRotation.ROTATION_0,
quality: camera.QualityLevel.QUALITY_LEVEL_HIGH,
location: { latitude: 0, longitude: 0, altitude: 0 }
};
await this.photoOutput.capture(photoSettings);
// 获取照片数据
const photo = await this.photoOutput.getLatestPhoto();
const imageData = await photo.main.getComponent(image.ComponentType.JPEG);
return imageData;
} catch (error) {
console.error('拍照失败:', error);
return null;
}
}
// 共享摄像头到其他设备 async shareCameraToDevice(deviceId: string): Promise { try { // 这里需要实现摄像头流的编码和传输 console.log('共享摄像头到设备:', deviceId); return true; } catch (error) { console.error('共享摄像头失败:', error); return false; } }
// 释放资源 async release() { if (this.cameraInput) { await this.cameraInput.close(); }
if (this.cameraManager) {
// 停止会话并释放资源
}
} }
export default new CameraSharingManager(); 5.2 文件共享 typescript
// ets/utils/FileSharingManager.ts import fileIo from '@ohos.fileio'; import fs from '@ohos.file.fs';
class FileSharingManager { // 发送文件到其他设备 async sendFileToDevice(filePath: string, deviceId: string): Promise { try { // 读取文件内容 const file = await fileIo.open(filePath, fileIo.OpenMode.READ_ONLY); const stat = await fileIo.stat(filePath); const buffer = new ArrayBuffer(stat.size); await fileIo.read(file.fd, buffer); await fileIo.close(file.fd);
// 这里需要实现文件传输逻辑
// 实际开发中会使用分布式文件系统或网络传输
console.log(`发送文件 ${filePath} 到设备 ${deviceId}, 大小: ${stat.size} 字节`);
return true;
} catch (error) {
console.error('发送文件失败:', error);
return false;
}
}
// 从其他设备接收文件
async receiveFileFromDevice(deviceId: string, fileName: string, fileData: ArrayBuffer): Promise<string | null> {
try {
const savePath = ${getContext(this).filesDir}/${fileName};
const file = await fileIo.open(savePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
await fileIo.write(file.fd, fileData);
await fileIo.close(file.fd);
console.log(`从设备 ${deviceId} 接收文件 ${fileName}, 保存到: ${savePath}`);
return savePath;
} catch (error) {
console.error('接收文件失败:', error);
return null;
}
}
// 获取共享文件列表 async getSharedFiles(deviceId: string): Promise<Array> { try { // 这里需要从分布式存储获取文件列表 return ['document.pdf', 'photo.jpg', 'video.mp4']; } catch (error) { console.error('获取共享文件列表失败:', error); return []; } } }
export default new FileSharingManager(); 六、多端协同安全 6.1 安全认证管理 typescript
// ets/utils/SecurityManager.ts import userIAM from '@ohos.userIAM.userAuth';
class SecurityManager { // 设备认证 async authenticateDevice(deviceId: string): Promise { try { // 这里使用PIN码认证(实际应用应使用更安全的认证方式) const result = await userIAM.authenticate({ challenge: deviceId, authType: userIAM.AuthType.PIN, authTrustLevel: userIAM.AuthTrustLevel.ATL3 });
return result === userIAM.ResultCode.SUCCESS;
} catch (error) {
console.error('设备认证失败:', error);
return false;
}
}
// 数据加密 encryptData(data: string, key: string): string { // 这里实现数据加密逻辑 // 实际开发中应使用鸿蒙的安全加密框架 return btoa(data); // 简单示例,实际应用需要更安全的加密 }
// 数据解密 decryptData(encryptedData: string, key: string): string { // 这里实现数据解密逻辑 return atob(encryptedData); }
// 权限检查 checkPermission(permission: string): Promise { return new Promise((resolve) => { // 检查应用权限 // 实际开发中应使用鸿蒙的权限管理API resolve(true); }); } }
export default new SecurityManager(); 七、实战:多端协同阅读应用 typescript
// ets/pages/ReadingApp.ets @Entry @Component struct ReadingApp { @State currentBook: { id: string, title: string, content: string, progress: number } | null = null; @State connectedDevices: Array<{id: string, name: string}> = []; @State readingPosition: number = 0; @State fontSize: number = 16; @State theme: 'light' | 'dark' = 'light';
private distributedDataManager = DistributedDataManager; private continuationManager = ContinuationManager;
async aboutToAppear() { // 初始化分布式数据 await this.distributedDataManager.initialize();
// 加载阅读进度
await this.loadReadingProgress();
// 监听数据同步
this.distributedDataManager.onDataChange((data) => {
if (data.key === 'reading_progress') {
this.handleProgressSync(data.value);
}
});
}
async loadReadingProgress() { const progress = await this.distributedDataManager.get('reading_progress'); if (progress) { this.readingPosition = progress.position || 0; this.fontSize = progress.fontSize || 16; this.theme = progress.theme || 'light'; } }
handleProgressSync(progress: any) { if (progress && progress.position !== undefined) { this.readingPosition = progress.position; console.log('阅读进度已从其他设备同步'); } }
async saveProgress() { const progress = { bookId: this.currentBook?.id, position: this.readingPosition, fontSize: this.fontSize, theme: this.theme, timestamp: Date.now(), deviceId: DeviceInfoUtil.getDeviceInfo().deviceId };
await this.distributedDataManager.save('reading_progress', progress);
await this.distributedDataManager.sync();
}
async transferReading(deviceId: string) { if (!this.currentBook) return;
// 保存当前进度
await this.saveProgress();
// 开始流转
const selectedDeviceId = await this.continuationManager.showDevicePicker();
if (selectedDeviceId) {
console.log('流转阅读到设备:', selectedDeviceId);
// 这里实际会触发应用流转
// 流转后,目标设备会打开阅读应用并恢复进度
}
}
build() { Column({ space: 20 }) { // 顶部工具栏 Row({ space: 12 }) { Text(this.currentBook?.title || '选择一本书') .fontSize(18) .fontWeight(FontWeight.Bold) .layoutWeight(1)
Button('流转')
.width(80)
.height(36)
.fontSize(12)
.onClick(() => {
this.showDeviceSelector();
})
}
.width('100%')
.padding(16)
.backgroundColor(this.theme === 'dark' ? '#333333' : '#FFFFFF')
// 阅读区域
Scroll() {
Column({ space: 20 }) {
Text(this.currentBook?.content || '暂无内容')
.fontSize(this.fontSize)
.fontColor(this.theme === 'dark' ? '#FFFFFF' : '#333333')
.lineHeight(this.fontSize * 1.6)
}
.padding(20)
}
.onScroll((event: { scrollOffset: number }) => {
this.readingPosition = event.scrollOffset;
// 自动保存进度(防抖处理)
this.debouncedSave();
})
.layoutWeight(1)
.backgroundColor(this.theme === 'dark' ? '#1A1A1A' : '#F8F8F8')
// 底部控制栏
Row({ space: 20 }) {
// 字体大小控制
Row({ space: 8 }) {
Button('A-')
.width(40)
.height(40)
.fontSize(16)
.onClick(() => {
if (this.fontSize > 12) {
this.fontSize--;
this.saveProgress();
}
})
Text(`${this.fontSize}`)
.width(40)
.textAlign(TextAlign.Center)
.fontColor(this.theme === 'dark' ? '#FFFFFF' : '#333333')
Button('A+')
.width(40)
.height(40)
.fontSize(16)
.onClick(() => {
if (this.fontSize < 24) {
this.fontSize++;
this.saveProgress();
}
})
}
// 主题切换
Button(this.theme === 'light' ? '🌙' : '☀️')
.width(40)
.height(40)
.fontSize(16)
.onClick(() => {
this.theme = this.theme === 'light' ? 'dark' : 'light';
this.saveProgress();
})
// 进度显示
Text(`${Math.floor(this.readingPosition)}`)
.fontSize(14)
.fontColor(this.theme === 'dark' ? '#FFFFFF' : '#333333')
.layoutWeight(1)
.textAlign(TextAlign.End)
}
.width('100%')
.padding(16)
.backgroundColor(this.theme === 'dark' ? '#333333' : '#FFFFFF')
}
.width('100%')
.height('100%')
.backgroundColor(this.theme === 'dark' ? '#000000' : '#F5F5F5')
}
private showDeviceSelector() { // 显示设备选择器 this.continuationManager.showDevicePicker().then(deviceId => { if (deviceId) { this.transferReading(deviceId); } }); }
private debouncedSave = this.debounce(() => { this.saveProgress(); }, 1000);
private debounce(func: Function, delay: number) { let timer: number | null = null; return function(this: any, ...args: any[]) { if (timer) clearTimeout(timer); timer = setTimeout(() => { func.apply(this, args); }, delay); }; } } 八、调试与优化 8.1 多端协同调试 typescript
// ets/utils/DistributedDebugger.ts class DistributedDebugger { static enableDebugLog() { console.info('分布式调试模式已启用');
// 监听所有分布式事件
this.listenToDistributedEvents();
// 显示调试面板
this.showDebugPanel();
}
private static listenToDistributedEvents() { // 这里可以监听各种分布式事件 console.log('开始监听分布式事件...'); }
private static showDebugPanel() { // 在界面上显示调试信息 const debugInfo = { deviceId: DeviceInfoUtil.getDeviceInfo().deviceId, connectedDevices: [], dataSyncStatus: '正常', networkStatus: '在线' };
console.table(debugInfo);
}
static logDataSync(data: any) { console.group('数据同步日志'); console.log('时间:', new Date().toLocaleString()); console.log('数据:', data); console.groupEnd(); } } 8.2 性能监控 typescript
class DistributedPerformanceMonitor { private metrics: Map<string, Array> = new Map();
// 测量流转时间
static measureTransferTime(startTime: number) {
const duration = performance.now() - startTime;
console.log(流转耗时: ${duration.toFixed(2)}ms);
// 记录性能指标
this.recordMetric('transfer_time', duration);
}
// 测量数据同步时间 static measureSyncTime(dataSize: number, startTime: number) { const duration = performance.now() - startTime; const speed = dataSize / (duration / 1000); // bytes per second
console.log(`数据同步: ${dataSize} bytes, 耗时: ${duration.toFixed(2)}ms, 速度: ${(speed / 1024).toFixed(2)} KB/s`);
this.recordMetric('sync_speed', speed);
}
private static recordMetric(name: string, value: number) { let metrics = this.metrics.get(name) || []; metrics.push(value);
// 只保留最近的100个记录
if (metrics.length > 100) {
metrics = metrics.slice(-100);
}
this.metrics.set(name, metrics);
}
static getPerformanceReport() { const report: any = {};
this.metrics.forEach((values, name) => {
if (values.length > 0) {
const sum = values.reduce((a, b) => a + b, 0);
const avg = sum / values.length;
const max = Math.max(...values);
const min = Math.min(...values);
report[name] = {
count: values.length,
average: avg,
max: max,
min: min,
latest: values[values.length - 1]
};
}
});
return report;
} } 九、总结与下期预告 9.1 本文要点回顾 分布式基础:设备发现、连接和管理
应用流转:跨设备无缝接续应用体验
数据同步:分布式数据存储和实时同步
硬件共享:摄像头、文件等硬件能力共享
安全机制:多端协同的安全认证和加密
实战应用:多端协同阅读、待办等完整应用
9.2 下期预告:《鸿蒙开发之:性能优化与调试技巧》 下篇文章将深入讲解:
应用性能分析与监控
内存管理和优化
渲染性能优化
网络请求优化
启动速度优化
调试工具和技巧
动手挑战 任务1:实现多端协同画板 要求:
支持多设备同时绘画
实时同步绘画内容
支持不同颜色和画笔大小
保存和加载绘画作品
任务2:实现多端协同游戏 要求:
支持多设备联机游戏
实时同步游戏状态
支持语音聊天
游戏进度云端同步
任务3:实现智能家居控制中心 要求:
统一控制多设备家居
设备状态实时同步
支持场景模式
远程控制和自动化
将你的代码分享到评论区,我会挑选优秀实现进行详细点评!
常见问题解答 Q:多端协同需要设备都在同一个网络吗? A:通常需要在同一局域网,但鸿蒙也支持远程协同(需要通过华为账号等机制)。
Q:流转应用时数据会同步传输吗? A:流转时只传输应用状态数据,大文件数据可以通过分布式数据框架同步。
Q:如何保证多端协同的安全性? A:鸿蒙提供了端到端的加密通信、设备认证、权限控制等多层安全机制。
Q:多端协同对设备性能要求高吗? A:基础的数据同步对性能要求不高,但视频流转等实时性要求高的场景需要较好的网络和设备性能。
PS:现在HarmonyOS应用开发者认证正在做活动,初级和高级都可以免费学习及考试,赶快加入班级学习啦:【注意,考试只能从此唯一链接进入】 developer.huawei.com/consumer/cn…
版权声明:本文为《鸿蒙开发系列》第8篇,原创文章,转载请注明出处。
标签:#HarmonyOS #鸿蒙开发 #多端协同 #分布式 #应用流转 #华为开发者 ————————————————