鸿蒙跨设备协同开发07——动态控制应用接续

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

1、前 言

本文的内容是基于鸿蒙跨设备协同开发06——应用接续的进一步讨论。

从API version 10起,提供了支持动态配置迁移能力的功能。即应用可以根据实际使用场景,在需要迁移功能时,设置开启应用迁移能力;在业务不需要迁移时,则可以关闭迁移能力(例如:编辑类应用在编辑文本的页面下才需要迁移,其他页面不需要迁移)。

我们可以通过调用setMissionContinueState接口对迁移能力进行设置。setMissionContinueState接口定义如下:

// callback版本setMissionContinueState(state: AbilityConstant.ContinueState, callback: AsyncCallback<void>): void// Promiseb版本setMissionContinueState(state: AbilityConstant.ContinueState): Promise<void>

其中AbilityConstant.ContinueState是枚举,定义如下:​​​​​​​

enum ContinueState {  CONTINUATION = 0, // 迁移保存状态。  APP_RECOVERY = 1 // 应用恢复保存状态。}

以Promise版本为例,设置示例代码如下:​​​​​​​

import { UIAbility, AbilityConstant } from '@kit.AbilityKit';import { BusinessError } from '@kit.BasicServicesKit';export default class EntryAbility extends UIAbility {  onForeground() {    this.context.setMissionContinueState(AbilityConstant.ContinueState.INACTIVE).then(() => {      console.info('success');    }).catch((err: BusinessError) => {      console.error(`setMissionContinueState failed, code is ${err.code}, message is ${err.message}`);    });  }}

2、动态迁移实现

默认状态下,应用的迁移能力为ACTIVE状态(可以迁移)。

如果需要实现某些特殊场景(比如只在具体某个页面下支持迁移,或者只在某个事件发生时才支持迁移)可以按照如下步骤进行配置。

👉🏻 step 1:先默认关闭迁移能力

由于默认情况下,迁移能力是ACTIVE的,因此我们需要如果想默认先关闭迁移能力,就需要在Ability的onCreate生命周期回调中关闭(发生的时机靠前),示例代码如下:​​​​​​​

// EntryAbility.etsimport UIAbility from '@ohos.app.ability.UIAbility';import AbilityConstant from '@ohos.app.ability.AbilityConstant';import Want from '@ohos.app.ability.Want';export default class EntryAbility extends UIAbility {  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {    // ...    this.context.setMissionContinueState(AbilityConstant.ContinueState.INACTIVE, (result) => {      console.info(`setMissionContinueState: ${JSON.stringify(result)}`);    });    // ...  }}

👉🏻 step 2:在需要开启的场景动态打开

如果需要在具体某个页面中打开迁移能力,可以在该页面的onPageShow()函数中设置。代码如下:​​​​​​​

// PageName.etsimport AbilityConstant from '@ohos.app.ability.AbilityConstant';import common from '@ohos.app.ability.common'@Entry@Componentstruct PageName {  private context = getContext(this) as common.UIAbilityContext;  build() {    // ...  }  // ...  onPageShow(){  // 进入该页面时,将应用设置为可迁移状态    this.context.setMissionContinueState(AbilityConstant.ContinueState.ACTIVE, (result) => {      console.info('setMissionContinueState ACTIVE result: ', JSON.stringify(result));    });  }}

如果在某个组件的触发事件中打开迁移能力,可以在该事件中设置。代码如下:​​​​​​​

// PageName.etsimport AbilityConstant from '@ohos.app.ability.AbilityConstant';import common from '@ohos.app.ability.common'@Entry@Componentstruct PageName {  private context = getContext(this) as common.UIAbilityContext;  build() {    // ...    Button() {      //...    }.onClick(()=>{    //点击该按钮时,将应用设置为可迁移状态      this.context.setMissionContinueState(AbilityConstant.ContinueState.ACTIVE, (result) => {        console.info('setMissionContinueState ACTIVE result: ', JSON.stringify(result));      });    })  }}

❓ 迁移后的回迁问题

我们现在分析一个场景:

迁移加载时,目标端拉起的应用可能执行过自己的迁移状态设置命令(如:冷启动时目标端在onCreate中设置了INACTIVE;热启动时对端已打开了不可迁移的页面,迁移状态为INACTIVE等情况)

为了保证迁移过后的应用依然具有可以迁移回源端的能力,我们应在onCreate和onNewWant的迁移调用判断中,如果是从迁移状态启动的,则将迁移状态设置为ACTIVE。

【我们在鸿蒙跨设备协同开发06——应用接续已经知道,在迁移状态启动后,我们通过onCreate方法和onNewWant方法中的launchParam中的launchReason参数知道当前应用的启动方式】

因此,我们如果是从源端迁移过来启动的,同时,我们又想要保留迁移回源端的能力。那我们需要在onCreate和onNewWant中针对迁移场景做Active激活操作。示例代码如下:​​​​​​​

// EntryAbility.etsimport UIAbility from '@ohos.app.ability.UIAbility';import AbilityConstant from '@ohos.app.ability.AbilityConstant';import Want from '@ohos.app.ability.Want';export default class EntryAbility extends UIAbility {  // ...  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {    // ...    // 迁移冷启动时,设置状态为可迁移    if (launchParam.launchReason == AbilityConstant.LaunchReason.CONTINUATION) {      this.context.setMissionContinueState(AbilityConstant.ContinueState.ACTIVE, (result) => {        console.info(`setMissionContinueState: ${JSON.stringify(result)}`);      });    }  }  onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {    // ...    // 迁移热启动时,设置状态为可迁移    if (launchParam.launchReason == AbilityConstant.LaunchReason.CONTINUATION) {      this.context.setMissionContinueState(AbilityConstant.ContinueState.ACTIVE, (result) => {        console.info('setMissionContinueState ACTIVE result: ', JSON.stringify(result));      });    }  }  // ...}

3、页面栈迁移问题

应用接续还支持应用动态选择是否进行页面栈恢复(默认进行页面栈信息恢复)。如果应用不想使用系统默认恢复的页面栈,则可以设置不进行页面栈迁移,而需要在onWindowStageRestore设置迁移后进入的页面。

  • 当前仅支持router路由的页面栈信息自动恢复,暂不支持navigation路由的页面栈自动恢复。

  • 如果应用使用navigation路由,可以设置不进行页面栈迁移,并将需要接续的页面(或页面栈)信息保存在want中传递,然后在目标端手动加载指定页面。

举例:假设应用在源端的页面栈中存在Index和Second路由,而在目标端恢复时不需要按照源端页面栈进行恢复,需要恢复到指定页面。代码如下:​​​​​​​

// EntryAbility.etsimport UIAbility from '@ohos.app.ability.UIAbility';import AbilityConstant from '@ohos.app.ability.AbilityConstant';import wantConstant from '@ohos.app.ability.wantConstant';import window from '@ohos.window';export default class EntryAbility extends UIAbility {  // ...  onContinue(wantParam: Record<string, Object>) {    console.info(`onContinue version = ${wantParam.version}, targetDevice: ${wantParam.targetDevice}`);    wantParam[wantConstant.Params.SUPPORT_CONTINUE_PAGE_STACK_KEY] = false;    return AbilityConstant.OnContinueResult.AGREE;  }  // ...  onWindowStageRestore(windowStage: window.WindowStage) {      // 若不需要自动迁移页面栈信息,则需要在此处设置应用迁移后进入的页面    windowStage.loadContent('pages/Index', (err, data) => {      if (err.code) {        console.info('Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');        return;      }      console.info('Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');    });  }}

4、接续后,源端退出控制

支持应用动态选择迁移成功后是否退出迁移源端应用(默认迁移成功后退出迁移源端应用)。

如果应用不想让系统自动退出迁移源端应用,则可以设置不退出。设置方法示例如下:​​​​​​​

import UIAbility from '@ohos.app.ability.UIAbility';import AbilityConstant from '@ohos.app.ability.AbilityConstant';import wantConstant from '@ohos.app.ability.wantConstant';export default class EntryAbility extends UIAbility {  // ...  onContinue(wantParam: Record<string, Object>) {    console.info(`onContinue version = ${wantParam.version}, targetDevice: ${wantParam.targetDevice}`);    // 设置接续后,源端不退出应用    wantParam[wantConstant.Params.SUPPORT_CONTINUE_SOURCE_EXIT_KEY] = false;    return AbilityConstant.OnContinueResult.AGREE;  }  // ...}

5、接续不同的Ability

一般情况下,跨端迁移的双端是同Ability之间,但有些应用在不同设备类型下的同一个业务Ability名称不同(即异Ability)。

为了支持该场景下的两个Ability之间能够完成迁移,可以通过在module.json5文件的abilities标签中配置迁移类型continueType进行关联。需要迁移的两个Ability的continueType字段取值必须保持一致,示例如下:​​​​​​​

 // 设备A   {     "module": {       // ...       "abilities": [         {           // ...           "name": "Ability-deviceA",           "continueType": ['continueType1'], // continueType标签配置         }       ]     }   }   // 设备B   {     "module": {       // ...       "abilities": [         {           // ...           "name": "Ability-deviceB",           "continueType": ['continueType1'], // 与设备A相同的continueType标签         }       ]     }   }

注意:

  • continueType在本应用中要保证唯一,字符串以字母、数字和下划线组成,最大长度127个字节,不支持中文。

  • continueType标签类型为字符串数组,如果配置了多个字段,当前仅第一个字段会生效。

6、快速启动目标应用

默认情况下,发起迁移后不会立即拉起对端的目标应用,而是等待迁移数据从源端同步到对端后,才会拉起。

为了发起迁移后能够立即拉起目标应用,做到及时响应,我们可以选择在数据完全同步到对端后,先启动应用。

实现方式是通过在continueType标签中添加“_ContinueQuickStart”后缀进行生效,这样待迁移数据从源端同步到对端后只恢复迁移数据即可(页面提前响应,做好初始化),提升应用迁移体验。示例如下:​​​​​​​

{  "module": {    // ...    "abilities": [      {        // ...        "name": "EntryAbility"        // 如果已经配置了continueType标签,可以在该标签值后添加'_ContinueQuickStart'后缀;        // 如果没有配置continueType标签,可以使用AbilityName + '_ContinueQuickStart'作为continueType标签实现快速拉起目标应用        "continueType": ['EntryAbility_ContinueQuickStart'],       }    ]  }}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值