一、环境配置

  • 平台硬件: RK3568
  • OS版本:OpenHarmony 4.1 Release 32bit(4.1.7.8)
  • sdk:API11(full sdk)
  • DevEco:4.1.0.400

 

二、项目介绍

本项目实现了分布式认证,分布式相机预览拍照,分布式图库同步显示删除

 

三、项目实现注意事项

3.1分布式图库需要基于分布式文件系统实现,分布式文件系统需要预先登录分布式账号

参考 @ohos.account.distributedAccount (分布式帐号管理) (openharmony.cn)

/**
 * 分布式账号类
 * 功能:
 * 1.判断是否登录
 * 2.登录默认账号
 */
export class DistributedAccountHelper {
  private distributedAccountAbility: account_distributedAccount.DistributedAccountAbility;

  constructor() {
    this.distributedAccountAbility = account_distributedAccount.getDistributedAccountAbility();
  }

  /**
   * 检查当前登录分布式账号信息
   * @returns Promise<boolean>
   */
  checkLogin(): Promise<void> {
    return new Promise((resolve, reject) => {
      this.distributedAccountAbility.getOsAccountDistributedInfo().then((data: account_distributedAccount.DistributedInfo) => {
        Logger.info(TAG, 'distributed information: ' + JSON.stringify(data));
        resolve();
      }).catch((err: BusinessError) => {
        Logger.info(TAG, 'getOsAccountDistributedInfo exception: ' + JSON.stringify(err));
        resolve();
      });
    });
  }

  /**
   * 登录分布式账号
   * @returns Promise<void>
   */
  login(): Promise<void> {
    let distributedInfo: account_distributedAccount.DistributedInfo = {
      name: 'ZhangSan',
      id: '12345',
      event: 'Ohos.account.event.LOGIN',
    };
    return new Promise((resolve, reject) => {
      this.distributedAccountAbility.setOsAccountDistributedInfo(distributedInfo).then(() => {
        Logger.info(TAG, 'setOsAccountDistributedInfo LOGIN successfully');
        resolve();
      }).catch((err: BusinessError) => {
        Logger.info(TAG, 'setOsAccountDistributedInfo exception: ' + JSON.stringify(err));
        reject(err);
      });
    });
  }
}

 页面出现前进行账号登录。

  async aboutToAppear() {
    // 登陆分布式账号
    await this.dealDistributedAccount();
    // 初始化分布式model
    RemoteDeviceModel.createRemoteDeviceModel();

    Logger.info(TAG, 'DeviceMangerPage init success!');
  }

  async dealDistributedAccount() {
    const helper = new DistributedAccountHelper();
    // 登陆自己的分布式账号
    await helper.login();
    // 检查结果
    await helper.checkLogin();
  }

3.2分布式文件系统不同设备间同步涉及数据安全,如果本设备安全等级低于文件安全等级,则不能同步。

参考@ohos.file.securityLabel (数据标签) (openharmony.cn)

对于rk3568,本身没有安全芯片,安全等级最低,为S1,而分布式文件夹中的文件默认安全等级为S3,所以普通情况下已经登录同一分布式账号的应用,只能看到分布式文件夹有文件,有文件名,但是访问会出现Permission denied,参数错误等。

解决办法:手动降低文件数据安全等级,以下为适用于rk3568的代码示例。

注意,代码实现中的s0-s4对应实际安全等级S1-S5

      //设置文件的数据等级为s0
      securityLabel.setSecurityLabel(localPhotoUri, 's0').then(() => {
        Logger.info(TAG, `Succeeded in setSecurityLabeling. ${localPhotoUri}`);
      }).catch((err: BusinessError) => {
        Logger.error(TAG, `Failed to setSecurityLabel. Code: ${err.code}, message: ${err.message}`);
      });

3.3 分布式相机使用远端设备进行拍照时(参考最佳实践进行实现),无法进入'photoAvailable'回调,无法获取原始camera.Photo。(不清楚是否为个例,欢迎讨论)

参考@ohos.multimedia.image (图片处理) (openharmony.cn)

解决办法:分布式相机只能预览,不能拍照,那就从预览流取出数据,保存为图片(其实这中方法也适用于本地设备拍照,但是最佳实践是一个输出流一个预览流)。

普通拍照方法:

  /**
   * 拍照回调注册类
   * @param photoOutput
   */
  async setPhotoOutputCb(photoOutput: camera.PhotoOutput) {
    //设置回调之后,调用photoOutput的capture方法,就会将拍照的buffer回传到回调中
    //分布式拍照无法进入该回调,新增distributedTakePicture
    photoOutput.on('photoAvailable', (errCode: BusinessError, photo: camera.Photo): void => {
      Logger.info(TAG, 'getPhoto start');
      Logger.info(TAG, `err: ${JSON.stringify(errCode)}`);
      if (errCode || photo === undefined) {
        Logger.error(TAG, 'getPhoto failed');
        return;
      }
      let imageObj: image.Image = photo.main;
      imageObj.getComponent(image.ComponentType.JPEG, (errCode: BusinessError, component: image.Component): Promise<void> => {
        Logger.info(TAG, 'getComponent start');
        if (errCode || component === undefined) {
          Logger.error(TAG, 'getComponent failed');
          return;
        }
        let buffer: ArrayBuffer;
        if (component.byteBuffer) {
          buffer = component.byteBuffer;
        } else {
          Logger.error(TAG, 'byteBuffer is null');
          return;
        }
        this.saveImage(buffer, imageObj);
      });
    });
    photoOutput.on('error', (err: BusinessError): void => {
      Logger.error(TAG, `${JSON.stringify(err)}`);
    });
  }

分布式设备拍照方法:

  distributedTakePicture(surfaceId: string) {
    //rk createPreviewOutput 只支持{"format":3,"size":{"width":640,"height":480}}
    let region: image.Region = { x: 0, y: 0, size: { width: 640, height: 480 } };
    image.createPixelMapFromSurface(surfaceId, region).then(async (pixelMap: image.PixelMap) => {
      Logger.info(TAG, 'Succeeded in creating pixelMap from Surface');

      let packOpts: image.PackingOption = { format: "image/jpeg", quality: 100 }
      const imagePackerApi: image.ImagePacker = image.createImagePacker();
      await pixelMap.rotate(-90.0);
      imagePackerApi.packing(pixelMap, packOpts, (err: BusinessError, data: ArrayBuffer) => {
        if (err) {
          Logger.error('Failed in packing the image.' + JSON.stringify(err))
        } else {
          this.saveImage(data);
          Logger.info(TAG, 'Succeeded in packing the image.');
          pixelMap.release();
        }
      })
    }).catch((error: BusinessError) => {
      Logger.error(TAG, 'Failed to create pixelMap ' + JSON.stringify(error));
    });
  }

 四、项目源码

// 项目源码还在优化,关键问题上面已经解决,后续考虑捐献到社区,欢迎持续关注。

更新:项目源码:distributeddemo: 分布式相机git (gitee.com)

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐