news 2025/12/17 17:37:12

Harmony开发之跨设备调用——远程启动Ability

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Harmony开发之跨设备调用——远程启动Ability

Harmony开发之跨设备调用——远程启动Ability

引入:打破设备边界的应用能力

在传统的移动应用开发中,每个应用都运行在独立的设备上,设备间的应用能力无法共享。而HarmonyOS的跨设备调用能力,让应用可以像调用本地Ability一样,无缝调用其他设备上的Ability,真正实现了"一次开发,多端部署,跨端流转"的分布式体验。

想象一下这样的场景:你在手机上浏览一篇长文,走到客厅后可以继续在智慧屏上阅读;在平板上编辑文档时,可以直接调用手机上的摄像头拍照插入图片。这些场景的实现,都依赖于HarmonyOS的跨设备调用能力。

一、跨设备调用核心概念

1.1 什么是跨设备调用

跨设备调用(Cross-Device Call)是指一个设备上的应用能够发现、连接并调用另一个设备上的Ability,就像调用本地Ability一样简单。这种能力基于HarmonyOS的分布式软总线技术,实现了设备间的能力共享和协同。

1.2 核心组件

Want:跨设备调用的核心载体,封装了目标Ability的信息和调用意图。

WantAgent:Want的封装器,用于延迟执行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匹配方式启动远程Ability:

import { AbilityConstant, common, UIAbility } from '@kit.AbilityKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; async function startRemoteAbilityByAction(): Promise<void> { 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(): Promise<void> { 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(): Promise<void> { 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(): Promise<void> { 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(): Promise<void> { 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(): Promise<void> { 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 创建WantAgent

import { WantAgent } from '@kit.AbilityKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; async function createWantAgent(): Promise<WantAgent.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 触发WantAgent

import { WantAgent } from '@kit.AbilityKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; async function triggerWantAgent(wantAgent: WantAgent.WantAgent): Promise<void> { 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 在通知中使用WantAgent

import { notificationManager } from '@kit.NotificationKit'; import { WantAgent } from '@kit.AbilityKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; async function createNotificationWithWantAgent(): Promise<void> { 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(): Promise<void> { 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(): Promise<void> { 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): Promise<void> { 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): Promise<string> { 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): Promise<void> { 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): Promise<void> { 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: Map<string, common.RemoteAbilityConnection> = new Map(); private maxConnections: number = 5; // 获取连接 async getConnection(deviceId: string, bundleName: string, abilityName: string): Promise<common.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): Promise<common.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): Promise<void> { 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): Promise<void> { return new Promise(resolve => setTimeout(resolve, ms)); } }

7.3 权限检查与申请

import { abilityAccessCtrl } from '@kit.AbilityAccessCtrlKit'; async function checkAndRequestPermissions(): Promise<boolean> { 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分布式能力的核心,它打破了设备间的物理边界,让应用能力可以在多设备间自由流转。通过本文的学习,你应该掌握了:

核心要点回顾:

  1. Want与WantAgent:跨设备调用的核心数据结构和执行器
  2. 隐式与显式启动:两种启动远程Ability的方式
  3. 连接模式:建立长连接进行持续通信
  4. 错误处理与重试:保证跨设备调用的可靠性

最佳实践:

  • 合理使用连接池管理跨设备连接
  • 实现完善的错误处理和重试机制
  • 在适当的时机清理连接资源
  • 遵循最小权限原则申请权限

跨设备调用技术的正确运用,将为你的HarmonyOS应用带来真正的分布式体验,让用户在不同设备间无缝切换,享受一致的应用服务。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/15 11:00:28

27、Linux与UNIX系统管理操作指南

Linux与UNIX系统管理操作指南 1. 用户与组管理 在进行系统管理时,用户和组的管理是基础且重要的部分。以Kim登录系统为例,在Kim登录前,需要确保默认组存在。若默认组不存在,就需要编辑 /etc/group 文件来创建该组,同时要保证使用的GID是唯一的,并且与 /etc/passwd …

作者头像 李华
网站建设 2025/12/15 10:59:15

基于springboot + vue学生选课信息管理系统

学生信息管理 目录 基于springboot vue学生信息管理系统 一、前言 二、系统功能演示 详细视频演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue学生选课信息管理系统 一、…

作者头像 李华
网站建设 2025/12/15 10:56:26

2026毕设ssm+vue基于的住房保障系统论文+程序

本系统&#xff08;程序源码&#xff09;带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、选题背景 关于住房保障信息化问题的研究&#xff0c;现有研究主要以宏观政策评估、融资模式及土建技术为主&#xff0c;专门针对“保障…

作者头像 李华