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.ets
import 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.ets
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import common from '@ohos.app.ability.common'
@Entry
@Component
struct 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.ets
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import common from '@ohos.app.ability.common'
@Entry
@Component
struct 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.ets
import 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设置迁移后进入的页面。
|
举例:假设应用在源端的页面栈中存在Index和Second路由,而在目标端恢复时不需要按照源端页面栈进行恢复,需要恢复到指定页面。代码如下:
// EntryAbility.ets
import 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'],
}
]
}
}