[文章]HarmonyOS Next 应用元服务开发-分布式数据对象迁移数据权限与基础数据

阅读量0
0
0

使用分布式数据对象迁移数据,当需要迁移的数据较大(100KB以上)或需要迁移文件时,可以使用分布式数据对象。原理与接口说明详见分布式数据对象跨设备数据同步。

说明:自API 12起,由于直接使用跨设备文件访问实现文件的迁移,难以获取文件同步完成的时间。为了保证更高的成功率,文件的迁移不建议继续通过该方式实现,推荐使用分布式数据对象携带资产的方式。开发者此前通过跨设备文件访问实现的文件迁移依然生效。

一、申请权限

说明,自API 12起,无需申请ohos.permission.DISTRIBUTED_DATASYNC权限。

API 11及以前版本,需要执行如下操作。

1.声明ohos.permission.DISTRIBUTED_DATASYNC权限。

2.由于ohos.permission.DISTRIBUTED_DATASYNC权限需要用户授权,应用需在首次启动、或进入接续页面时弹窗向用户申请授权。

二、基础数据迁移

使用分布式数据对象,与上述开发步骤类似,需要在源端onContinue()接口中进行数据保存,并在对端的onCreate()/onNewWant()接口中进行数据恢复。

在源端UIAbility的onContinue()接口中创建分布式数据对象并保存数据,执行流程如下:

在onContinue()接口中使用create()接口创建分布式数据对象,将所要迁移的数据填充到分布式数据对象数据中。

调用genSessionId()接口生成数据对象组网id,并使用该id调用setSessionId()加入组网,激活分布式数据对象。

使用save()接口将已激活的分布式数据对象持久化,确保源端退出后对端依然可以获取到数据。

将生成的sessionId通过want传递到对端,供对端激活同步使用。

说明,分布式数据对象需要先激活,再持久化,因此必须在调用setSessionId()后再调用save()接口。对于源端迁移后需要退出的应用,为了防止数据未保存完成应用就退出,应采用await的方式等待save()接口执行完毕。从API 12 起,onContinue()接口提供了async版本供该场景使用。

当前,wantParams中“sessionId”字段在迁移流程中被系统占用,建议开发者在wantParams中定义其他key值存储该分布式数据对象生成的id,避免数据异常。

示例代码如下:

import { distributedDataObject } from '@kit.ArkData';

import { UIAbility, AbilityConstant } from '@kit.AbilityKit';

import { BusinessError } from '@kit.BasicServicesKit';

import { hilog } from '@kit.PerformanceAnalysisKit';

const TAG: string = '[MigrationAbility]';

const DOMAIN_NUMBER: number = 0xFF00;

 

// 业务数据定义

class ParentObject {

  mother: string

  father: string

 

  constructor(mother: string, father: string) {

    this.mother = mother

    this.father = father

  }

}

 

// 支持字符、数字、布尔值、对象的传递

class SourceObject {

  name: string | undefined

  age: number | undefined

  isVis: boolean | undefined

  parent: ParentObject | undefined

 

  constructor(name: string | undefined, age: number | undefined, isVis: boolean | undefined, parent: ParentObject | undefined) {

    this.name = name

    this.age = age

    this.isVis = isVis

    this.parent = parent

  }

}

 

export default class MigrationAbility extends UIAbility {

  d_object?: distributedDataObject.DataObject;

 

  async onContinue(wantParam: Record<string, Object>): Promise<AbilityConstant.OnContinueResult> {

    // ...

    let parentSource: ParentObject = new ParentObject('jack mom', 'jack Dad');

    let source: SourceObject = new SourceObject("jack", 18, false, parentSource);

 

    // 创建分布式数据对象

    this.d_object = distributedDataObject.create(this.context, source);

 

    // 生成数据对象组网id,激活分布式数据对象

    let dataSessionId: string = distributedDataObject.genSessionId();

    this.d_object.setSessionId(dataSessionId);

 

    // 将组网id存在want中传递到对端

    wantParam['dataSessionId'] = dataSessionId;

 

    // 数据对象持久化,确保迁移后即使应用退出,对端依然能够恢复数据对象

    // 从wantParam.targetDevice中获取到对端设备的networkId作为入参

    await this.d_object.save(wantParam.targetDevice as string).then((result:

      distributedDataObject.SaveSuccessResponse) => {

      hilog.info(DOMAIN_NUMBER, TAG, `Succeeded in saving. SessionId: ${result.sessionId},

        version:${result.version}, deviceId:${result.deviceId}`);

    }).catch((err: BusinessError) => {

      hilog.error(DOMAIN_NUMBER, TAG, 'Failed to save. Error: ', JSON.stringify(err) ?? '');

    });

  }

}

在对端UIAbility的onCreate()/onNewWant()中,通过加入与源端一致的分布式数据对象组网进行数据恢复。

创建空的分布式数据对象,用于接收恢复的数据;

从want中读取分布式数据对象组网id;

注册on()接口监听数据变更。在收到status为restore的事件的回调中,实现数据恢复完毕时需要进行的业务操作。

调用setSessionId()加入组网,激活分布式数据对象。

说明,对端加入组网的分布式数据对象不能为临时变量,因为在分布式数据对象on()接口为异步回调,可能在onCreate()/onNewWant()执行结束后才执行,临时变量被释放可能导致空指针异常。可以使用类成员变量避免该问题。对端用于创建分布式数据对象的Object,其属性应在激活分布式数据对象前置为undefined,否则会导致新数据加入组网后覆盖源端数据,数据恢复失败。应当在激活分布式数据对象之前,调用分布式数据对象的on()接口进行注册监听,防止错过restore事件导致数据恢复失败。

示例代码如下:

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';

import { distributedDataObject } from '@kit.ArkData';

import { hilog } from '@kit.PerformanceAnalysisKit';

const TAG: string = '[MigrationAbility]';

const DOMAIN_NUMBER: number = 0xFF00;

 

// 示例数据对象定义与上同

 

export default class MigrationAbility extends UIAbility {

  d_object?: distributedDataObject.DataObject;

 

  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {

    if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) {

      // ...

      // 调用封装好的分布式数据对象处理函数

      this.handleDistributedData(want);

    }

  }

 

  onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {

    if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) {

      if (want.parameters !== undefined) {

        // ...

        // 调用封装好的分布式数据对象处理函数

        this.handleDistributedData(want);

      }

    }

  }

 

  handleDistributedData(want: Want) {

    // 创建空的分布式数据对象

    let remoteSource: SourceObject = new SourceObject(undefined, undefined, undefined, undefined);

    this.d_object = distributedDataObject.create(this.context, remoteSource);

 

    // 读取分布式数据对象组网id

    let dataSessionId = '';

    if (want.parameters !== undefined) {

      dataSessionId = want.parameters.dataSessionId as string;

    }

    // 添加数据变更监听

    this.d_object.on("status", (sessionId: string, networkId: string, status: 'online' | 'offline' | 'restored') => {

      hilog.info(DOMAIN_NUMBER, TAG, "status changed " + sessionId + " " + status + " " + networkId);

      if (status == 'restored') {

        if (this.d_object) {

          // 收到迁移恢复的状态时,可以从分布式数据对象中读取数据

          hilog.info(DOMAIN_NUMBER, TAG, "restored name:" + this.d_object['name']);

          hilog.info(DOMAIN_NUMBER, TAG, "restored parents:" + JSON.stringify(this.d_object['parent']));

        }

      }

 

    // 激活分布式数据对象

    this.d_object.setSessionId(dataSessionId);

  }

}

本文主要引用HarmonyOS官方文档

回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友