// Page_MigrationAbilityFirst.ets
import AbilityConstant from ‘@ohos.app.ability.AbilityConstant’;
import common from ‘@ohos.app.ability.common’;
import hilog from ‘@ohos.hilog’;
const TAG: string = ‘[MigrationAbility]’;
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_MigrationAbilityFirst {
private context = getContext(this) as common.UIAbilityContext;
build() {
// …
}
// …
onPageShow(){
// 进入该页面时,将应用设置为可迁移状态
this.context.setMissionContinueState(AbilityConstant.ContinueState.ACTIVE, (result) => {
hilog.info(DOMAIN_NUMBER, TAG, ‘%{public}s’, setMissionContinueState ACTIVE result: ${JSON.stringify(result)}
);
});
}
}
在某个组件的触发事件中设置应用迁移能力。
// Page_MigrationAbilityFirst.ets
import AbilityConstant from ‘@ohos.app.ability.AbilityConstant’;
import common from ‘@ohos.app.ability.common’;
import hilog from ‘@ohos.hilog’;
import promptAction from ‘@ohos.promptAction’;
const TAG: string = ‘[MigrationAbility]’;
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_MigrationAbilityFirst {
private context = getContext(this) as common.UIAbilityContext;
build() {
// …
Button() {
// …
}
.onClick(()=>{
// 点击该按钮时,将应用设置为可迁移状态
this.context.setMissionContinueState(AbilityConstant.ContinueState.ACTIVE, (result) => {
hilog.info(DOMAIN_NUMBER, TAG, ‘%{public}s’, setMissionContinueState ACTIVE result: ${JSON.stringify(result)}
);
});
})
}
}
保证迁移连续性
由于迁移加载时,对端拉起的应用可能执行过自己的迁移状态设置命令(例如,冷启动时对端在 onCreate()
中设置了 INACTIVE ;热启动时对端已打开了不可迁移的页面,迁移状态为 INACTIVE 等情况)。为了保证迁移过后的应用依然具有可以迁移回源端的能力,应在 onCreate()
/ onNewWant()
的迁移调用判断中,将迁移状态设置为 ACTIVE 。
// MigrationAbility.ets
import AbilityConstant from ‘@ohos.app.ability.AbilityConstant’;
import hilog from ‘@ohos.hilog’;
import UIAbility from ‘@ohos.app.ability.UIAbility’;
import type Want from ‘@ohos.app.ability.Want’;
const TAG: string = ‘[MigrationAbility]’;
const DOMAIN_NUMBER: number = 0xFF00;
export default class MigrationAbility extends UIAbility {
// …
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// …
// 调用原因为迁移时,设置状态为可迁移,应对冷启动情况
if (launchParam.launchReason == AbilityConstant.LaunchReason.CONTINUATION) {
this.context.setMissionContinueState(AbilityConstant.ContinueState.ACTIVE, (result) => {
hilog.info(setMissionContinueState ACTIVE result: ${JSON.stringify(result)}
);
});
}
}
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// …
// 调用原因为迁移时,设置状态为可迁移,应对热启动情况
if (launchParam.launchReason == AbilityConstant.LaunchReason.CONTINUATION) {
this.context.setMissionContinueState(AbilityConstant.ContinueState.ACTIVE, (result) => {
hilog.info(DOMAIN_NUMBER, TAG, setMissionContinueState ACTIVE result: ${JSON.stringify(result)}
);
});
}
}
// …
}
按需迁移页面栈
支持应用动态选择是否进行页面栈恢复(默认进行页面栈信息恢复)。如果应用不想使用系统默认恢复的页面栈,则可以设置不进行页面栈迁移,而需要在onWindowStageRestore()
设置迁移后进入的页面,参数定义见 SUPPORT_CONTINUE_PAGE_STACK_KEY 。
应用在源端的页面栈中存在Index和Second路由,而在对端恢复时不需要按照源端页面栈进行恢复,需要恢复到指定页面。
例如,UIAbility
迁移不需要自动迁移页面栈信息。
// MigrationAbility.ets
import AbilityConstant from ‘@ohos.app.ability.AbilityConstant’;
import hilog from ‘@ohos.hilog’;
import UIAbility from ‘@ohos.app.ability.UIAbility’;
import wantConstant from ‘@ohos.app.ability.wantConstant’;
import type window from ‘@ohos.window’;
const TAG: string = ‘[MigrationAbility]’;
const DOMAIN_NUMBER: number = 0xFF00;
export default class MigrationAbility extends UIAbility {
// …
onContinue(wantParam: Record<string, Object>):AbilityConstant.OnContinueResult {
hilog.info(DOMAIN_NUMBER, TAG, onContinue version = ${wantParam.version}, targetDevice: ${wantParam.targetDevice}
);
wantParam[wantConstant.Params.SUPPORT_CONTINUE_PAGE_STACK_KEY] = false;
return AbilityConstant.OnContinueResult.AGREE;
}
onWindowStageRestore(windowStage: window.WindowStage) : void {
// 若不需要自动迁移页面栈信息,则需要在此处设置应用迁移后进入的页面
windowStage.loadContent(‘pages/page_migrationability/Page_MigrationAbilityThird’, (err, data) => {
if (err.code) {
hilog.error(DOMAIN_NUMBER, TAG, ‘Failed to load the content. Cause: %{public}s’, JSON.stringify(err) ?? ‘’);
return;
}
});
}
}
按需退出
支持应用动态选择迁移成功后是否退出迁移源端应用(默认迁移成功后退出迁移源端应用)。如果应用不想让系统自动退出迁移源端应用,则可以设置不退出,参数定义见 SUPPORT_CONTINUE_SOURCE_EXIT_KEY 。
示例:UIAbility
设置迁移成功后,源端不需要退出迁移应用。
import AbilityConstant from ‘@ohos.app.ability.AbilityConstant’;
import hilog from ‘@ohos.hilog’;
import UIAbility from ‘@ohos.app.ability.UIAbility’;
import wantConstant from ‘@ohos.app.ability.wantConstant’;
const TAG: string = ‘[MigrationAbility]’;
const DOMAIN_NUMBER: number = 0xFF00;
export default class MigrationAbility extends UIAbility {
// …
onContinue(wantParam: Record<string, Object>):AbilityConstant.OnContinueResult {
hilog.info(DOMAIN_NUMBER, TAG, onContinue version = ${wantParam.version}, targetDevice: ${wantParam.targetDevice}
);
wantParam[wantConstant.Params.SUPPORT_CONTINUE_SOURCE_EXIT_KEY] = false;
return AbilityConstant.OnContinueResult.AGREE;
}
}
跨端迁移中的数据迁移
当前支持三种不同的数据迁移方式,开发者可以根据实际使用需要进行选择。
说明:
部分ArkUI组件支持通过配置restoreId
的方式,在迁移后将特定状态恢复到对端设备。详情请见分布式迁移标识。
如果涉及分布式对象和分布式文件迁移时应注意:
- 需要申请
ohos.permission.DISTRIBUTED_DATASYNC
权限,配置方式请参见 声明权限 。 - 同时需要在应用首次启动时弹窗向用户申请授权,使用方式请参见 向用户申请授权 。
使用wantParam迁移数据
在需要迁移的数据较少(100KB以下)时,开发者可以选择在wantParam
中增加字段进行数据迁移。示例如下:
import UIAbility from ‘@ohos.app.ability.UIAbility’;
import AbilityConstant from ‘@ohos.app.ability.AbilityConstant’;
import Want from ‘@ohos.app.ability.Want’;
const TAG: string = ‘[MigrationAbility]’;
const DOMAIN_NUMBER: number = 0xFF00;
export default class MigrationAbility extends UIAbility {
// 源端保存
onContinue(wantParam: Record<string, Object>):AbilityConstant.OnContinueResult {
// 将要迁移的数据保存在wantParam的自定义字段(例如data)中
const continueInput = ‘迁移的数据’;
wantParam[‘data’] = continueInput;
return AbilityConstant.OnContinueResult.AGREE;
}
// 对端恢复
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) {
// 将上述保存的数据取出恢复
let continueInput = ‘’;
if (want.parameters !== undefined) {
continueInput = JSON.stringify(want.parameters.data);
hilog.info(DOMAIN_NUMBER, TAG, continue input ${continueInput}
);
}
// 触发页面恢复
this.context.restoreWindowStage(this.storage);
}
}
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
if (launchParam.launchReason == AbilityConstant.LaunchReason.CONTINUATION) {
let continueInput = ‘’;
if (want.parameters !== undefined) {
continueInput = JSON.stringify(want.parameters.data);
hilog.info(DOMAIN_NUMBER, TAG, continue input ${JSON.stringify(continueInput)}
);
}
// 触发页面恢复
this.context.restoreWindowStage(this.storage);
}
}
}
使用分布式对象迁移数据
当需要迁移的数据较大(100KB以上)时,可以选择 分布式对象 进行数据迁移。
- 在源端
onContinue()
接口中创建一个分布式数据对象DataObject
,将所要迁移的数据填充到分布式对象数据中,并将生成的sessionId
通过want
传递到对端。 - 对端在
onCreate()/onNewWant
中进行数据恢复时,可以从want中读取该sessionId
,通过分布式对象恢复数据。
使用分布式文件迁移数据
当需要迁移的数据较大(100KB以上)时,也可以选择分布式文件进行数据迁移。相比于分布式对象,分布式文件更适用于需要传输的数据为文件的场景。在源端将数据写入分布式文件路径后,对端迁移后拉起的应用能够在同个分布式文件路径下访问到该文件。
验证指导
为方便开发者验证已开发的可迁移应用,系统提供了一个全局任务中心demo作为迁移的入口。下面介绍通过安装全局任务中心来验证迁移的方式。
1. 编译安装全局任务中心
配置环境
public-SDK不支持开发者使用所有的系统API,例如:全局任务中心使用的 @ohos.distributedDeviceManager 不包括在public_SDK中。因此为了正确编译安装全局任务中心,开发者需要替换full-SDK,具体操作可参见替换指南。
说明:
本文中的截图仅为参考,具体的显示界面请以实际使用的DevEco Studio和SDK的版本为准。
下载MissionCenter_Demo 示例代码
编译工程文件
a.新建一个工程,找到对应的文件夹替换下载文件
b.自动签名,编译安装。
DevEco的自动签名模板默认签名权限为normal级。而本应用设计到ohos.permission.MANAGE_MISSIONS权限为system_core级别。自动生成的签名无法获得足够的权限,所以需要将权限升级为system_core级别,然后签名。
c.系统权限设置(以api10目录为例): 将Sdk目录下的openharmony\api版本(如:10)\toolchains\lib\UnsignedReleasedProfileTemplate.json文件中的"apl":“normal"改为"apl”:“system_core”。
- 点击file->Project Structure。
- 点击Signing Configs 点击OK。
- 连接开发板运行生成demo。
2. 设备组网
- 打开A,B两设备的计算器。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数HarmonyOS鸿蒙开发工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年HarmonyOS鸿蒙开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上HarmonyOS鸿蒙开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新
如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注鸿蒙获取)
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上HarmonyOS鸿蒙开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新
如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注鸿蒙获取)
[外链图片转存中…(img-wg941X6F-1712668934797)]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!