网站链接锚文字怎么做,做seo是什么意思,农村电商网站建设ppt,怎样进行网络营销吸引顾客Harmony开发之跨设备调用——远程启动Ability
引入#xff1a;打破设备边界的应用能力
在传统的移动应用开发中#xff0c;每个应用都运行在独立的设备上#xff0c;设备间的应用能力无法共享。而HarmonyOS的跨设备调用能力#xff0c;让应用可以像调用本地Ability一样打破设备边界的应用能力在传统的移动应用开发中每个应用都运行在独立的设备上设备间的应用能力无法共享。而HarmonyOS的跨设备调用能力让应用可以像调用本地Ability一样无缝调用其他设备上的Ability真正实现了一次开发多端部署跨端流转的分布式体验。想象一下这样的场景你在手机上浏览一篇长文走到客厅后可以继续在智慧屏上阅读在平板上编辑文档时可以直接调用手机上的摄像头拍照插入图片。这些场景的实现都依赖于HarmonyOS的跨设备调用能力。一、跨设备调用核心概念1.1 什么是跨设备调用跨设备调用Cross-Device Call是指一个设备上的应用能够发现、连接并调用另一个设备上的Ability就像调用本地Ability一样简单。这种能力基于HarmonyOS的分布式软总线技术实现了设备间的能力共享和协同。1.2 核心组件Want跨设备调用的核心载体封装了目标Ability的信息和调用意图。WantAgentWant的封装器用于延迟执行Want常用于通知、快捷方式等场景。AbilityManager提供跨设备调用的管理接口包括启动、连接、断开等操作。1.3 调用模式对比调用模式特点适用场景隐式启动通过action匹配目标Ability系统自动选择通用功能调用如拍照、分享显式启动明确指定目标Ability的bundleName和abilityName特定应用间的协同带返回值启动启动Ability并等待返回结果需要获取返回数据的场景连接模式建立长连接持续通信跨设备数据同步、远程控制二、Want与WantAgent详解2.1 Want基本结构Want是跨设备调用的核心数据结构包含以下关键信息interface Want { deviceId?: string; // 目标设备ID空表示本地设备 bundleName?: string; // 目标应用包名 abilityName?: string; // 目标Ability名称 action?: string; // 动作标识 entities?: string[]; // 实体类型 uri?: string; // URI数据 type?: string; // MIME类型 parameters?: { [key: string]: any }; // 参数数据 }2.2 WantAgent工作流程WantAgent是对Want的封装支持延迟执行和权限控制// WantAgent创建流程 const wantAgentInfo: WantAgent.WantAgentInfo { wants: [want], // 要执行的Want数组 operationType: WantAgent.OperationType.START_ABILITIES, // 操作类型 requestCode: 0, // 请求码用于回调识别 wantAgentFlags: [WantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG] // 标志位 };三、跨设备调用实战开发3.1 权限配置在module.json5中配置跨设备调用所需权限{ reqPermissions: [ { name: ohos.permission.DISTRIBUTED_DATASYNC, reason: 跨设备数据同步 }, { name: ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE, reason: 监听设备状态变化 }, { name: ohos.permission.GET_DISTRIBUTED_DEVICE_INFO, reason: 获取分布式设备信息 } ] }3.2 隐式启动远程Ability通过action匹配方式启动远程Abilityimport { AbilityConstant, common, UIAbility } from kit.AbilityKit; import { BusinessError } from kit.BasicServicesKit; import { hilog } from kit.PerformanceAnalysisKit; async function startRemoteAbilityByAction(): Promisevoid { try { const want { action: action.system.open, // 系统打开动作 entities: [entity.system.browser], // 浏览器实体 uri: https://www.example.com, // 要打开的URL type: text/html }; const context getContext(this) as common.UIAbilityContext; await context.startAbility(want); hilog.info(0x0000, testTag, Remote ability started successfully); } catch (error) { hilog.error(0x0000, testTag, Failed to start remote ability: ${JSON.stringify(error)}); } }3.3 显式启动远程Ability明确指定目标Ability的详细信息import { AbilityConstant, common, UIAbility } from kit.AbilityKit; import { BusinessError } from kit.BasicServicesKit; import { hilog } from kit.PerformanceAnalysisKit; async function startRemoteAbilityExplicitly(): Promisevoid { try { const want { deviceId: 1234567890, // 目标设备ID bundleName: com.example.remoteapp, abilityName: RemoteAbility, parameters: { key1: value1, key2: 100 } }; const context getContext(this) as common.UIAbilityContext; await context.startAbility(want); hilog.info(0x0000, testTag, Remote ability started successfully); } catch (error) { hilog.error(0x0000, testTag, Failed to start remote ability: ${JSON.stringify(error)}); } }3.4 带返回值启动远程Ability启动远程Ability并等待返回结果import { AbilityConstant, common, UIAbility } from kit.AbilityKit; import { BusinessError } from kit.BasicServicesKit; import { hilog } from kit.PerformanceAnalysisKit; async function startRemoteAbilityForResult(): Promisevoid { try { const want { deviceId: 1234567890, bundleName: com.example.remoteapp, abilityName: RemoteAbility, parameters: { requestData: some data } }; const context getContext(this) as common.UIAbilityContext; await context.startAbilityForResult(want, (error: BusinessError, data: AbilityConstant.AbilityResult) { if (error) { hilog.error(0x0000, testTag, Ability result error: ${JSON.stringify(error)}); return; } if (data.resultCode AbilityConstant.ResultCode.RESULT_OK) { const resultData data.want?.parameters; hilog.info(0x0000, testTag, Ability result: ${JSON.stringify(resultData)}); } else { hilog.warn(0x0000, testTag, Ability result canceled: ${data.resultCode}); } }); } catch (error) { hilog.error(0x0000, testTag, Failed to start remote ability: ${JSON.stringify(error)}); } }3.5 连接远程Ability建立与远程Ability的长连接import { AbilityConstant, common, UIAbility } from kit.AbilityKit; import { BusinessError } from kit.BasicServicesKit; import { hilog } from kit.PerformanceAnalysisKit; class RemoteConnection implements common.RemoteAbilityConnection { private connectionId: number -1; private remoteProxy: common.RemoteProxy | null null; // 连接建立回调 onAbilityConnectDone(elementName: common.ElementName, remote: common.RemoteProxy, resultCode: number): void { if (resultCode 0) { this.connectionId elementName.abilityName.length; this.remoteProxy remote; hilog.info(0x0000, testTag, Remote ability connected successfully); // 发送数据到远程Ability this.sendDataToRemote(); } else { hilog.error(0x0000, testTag, Failed to connect remote ability: ${resultCode}); } } // 连接断开回调 onAbilityDisconnectDone(elementName: common.ElementName, resultCode: number): void { hilog.info(0x0000, testTag, Remote ability disconnected); this.connectionId -1; this.remoteProxy null; } // 发送数据到远程Ability async sendDataToRemote(): Promisevoid { if (!this.remoteProxy) { return; } try { const data { message: Hello from local device, timestamp: Date.now() }; await this.remoteProxy.sendRequest(1, data, {}); hilog.info(0x0000, testTag, Data sent to remote ability); } catch (error) { hilog.error(0x0000, testTag, Failed to send data: ${JSON.stringify(error)}); } } // 建立连接 async connectRemoteAbility(): Promisevoid { try { const want { deviceId: 1234567890, bundleName: com.example.remoteapp, abilityName: RemoteServiceAbility }; const context getContext(this) as common.UIAbilityContext; await context.connectAbility(want, this); hilog.info(0x0000, testTag, Connecting to remote ability...); } catch (error) { hilog.error(0x0000, testTag, Failed to connect remote ability: ${JSON.stringify(error)}); } } // 断开连接 async disconnectRemoteAbility(): Promisevoid { if (this.connectionId -1) { return; } try { const context getContext(this) as common.UIAbilityContext; await context.disconnectAbility(this); hilog.info(0x0000, testTag, Disconnecting from remote ability...); } catch (error) { hilog.error(0x0000, testTag, Failed to disconnect: ${JSON.stringify(error)}); } } } // 使用示例 const remoteConnection new RemoteConnection(); await remoteConnection.connectRemoteAbility();四、远程Ability的实现4.1 Service Ability实现远程Service Ability需要实现IAbilityConnection接口import { AbilityConstant, common, UIAbility } from kit.AbilityKit; import { BusinessError } from kit.BasicServicesKit; import { hilog } from kit.PerformanceAnalysisKit; export default class RemoteServiceAbility extends UIAbility { private connection: common.RemoteAbilityConnection | null null; onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { hilog.info(0x0000, testTag, RemoteServiceAbility onCreate); // 注册连接回调 this.connection { onAbilityConnectDone: this.onConnectDone.bind(this), onAbilityDisconnectDone: this.onDisconnectDone.bind(this) }; } onConnectDone(elementName: common.ElementName, remote: common.RemoteProxy, resultCode: number): void { if (resultCode 0) { hilog.info(0x0000, testTag, Remote client connected); // 设置消息处理回调 remote.setReceiveRequestCallback(this.handleRequest.bind(this)); } } onDisconnectDone(elementName: common.ElementName, resultCode: number): void { hilog.info(0x0000, testTag, Remote client disconnected); } // 处理来自客户端的请求 handleRequest(code: number, data: any, reply: common.MessageParcel, option: common.MessageOption): void { hilog.info(0x0000, testTag, Received request code: ${code}, data: ${JSON.stringify(data)}); switch (code) { case 1: // 处理消息请求 this.handleMessageRequest(data, reply); break; case 2: // 处理数据请求 this.handleDataRequest(data, reply); break; default: hilog.warn(0x0000, testTag, Unknown request code: ${code}); reply.writeInt(AbilityConstant.ResultCode.RESULT_CANCELED); } } // 处理消息请求 private handleMessageRequest(data: any, reply: common.MessageParcel): void { const message data.message; hilog.info(0x0000, testTag, Received message: ${message}); // 处理消息并返回结果 const result { status: success, receivedAt: Date.now(), processedMessage: message.toUpperCase() }; reply.writeInt(AbilityConstant.ResultCode.RESULT_OK); reply.writeString(JSON.stringify(result)); } // 处理数据请求 private handleDataRequest(data: any, reply: common.MessageParcel): void { const requestData data.requestData; hilog.info(0x0000, testTag, Processing data: ${JSON.stringify(requestData)}); // 模拟数据处理 const processedData this.processData(requestData); reply.writeInt(AbilityConstant.ResultCode.RESULT_OK); reply.writeString(JSON.stringify(processedData)); } // 数据处理逻辑 private processData(data: any): any { return { original: data, processed: true, timestamp: Date.now(), result: Data processed successfully }; } }4.2 Page Ability实现远程Page Ability需要处理启动参数和返回结果import { AbilityConstant, common, UIAbility } from kit.AbilityKit; import { BusinessError } from kit.BasicServicesKit; import { hilog } from kit.PerformanceAnalysisKit; export default class RemotePageAbility extends UIAbility { private result: AbilityConstant.AbilityResult { resultCode: AbilityConstant.ResultCode.RESULT_CANCELED, want: undefined }; onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { hilog.info(0x0000, testTag, RemotePageAbility onCreate); // 处理启动参数 const parameters want.parameters; if (parameters) { hilog.info(0x0000, testTag, Launch parameters: ${JSON.stringify(parameters)}); } } onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void { hilog.info(0x0000, testTag, RemotePageAbility onNewWant); } onDestroy(): void { hilog.info(0x0000, testTag, RemotePageAbility onDestroy); } // 设置返回结果 setResult(resultCode: number, resultData?: any): void { this.result.resultCode resultCode; if (resultData) { this.result.want { parameters: resultData }; } } // 返回结果给调用方 terminateSelfWithResult(): void { const context getContext(this) as common.UIAbilityContext; context.terminateSelfWithResult(this.result, (error: BusinessError) { if (error) { hilog.error(0x0000, testTag, Failed to terminate with result: ${JSON.stringify(error)}); } }); } }五、WantAgent高级用法5.1 创建WantAgentimport { WantAgent } from kit.AbilityKit; import { BusinessError } from kit.BasicServicesKit; import { hilog } from kit.PerformanceAnalysisKit; async function createWantAgent(): PromiseWantAgent.WantAgent { try { const want { action: action.system.open, entities: [entity.system.browser], uri: https://www.example.com }; const wantAgentInfo: WantAgent.WantAgentInfo { wants: [want], operationType: WantAgent.OperationType.START_ABILITIES, requestCode: 1001, wantAgentFlags: [WantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG] }; const wantAgent await WantAgent.getWantAgent(wantAgentInfo); hilog.info(0x0000, testTag, WantAgent created successfully); return wantAgent; } catch (error) { hilog.error(0x0000, testTag, Failed to create WantAgent: ${JSON.stringify(error)}); throw error; } }5.2 触发WantAgentimport { WantAgent } from kit.AbilityKit; import { BusinessError } from kit.BasicServicesKit; import { hilog } from kit.PerformanceAnalysisKit; async function triggerWantAgent(wantAgent: WantAgent.WantAgent): Promisevoid { try { await WantAgent.trigger(wantAgent, undefined, { onCompleted: (code: number, result: any, want: Want) { hilog.info(0x0000, testTag, WantAgent triggered, code: ${code}); } }); } catch (error) { hilog.error(0x0000, testTag, Failed to trigger WantAgent: ${JSON.stringify(error)}); } }5.3 在通知中使用WantAgentimport { notificationManager } from kit.NotificationKit; import { WantAgent } from kit.AbilityKit; import { BusinessError } from kit.BasicServicesKit; import { hilog } from kit.PerformanceAnalysisKit; async function createNotificationWithWantAgent(): Promisevoid { try { // 创建WantAgent const want { action: action.system.open, entities: [entity.system.browser], uri: https://www.example.com }; const wantAgentInfo: WantAgent.WantAgentInfo { wants: [want], operationType: WantAgent.OperationType.START_ABILITIES, requestCode: 1002 }; const wantAgent await WantAgent.getWantAgent(wantAgentInfo); // 创建通知 const notificationRequest: notificationManager.NotificationRequest { id: 1001, slotId: default_slot, content: { notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, normal: { title: 跨设备通知, text: 点击打开远程浏览器 } }, wantAgent: wantAgent }; await notificationManager.publish(notificationRequest); hilog.info(0x0000, testTag, Notification with WantAgent published); } catch (error) { hilog.error(0x0000, testTag, Failed to create notification: ${JSON.stringify(error)}); } }六、完整实战案例跨设备文件共享6.1 场景描述实现一个跨设备文件共享应用用户可以在手机端选择文件通过跨设备调用将文件发送到平板端平板端接收文件并显示传输进度。6.2 手机端实现发送方import { AbilityConstant, common, UIAbility } from kit.AbilityKit; import { BusinessError } from kit.BasicServicesKit; import { hilog } from kit.PerformanceAnalysisKit; import { fileIo } from kit.FileKit; class FileSenderAbility extends UIAbility { private remoteConnection: common.RemoteAbilityConnection | null null; private filePath: string ; private targetDeviceId: string ; // 选择文件并发送 async selectAndSendFile(): Promisevoid { try { // 选择文件实际应用中需要文件选择器 this.filePath /data/storage/el2/base/files/sample.txt; // 读取文件内容 const fileContent await this.readFile(this.filePath); // 建立远程连接 await this.connectToReceiver(); // 发送文件 await this.sendFile(fileContent); } catch (error) { hilog.error(0x0000, testTag, File send failed: ${JSON.stringify(error)}); } } // 建立到接收方的连接 async connectToReceiver(): Promisevoid { const want { deviceId: this.targetDeviceId, bundleName: com.example.filereceiver, abilityName: FileReceiverServiceAbility }; this.remoteConnection { onAbilityConnectDone: this.onConnectDone.bind(this), onAbilityDisconnectDone: this.onDisconnectDone.bind(this) }; const context getContext(this) as common.UIAbilityContext; await context.connectAbility(want, this.remoteConnection); } // 发送文件数据 async sendFile(fileContent: string): Promisevoid { if (!this.remoteConnection) { throw new Error(Remote connection not established); } const data { fileName: sample.txt, fileSize: fileContent.length, content: fileContent, timestamp: Date.now() }; await this.remoteConnection.sendRequest(1, data, {}); hilog.info(0x0000, testTag, File sent successfully); } // 读取文件 async readFile(filePath: string): Promisestring { const file await fileIo.open(filePath, fileIo.OpenMode.READ_ONLY); try { const stat await fileIo.stat(filePath); const buffer new ArrayBuffer(stat.size); await fileIo.read(file.fd, buffer, { position: 0 }); return new TextDecoder().decode(buffer); } finally { await fileIo.close(file.fd); } } // 连接建立回调 onConnectDone(elementName: common.ElementName, remote: common.RemoteProxy, resultCode: number): void { if (resultCode 0) { hilog.info(0x0000, testTag, Connected to receiver); } } // 连接断开回调 onDisconnectDone(elementName: common.ElementName, resultCode: number): void { hilog.info(0x0000, testTag, Disconnected from receiver); } }6.3 平板端实现接收方import { AbilityConstant, common, UIAbility } from kit.AbilityKit; import { BusinessError } from kit.BasicServicesKit; import { hilog } from kit.PerformanceAnalysisKit; import { fileIo } from kit.FileKit; export default class FileReceiverServiceAbility extends UIAbility { private connection: common.RemoteAbilityConnection | null null; onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { hilog.info(0x0000, testTag, FileReceiverServiceAbility onCreate); this.connection { onAbilityConnectDone: this.onConnectDone.bind(this), onAbilityDisconnectDone: this.onDisconnectDone.bind(this) }; } onConnectDone(elementName: common.ElementName, remote: common.RemoteProxy, resultCode: number): void { if (resultCode 0) { hilog.info(0x0000, testTag, File sender connected); // 设置请求处理回调 remote.setReceiveRequestCallback(this.handleFileRequest.bind(this)); } } onDisconnectDone(elementName: common.ElementName, resultCode: number): void { hilog.info(0x0000, testTag, File sender disconnected); } // 处理文件传输请求 async handleFileRequest(code: number, data: any, reply: common.MessageParcel, option: common.MessageOption): Promisevoid { if (code 1) { await this.saveFile(data); reply.writeInt(AbilityConstant.ResultCode.RESULT_OK); reply.writeString(File received successfully); } else { reply.writeInt(AbilityConstant.ResultCode.RESULT_CANCELED); } } // 保存接收到的文件 async saveFile(fileData: any): Promisevoid { const { fileName, content } fileData; const savePath /data/storage/el2/base/files/received/${fileName}; // 确保目录存在 await fileIo.mkdir(/data/storage/el2/base/files/received, fileIo.Mode.IRWXU); // 写入文件 const file await fileIo.open(savePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE); try { const buffer new TextEncoder().encode(content); await fileIo.write(file.fd, buffer); hilog.info(0x0000, testTag, File saved: ${savePath}); } finally { await fileIo.close(file.fd); } } }七、性能优化与最佳实践7.1 连接池管理对于需要频繁跨设备调用的应用建议使用连接池管理连接class ConnectionPool { private connections: Mapstring, common.RemoteAbilityConnection new Map(); private maxConnections: number 5; // 获取连接 async getConnection(deviceId: string, bundleName: string, abilityName: string): Promisecommon.RemoteAbilityConnection { const key ${deviceId}_${bundleName}_${abilityName}; if (this.connections.has(key)) { return this.connections.get(key)!; } // 清理过期的连接 if (this.connections.size this.maxConnections) { this.cleanupIdleConnections(); } const connection await this.createConnection(deviceId, bundleName, abilityName); this.connections.set(key, connection); return connection; } // 创建新连接 private async createConnection(deviceId: string, bundleName: string, abilityName: string): Promisecommon.RemoteAbilityConnection { const want { deviceId, bundleName, abilityName }; const context getContext(this) as common.UIAbilityContext; return new Promise((resolve, reject) { const connection: common.RemoteAbilityConnection { onAbilityConnectDone: (elementName, remote, resultCode) { if (resultCode 0) { resolve(connection); } else { reject(new Error(Connection failed: ${resultCode})); } }, onAbilityDisconnectDone: () { this.connections.delete(${deviceId}_${bundleName}_${abilityName}); } }; context.connectAbility(want, connection); }); } // 清理空闲连接 private cleanupIdleConnections(): void { // 实现连接清理逻辑 } }7.2 错误处理与重试class CrossDeviceCallManager { private maxRetries: number 3; private retryDelay: number 1000; // 1秒 // 带重试的跨设备调用 async startAbilityWithRetry(want: Want, maxRetries: number this.maxRetries): Promisevoid { for (let attempt 1; attempt maxRetries; attempt) { try { const context getContext(this) as common.UIAbilityContext; await context.startAbility(want); return; // 成功则返回 } catch (error) { if (attempt maxRetries) { throw error; // 最后一次尝试仍然失败 } // 指数退避延迟 const delay this.retryDelay * Math.pow(2, attempt - 1); await this.delay(delay); } } } // 延迟函数 private delay(ms: number): Promisevoid { return new Promise(resolve setTimeout(resolve, ms)); } }7.3 权限检查与申请import { abilityAccessCtrl } from kit.AbilityAccessCtrlKit; async function checkAndRequestPermissions(): Promiseboolean { try { const atManager abilityAccessCtrl.createAtManager(); // 检查权限 const permissions [ ohos.permission.DISTRIBUTED_DATASYNC, ohos.permission.GET_DISTRIBUTED_DEVICE_INFO ]; const grantStatus await atManager.checkAccessToken(permissions); // 如果权限未授予请求权限 if (grantStatus.authList.some(item item.grantStatus abilityAccessCtrl.GrantStatus.PERMISSION_DENIED)) { await atManager.requestPermissionsFromUser(permissions); // 再次检查权限 const newGrantStatus await atManager.checkAccessToken(permissions); return newGrantStatus.authList.every(item item.grantStatus abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED); } return true; } catch (error) { console.error(Permission check failed:, error); return false; } }八、常见问题与解决方案8.1 设备发现失败问题无法发现目标设备。解决方案检查设备是否在同一局域网确认目标设备已开启分布式能力检查设备发现权限是否已授予8.2 连接超时问题跨设备连接建立超时。解决方案增加连接超时时间实现重试机制检查网络状况8.3 权限拒绝问题跨设备调用因权限不足失败。解决方案在module.json5中声明所需权限运行时动态请求用户授权优雅处理权限拒绝的情况8.4 数据序列化错误问题跨设备传输的数据无法正确序列化。解决方案确保传输的数据是可序列化的JSON对象避免传输循环引用的对象对于复杂对象使用自定义序列化方法总结跨设备调用是HarmonyOS分布式能力的核心它打破了设备间的物理边界让应用能力可以在多设备间自由流转。通过本文的学习你应该掌握了核心要点回顾Want与WantAgent跨设备调用的核心数据结构和执行器隐式与显式启动两种启动远程Ability的方式连接模式建立长连接进行持续通信错误处理与重试保证跨设备调用的可靠性最佳实践合理使用连接池管理跨设备连接实现完善的错误处理和重试机制在适当的时机清理连接资源遵循最小权限原则申请权限跨设备调用技术的正确运用将为你的HarmonyOS应用带来真正的分布式体验让用户在不同设备间无缝切换享受一致的应用服务。