概述

隔空传送是华为鸿蒙操作系统(HarmonyOS)中 Share Kit(分享服务)推出的一项创新跨端传输能力。该功能允许用户在多个鸿蒙设备之间,通过“一抓一放”的隔空手势,实现内容的快速分享与传输,无需物理接触或复杂操作,极大提升了多设备协同的便捷性。

核心场景

  • 用户在某设备(如手机)上浏览内容(网页、图片、文档等)。
  • 用户通过隔空手势(握拳抓取后向另一设备方向放开)将内容“投放”到目标设备(如平板、智慧屏等)。
  • 目标设备自动接收并打开对应内容,实现端到端的直达体验。

关键特性

  • 手势触发:隔空抓取手势与隔空截屏共用,用户无需触碰屏幕即可完成分享。
  • 跨端直达:通过 App Linking 技术,接收端可以直接打开应用内对应页面,而不仅仅是分享一个链接或文件。
  • 设备信任:仅允许在可信任设备间传输,保障安全。
  • 系统联动:与隔空截屏联动,根据开关状态和场景自动决定是否保存截屏或传输原图。

开发者适配要点

为了让应用支持隔空传送,开发者需要:

  1. 在应用中注册隔空传送事件监听。
  2. 在事件回调中构建分享数据(包含 App Linking 链接、缩略图等)。
  3. 在页面生命周期中正确注册和注销监听,确保应用在前台可分享页面时才响应手势。

设备侧隔空传送开关配置

开启路径

使用隔空传送功能前,用户需要在设备上手动开启开关。开启路径如下:

设置 > 系统 > 快捷启动和手势 > 隔空传送

只有开启该开关后,系统才会响应隔空抓取手势,并触发后续的传送逻辑。

与隔空截屏的联动规则

隔空传送与隔空截屏共用相同的手势(握拳抓取),两者的开关状态会交叉影响最终行为。详细规则如下表所示:

隔空传送开关状态 隔空截屏开关状态 当前界面已注册隔空传送事件 行为描述
开启 开启 图库场景:传输原图;其他场景:传送截屏。卡片下方出现“保存截屏至本机”选项(默认不保存),用户可手动勾选。
开启 开启 仅截屏,不传送。
开启 关闭 图库场景:传输原图;其他场景:无截屏,不传送。
开启 关闭 无截屏,不传送。
关闭 开启 任意 仅截屏,不传送。
关闭 关闭 任意 无截屏,不传送。

联动细节详细说明

  • 当两个开关同时开启,且当前界面已注册隔空传送事件时,用户抓取握拳会同时触发隔空传送和隔空截屏。此时,隔空传送的卡片下方会同步出现“保存截屏至本机”的提示(首次默认不保存)。
  • 用户可手动勾选“保存截屏至本机”,勾选后,传送的同时截屏图片会被保存至图库。系统会记录本次选择结果,并将其作为下次操作的默认值。
  • 如果隔空传送开启但隔空截屏关闭,则只有在图库场景下才能传输原图,其他场景既不截屏也不传送。
  • 如果隔空传送关闭,则无论隔空截屏是否开启,均不会发生传送行为。

开发者注意

  • 应用只有在前台且已注册隔空传送监听事件时,用户手势才会触发传送逻辑。因此,适配的关键在于合理注册和注销监听。
  • 如果应用未注册监听,即使设备开关开启,用户手势也只会触发系统默认行为(如仅截屏),不会调用应用内逻辑。
  • 图库场景下的“传输原图”属于系统行为,与第三方应用无关;第三方应用通常处理“其他场景”下的截屏传送或自定义内容传送。

可信任设备间传输机制

隔空传送的目标设备必须是可信任设备,信任关系的建立方式如下:

  1. 相同华为账号:若发送端与接收端登录了相同的华为账号,则设备默认可信,无需额外确认即可传输。
  2. 不同华为账号:若双端未登录相同华为账号,系统会询问用户是否信任对端设备。用户需要在两端同时确认信任。一旦双方均信任,则在 1 小时内 再次传输无需重复确认。

机制说明

  • 信任确认由系统自动完成,开发者无需在应用中处理信任逻辑。
  • 该机制确保了传输的安全性,同时减少了频繁确认的打扰。
  • 对于开发者而言,只需在接收端正确处理传入的数据(例如通过 App Linking 打开对应页面),信任关系由系统保障。

应用适配隔空传送的详细步骤(分享 App Linking 直达应用)

为了通过隔空传送实现内容直达应用(即接收端点击卡片后直接打开应用内对应页面),应用必须接入 App Linking(应用链接)技术,并按照以下步骤完成隔空传送事件的适配。

前提条件与注意事项

前提条件

  • 设备已开启隔空传送开关(设置 > 系统 > 快捷启动和手势 > 隔空传送)。
  • 应用已完成 App Linking 的接入和配置(参考:使用 App Linking 实现应用间跳转,具体配置步骤略)。
  • 应用需要获取到有效的 App Linking 链接,该链接能够直接跳转到应用内特定页面。

注意事项

  • 当应用进入可分享页面时,必须使用 harmonyShare.on('gesturesShare') 方法注册隔空传送监听事件。
  • 当应用离开可分享页面(包括应用退至后台等场景)时,必须使用 harmonyShare.off('gesturesShare') 方法取消隔空传送监听事件。
  • 收到隔空传送分享事件回调后,建议在 3 秒内 调用 sharableTarget.share() 方法发起分享,否则可能导致超时失败。

开发步骤

步骤 1:导入相关模块

在 TypeScript/ArkTS 代码中导入所需模块:

import { uniformTypeDescriptor as utd } from '@kit.ArkData';
import { systemShare, harmonyShare } from '@kit.ShareKit';
import { fileUri } from '@kit.CoreFileKit';

模块说明

  • uniformTypeDescriptor:来自 @kit.ArkData,提供统一数据类型描述符(UTD)枚举,用于声明分享数据的 MIME 类型。这里使用 UniformDataType.HYPERLINK 表示超链接类型。
  • systemShare:来自 @kit.ShareKit,提供 SharedData 类,用于构建分享数据对象。
  • harmonyShare:来自 @kit.ShareKit,提供隔空传送事件监听接口,包括 onoff 方法。
  • fileUri:来自 @kit.CoreFileKit,提供 getUriFromPath 方法,用于将本地文件路径转换为 URI 格式,供缩略图使用。

步骤 2:定义隔空传送分享事件监听/取消监听方法

在组件或页面中定义回调函数和处理方法。回调函数会在用户触发隔空传送手势且当前设备被识别为发送端时被调用,参数 sharableTarget 表示本次传送的目标。

private immersiveCallback = (sharableTarget: harmonyShare.SharableTarget) => {
  let uiContext: UIContext = this.getUIContext();
  let contextFaker: Context = uiContext.getHostContext() as Context;
  // 仅为示例,请替换为实际存在的文件路径(用于缩略图)
  let filePath = contextFaker.filesDir + '/exampleKnock1.jpg'; 
  let shareData: systemShare.SharedData = new systemShare.SharedData({
    utd: utd.UniformDataType.HYPERLINK,      // 分享类型为超链接
    content: 'https://sharekitdemo.drcn.agconnect.link/ZB3p', // 目标 App Linking 链接
    thumbnailUri: fileUri.getUriFromPath(filePath), // 缩略图 URI
    title: '隔空传送分享卡片标题',
    description: '隔空传送分享卡片描述'
  });
  // 调用 share 方法发起实际分享
  sharableTarget.share(shareData);
}

private immersiveListening() {
  harmonyShare.on('gesturesShare', this.immersiveCallback);
}

private immersiveDisablingListening() {
  harmonyShare.off('gesturesShare', this.immersiveCallback);
}

代码逐行解析

  1. private immersiveCallback = (sharableTarget: harmonyShare.SharableTarget) => { ... }

    • 定义一个箭头函数作为回调,类型为 (sharableTarget: SharableTarget) => void
    • 当用户隔空抓取且当前应用已注册监听时,系统会调用此函数,并传入一个 SharableTarget 对象,代表接收端设备。
  2. let uiContext: UIContext = this.getUIContext();

    • 获取当前组件的 UI 上下文(UIContext),用于后续获取宿主上下文。
  3. let contextFaker: Context = uiContext.getHostContext() as Context;

    • 通过 uiContext.getHostContext() 获取宿主上下文,并转换为 Context 类型。这里命名为 contextFaker 表示仅为演示使用,实际开发中应直接使用组件的上下文。
  4. let filePath = contextFaker.filesDir + '/exampleKnock1.jpg';

    • 构建一个本地文件路径,用于缩略图。注意:示例中使用了假想路径,实际开发中需替换为应用沙箱内真实存在的图片文件路径。
  5. let shareData: systemShare.SharedData = new systemShare.SharedData({ ... });

    • 创建 SharedData 对象,该对象封装了要分享的数据。

    • utd: utd.UniformDataType.HYPERLINK

      • 指定分享数据的统一类型为超链接(HYPERLINK)。使用 UTD 可以精确描述数据类型,接收端系统会根据该类型进行相应处理。
    • content: 'https://sharekitdemo.drcn.agconnect.link/ZB3p'

      • 分享的具体内容,这里是 App Linking 链接。该链接必须已在 AppGallery Connect 中配置,并且能够正确跳转到应用内指定页面。
    • thumbnailUri: fileUri.getUriFromPath(filePath)

      • 设置卡片缩略图的 URI。fileUri.getUriFromPath 将本地文件路径转换为 URI,接收端卡片会显示该缩略图。
    • title: '隔空传送分享卡片标题'

      • 接收端卡片标题,用于简短描述分享内容。
    • description: '隔空传送分享卡片描述'

      • 接收端卡片描述,用于补充说明。
  6. sharableTarget.share(shareData);

    • 调用 sharableTargetshare 方法,将 shareData 发送到接收端。必须在回调触发后 3 秒内调用,否则可能超时失败。
  7. private immersiveListening() { harmonyShare.on('gesturesShare', this.immersiveCallback); }

    • 注册隔空传送监听。harmonyShare.on 的第一个参数固定为 'gesturesShare',第二个参数为回调函数。
    • 调用此方法后,当用户在前台且设备开关开启时做出隔空抓取手势,系统会调用 immersiveCallback
  8. private immersiveDisablingListening() { harmonyShare.off('gesturesShare', this.immersiveCallback); }

    • 取消隔空传送监听。harmonyShare.off 的第一个参数同样为 'gesturesShare',第二个参数为要移除的回调函数(必须与注册时相同引用)。
    • 调用此方法后,用户手势将不再触发该回调。

步骤 3:在页面生命周期中注册与注销监听

在页面(Entry Component)的 aboutToAppear 中注册监听,并在 aboutToDisappear 中注销监听。同时需要处理应用退到后台的情况,确保后台时不会误触发或保持无效监听。

// Entry Component 代码片段
onPageHide(): void {
  let uiContext: UIContext = this.getUIContext();
  let context: Context = uiContext.getHostContext() as Context;
  context.eventHub.emit('onBackGround');
}

aboutToAppear(): void {
  this.immersiveListening();
  let uiContext: UIContext = this.getUIContext();
  let context: Context = uiContext.getHostContext() as Context;
  context.eventHub.on('onBackGround', this.onBackGround);
}

aboutToDisappear(): void {
  this.immersiveDisablingListening();
  let uiContext: UIContext = this.getUIContext();
  let context: Context = uiContext.getHostContext() as Context;
  context.eventHub.off('onBackGround', this.onBackGround);
}

private onBackGround = () => {
  this.immersiveDisablingListening();
}

代码逐行解析

  1. onPageHide(): void { ... }

    • 页面隐藏生命周期回调,当页面被覆盖或应用退到后台时触发。
    • 内部通过 context.eventHub.emit('onBackGround') 发送一个自定义事件 'onBackGround',通知当前组件执行清理操作。
    • 这里使用了宿主上下文的 eventHub 来传递事件,因为页面隐藏时组件可能尚未销毁,直接调用方法可能不可靠,通过事件总线可以确保组件内部方法被调用。
  2. aboutToAppear(): void { ... }

    • 页面即将出现时触发,适合进行初始化操作。
    • 首先调用 this.immersiveListening() 注册隔空传送监听。
    • 然后通过 context.eventHub.on('onBackGround', this.onBackGround) 注册自定义事件监听,以便在页面隐藏(如退后台)时收到通知。
  3. aboutToDisappear(): void { ... }

    • 页面即将销毁时触发,适合进行清理操作。
    • 首先调用 this.immersiveDisablingListening() 注销隔空传送监听。
    • 然后通过 context.eventHub.off('onBackGround', this.onBackGround) 注销自定义事件监听,避免内存泄漏。
  4. private onBackGround = () => { this.immersiveDisablingListening(); }

    • 自定义事件回调,当收到 'onBackGround' 事件(即页面隐藏/退后台)时,调用 immersiveDisablingListening() 注销隔空传送监听。
    • 这样即使页面未销毁,也能及时停止响应隔空手势,符合“离开可分享页面(包括应用退至后台等场景)时取消监听”的要求。

生命周期时序总结

  • 页面进入前台:aboutToAppear → 注册监听。
  • 页面退到后台(被覆盖或 Home 键):onPageHide → 发出 'onBackGround' 事件 → onBackGround 回调 → 注销监听。
  • 页面重新回到前台:aboutToAppear 再次触发 → 重新注册监听。
  • 页面销毁:aboutToDisappear → 注销监听,同时注销事件总线监听。

完整适配流程总结

  1. 前置条件:设备已开启隔空传送开关;应用已接入 App Linking 并配置好链接。
  2. 注册监听:在可分享页面 aboutToAppear 中注册 harmonyShare.on('gesturesShare', callback)
  3. 构建分享数据:在回调中创建 systemShare.SharedData,包含 UTD、App Linking 链接、缩略图、标题和描述。
  4. 发起分享:在回调中调用 sharableTarget.share(shareData),必须在 3 秒内完成。
  5. 注销监听:在页面 aboutToDisappear 中调用 harmonyShare.off('gesturesShare', callback);同时监听 onPageHide 或自定义后台事件,在退后台时也执行注销。
  6. 信任处理:无需应用处理,系统自动完成信任设备确认。

常见问题与注意事项

超时问题

  • 回调触发后,若超过 3 秒未调用 share(),系统可能取消本次分享,开发时需保证分享数据构建高效。
  • 建议在回调中直接使用预先准备好的数据,避免耗时操作(如网络请求、大量 IO)。

文件路径与缩略图

  • 缩略图必须使用有效文件 URI,否则卡片可能无法显示缩略图。
  • 确保文件存在于应用沙箱内,且权限允许读取。
  • 建议使用应用内资源或临时缓存文件。

App Linking 配置

  • content 中的链接必须是已配置且可正常跳转的 App Linking 链接,否则接收端无法直达应用。
  • App Linking 的配置包括在 AppGallery Connect 中关联域名、在应用中处理链接等,需参考官方文档。

多页面管理

  • 如果应用有多个页面需要支持隔空传送,每个页面都应独立注册/注销,避免相互干扰。
  • 可以使用一个全局管理器统一处理,但需注意页面切换时的注册状态。

联动截屏行为

  • 如果应用希望用户抓取时自动保存截屏,无需额外开发,系统会根据开关状态自动处理,但开发者应了解该行为对用户的影响。
  • 例如,在非图库场景下,如果隔空截屏开启且已注册事件,用户抓取后会传送截屏并提示是否保存,开发者无法控制该提示,但可通过分享内容(如 App Linking)引导用户后续操作。

设备信任

  • 信任确认由系统完成,开发者无需干涉。
  • 如果接收端未安装应用,系统可能无法打开 App Linking,此时需要应用提供备选方案(如 Web 页面)。

总结

隔空传送为鸿蒙生态提供了新颖的跨端交互方式,通过简单的隔空手势即可完成内容分享。开发者只需按照文档要求,在页面生命周期中正确注册监听,并构建包含 App Linking 的分享数据,即可让自己的应用支持这一功能。同时,理解与隔空截屏的联动规则和信任机制,有助于优化用户体验,避免不必要的困扰。

通过本文的详细解析,相信开发者能够顺利完成隔空传送的适配工作,为用户带来“一抓一放”的便捷体验。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐