如果你也对鸿蒙开发感兴趣,加入“Harmony自习室”吧!扫描下方名片,关注公众号,公众号更新更快,同时也有更多学习资料和技术讨论群。

1、前言

HarmonyOS的一个非常大的特点就是跨设备协同。针对开发者,HarmonyOS提供了一套协同服务套件(Service Collaboration Kit)提供了同账号下多端设备的协同能力。

用户通过此能力实现跨设备交互,使用其他设备的相机、扫描和图库功能。

需要注意的是,使用跨设备协同能力,设备需要具备以下基本条件:

  • 双端设备需要登录同一华为账号;双端设备需要打开WLAN和蓝牙开关。

  • 本端设备为HarmonyOS版本为HarmonyOS NEXT 4.0及以上的平板或2in1设备, 远端设备:HarmonyOS版本为HarmonyOS NEXT 4.0及以上、具有相机能力的手机或平板设备。

2、特性介绍

跨设备互通提供跨设备的相机、扫描、图库访问能力,平板或2in1设备可以调用手机的相机、扫描、图库等功能。

用户在平板、手机或电脑等设备上使用富文本类编辑应用(如:备忘录、邮件、笔记等)时,想要拍摄一些照片作为素材,但是当前设备拍摄不太方便。

通过跨设备互通-拍照,用户可以在当前设备的应用中指定平板或手机设备,并打开平板或手机的相机来拍摄所需的素材。通过手机或者平板设备拍摄,移动更便利、取景更灵巧、相机能力也更强大。拍摄的照片将实现快速回传到平板、手机或电脑设备的应用中,帮助用户高效完成图文并茂的文档设计。整个过程大致的演示效果如下:

图片

为了实现:协同拍摄设备的选取、拍摄结果的获取,这个两个能力,HarmonyOS提供了两个关键的API,分别是:

  • createCollaborationServiceMenuItems

这个API可以实现自动扫描附近可用的设备,当附近有一个或两个设备时,菜单将会直接平铺显示,显示效果示例如下:

图片

当附近有两个以上的设备时,将会折叠到一个菜单中去,示例效果如下:

图片

关键示例代码如下:

import { createCollaborationServiceMenuItems, CollaborationServiceFilter } from '@kit.ServiceCollaborationKit';@BuilderMyTestMenu() {  Menu() {  // 第一个参数是过滤类型,第二个参数是可以获取的张数    createCollaborationServiceMenuItems([CollaborationServiceFilter.ALL], 30)   }}

其中CollaborationServiceFilter 是枚举类型,可以选择的值可以是:​​​​​​​

enum CllaborationServiceFilter {  ALL = 0 // 匹配所有业务。  TAKE_PHOTO = 1 // 匹配跨端拍照。  SCAN_DOCUMENT = 2 // 匹配文档扫描。  IMAGE_PICKER = 3 //匹配图库选择器。}

  • CollaborationServiceStateDialog

这个API用于在调用远端拍照过程中,在本端给用户显示远端状态的提示对话框。同时,如果拍摄完毕后,将会由此组件将拍摄或者获取的数据回调。

关键的示例代码如下:​​​​​​​

import { CollaborationServiceStateDialog } from '@kit.ServiceCollaborationKit';CollaborationServiceStateDialog({  onState: (stateCode: number, bufferType: string, buffer: ArrayBuffer):void => this.doInsertPicture(stateCode, bufferType, buffer)})

拍摄状态可能为:对端设备拍摄中、图片导入中、协同失败、本端WLAN未开启、对端WLAN未开启。

【远端拍摄中】示例如下:

图片

【图片导入中】示例如下:

图片

【协同失败】示例如下:

图片

【本端WLAN未开启】示例如下:

图片

【对端WLAN未开启】示例如下:

图片

3、开发

一般情况下,我们的开发分为3步。

👉🏻 step 1:导入模块

import { createCollaborationServiceMenuItems, CollaborationServiceStateDialog, CollaborationServiceFilter } from '@kit.ServiceCollaborationKit';

👉🏻 step 2:调用设备选择器组件,显示可用列表。

使用createCollaborationServiceMenuItems 用于显示可用组件,其中支持两个参数

      第一个参数传入Array类型的CollaborationServiceFilter枚举值即可使用对应能力,目前支持ALL、TAKE_PHOTO、SCAN_DOCUMENT和IMAGE_PICKER。【ALL为预留值,匹配所有业务,功能将在后续拓展,TAKE_PHOTO匹配跨设备拍照能力,SCAN_DOCUMENT匹配跨设备扫描能力,IMAGE_PICKER匹配跨设备图库能力】

    第二个参数可以传入一个数字,表示接收的张数的上限,目前范围是1 ~ 50. ​​​​​​​

@BuilderMyTestMenu() {  Menu() {    createCollaborationServiceMenuItems([CollaborationServiceFilter.ALL], 30)   }}

👉🏻 step 3:显示等待弹窗并监听回调数据。

在build方法中添加弹窗组件CollaborationServiceStateDialog,用于提示远端相机拍摄状态和回传数据。需要实现其中的onState方法。

【CollaborationServiceStateDialog是全局的提示框,不会对原有布局产生影响】​​​​​​​

CollaborationServiceStateDialog({  onState: (stateCode: number, bufferType: string, buffer: ArrayBuffer):void => this.doInsertPicture(stateCode, bufferType, buffer)})

一个完整的Demo如下:​​​​​​​

import {  createCollaborationServiceMenuItems,  CollaborationServiceStateDialog,  CollaborationServiceFilter} from '@kit.ServiceCollaborationKit';import { image } from '@kit.ImageKit';import { hilog } from '@kit.PerformanceAnalysisKit';@Entry@Componentstruct Index {  @State picture: PixelMap | undefined = undefined;  @Builder  MyTestMenu() {    Menu() {      createCollaborationServiceMenuItems([CollaborationServiceFilter.ALL], 30)    }  }  build() {    Column({ space: 20 }) {      CollaborationServiceStateDialog({        onState: (stateCode: number, bufferType: string, buffer: ArrayBuffer): void => this.doInsertPicture(stateCode, bufferType, buffer)      })      Button('使用远端设备进行拍照')        .type(ButtonType.Normal)        .borderRadius(10)        .bindMenu(this.MyTestMenu)      if (this.picture) {        Image(this.picture)          .borderStyle(BorderStyle.Dotted)          .borderWidth(1)          .objectFit(ImageFit.Contain)          .height('80%')          .onComplete((event) => {            if (event != undefined) {              hilog.info(0, "MEMOMOCK", "onComplete " + event.loadingStatus)            }          })      }    }    .padding(20)    .width('100%')    .alignItems(HorizontalAlign.Center)  }  doInsertPicture(stateCode: number, bufferType: string, buffer: ArrayBuffer): void {    if (stateCode != 0) {      return    }    if (bufferType == "general.image") {      let imageSource = image.createImageSource(buffer)      imageSource.createPixelMap().then((pixelMap) => {        this.picture = pixelMap;      })    }  }}

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐