鸿蒙HarmonyOS应用开发——跨端迁移

打印 上一主题 下一主题

主题 595|帖子 595|积分 1785

在用户使用设备的过程中,当使用情境发生变革时(比方从室内走到户外大概附近有更得当的设备等),之前使用的设备可能已经不得当继续当前的使命,此时,用户可以选择新的设备来继续当前的使命,原设备可按需决定是否退出使命,这个就是跨端迁移的场景。常见的跨端迁移场景实例:在平板上播放的视频,迁移到智慧屏继续播放,从而得到更佳的观看体验;平板上的视频应用退出。在应用开发层面,跨端迁移指在A端运行的UIAbility迁移到B端上,完成迁移后,B端UIAbility继续使命,而A端UIAbility可按需决定是否退出。
跨端迁移的焦点使命是将应用的当前状态(包罗页面控件、状态变量等)无缝迁移到另一设备,从而在新设备上无缝接续应用体验。这意味着用户在一台设备上进行的操作可以在另一台设备的雷同应用中快速切换并无缝衔接。
重要功能包罗:


  • 支持用户自定义数据存储及规复。
  • 支持页面路由信息和页面控件状态数据的存储及规复。
  • 支持应用兼容性检测。
  • 支持应用根据现实使用场景动态设置迁移状态(默认迁移状态为 ACTIVE 激活状态)。比方,编辑类应用在编辑文本的页面下才需要迁移,其他页面不需要迁移,则可以通过setMissionContinueState进行控制。
  • 支持应用动态选择是否进行页面栈规复(默认进行页面栈信息规复)。比方,应用希望自定义迁移到其他设备后显示的页面,则可以通过SUPPORT_CONTINUE_PAGE_STACK_KEY进行控制。
  • 支持应用动态选择迁移成功后是否退出迁移源端应用(默认迁移成功后退出迁移源端应用)。可以通过SUPPORT_CONTINUE_SOURCE_EXIT_KEY进行控制。
   阐明:
开发者可以开发具有迁移能力的应用,迁移的触发由系统应用完成。
  运作机制



  • 在源端,通过UIAbility的 onContinue()回调,开发者可以生存待接续的业务数据。比方,在浏览器应用中完成跨端迁移,开发者需要使用 onContinue()回调生存页面URL等业务内容,而系统将主动生存页面状态,如当前浏览进度。
  • 分布式框架提供了跨设备应用界面、页面栈以及业务数据的生存和规复机制,它负责将数据从源端发送到对端。
  • 在对端,同一UIAbility可以通过 onCreate()/onNewWant()接口来规复业务数据。
约束限定



  • 跨端迁移要求在同一UIAbility之间进行,也就是需要雷同的bundleName、abilityName和签名信息。
  • 为了得到最佳体验,使用wantParam传输的数据需要控制在100KB以下。
  • 当前部门ArkUI组件支持迁移后,将特定状态规复到对端设备。
开发步调


  • 需要申请ohos.permission.DISTRIBUTED_DATASYNC权限。
  • 同时需要在应用初次启动时弹窗向用户申请授权,使用方式请参见 向用户申请授权 。
  • 在 module.json5设置文件 的abilities标签中设置跨端迁移标签continuable。
  1.    {
  2.      "module": {
  3.        // ...
  4.        "abilities": [
  5.          {
  6.            // ...
  7.            "continuable": true, // 配置UIAbility支持迁移
  8.          }
  9.        ]
  10.      }
  11.    }
复制代码
  阐明:
根据需要设置应用启动模式范例,设置详情请参照UIAbility组件启动模式。
  

  • 在源端UIAbility中实现 onContinue() 回调。
当UIAbility实例触发迁移时,onContinue() 回调在源端被调用,开发者可以在该接口中生存迁移数据,实现应用兼容性检测,决定是否支持此次迁移。


  • 生存迁移数据:开发者可以将要迁移的数据通过键值对的方式生存在wantParam参数中。
  • 应用兼容性检测:开发者可以通过从wantParam参数中获取对端应用的版本号与 源端应用版本号做兼容性校验。开发者可以在触发迁移时从onContinue()回调中wantParam.version获取到迁移对端应用的版本号与迁移源端应用版本号做兼容校验。
  • 迁移决策:开发者可以通过 onContinue() 回调的返回值决定是否支持此次迁移。
  1.    import UIAbility from '@ohos.app.ability.UIAbility';
  2.    import AbilityConstant from '@ohos.app.ability.AbilityConstant';
  3.    export default class EntryAbility extends UIAbility {
  4.      onContinue(wantParam: Record<string, Object>):AbilityConstant.OnContinueResult {
  5.        let version = wantParam.version;
  6.        let targetDevice = wantParam.targetDevice;
  7.        console.info(`onContinue version = ${version}, targetDevice: ${targetDevice}`); // 准备迁移数据
  8.        // 获取源端版本号
  9.        let versionSrc: number = -1; // 请填充具体获取版本号的代码
  10.        // 兼容性校验
  11.        if (version !== versionSrc) {
  12.          // 在兼容性校验不通过时返回MISMATCH
  13.          return AbilityConstant.OnContinueResult.MISMATCH;
  14.        }
  15.        // 将要迁移的数据保存在wantParam的自定义字段(例如data)中
  16.        const continueInput = '迁移的数据';
  17.        wantParam['data'] = continueInput;
  18.        return AbilityConstant.OnContinueResult.AGREE;
  19.      }
  20.    }
复制代码

  • 源端设备UIAbility实例在冷启动和热启动情况下分别会调用差别的接口来规复数据和加载UI。
    在对端设备的UIAbility中,需要实现 onCreate()/onNewWant()接口来规复迁移数据。
通过在 onCreate() / onNewWant() 回调中查抄launchReason,可以判断此次启动是否有迁移触发。开发者可以从want中获取之前生存的迁移数据,并在数据规复后调用restoreWindowStage()来触发页面规复,包罗页面栈信息。
  1.    import UIAbility from '@ohos.app.ability.UIAbility';
  2.    import AbilityConstant from '@ohos.app.ability.AbilityConstant';
  3.    import Want from '@ohos.app.ability.Want';
  4.    export default class EntryAbility extends UIAbility {
  5.      storage : LocalStorage = new LocalStorage();
  6.      onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  7.        console.info('EntryAbility onCreate')
  8.        if (launchParam.launchReason == AbilityConstant.LaunchReason.CONTINUATION) {
  9.          // 将上述的保存的数据取出恢复
  10.          let continueInput = '';
  11.          if (want.parameters != undefined) {
  12.            continueInput = JSON.stringify(want.parameters.data);
  13.            console.info(`continue input ${continueInput}`)
  14.          }
  15.          // 将数据显示当前页面
  16.          this.context.restoreWindowStage(this.storage);
  17.        }
  18.      }
  19.      onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  20.         console.info('EntryAbility onNewWant')
  21.         if (launchParam.launchReason == AbilityConstant.LaunchReason.CONTINUATION) {
  22.           // get user data from want params
  23.           let continueInput = '';
  24.           if (want.parameters != undefined) {
  25.             continueInput = JSON.stringify(want.parameters.data);
  26.             console.info(`continue input ${continueInput}`);
  27.           }
  28.           this.context.restoreWindowStage(this.storage);
  29.         }
  30.       }
  31.    }
复制代码
可选设置迁移能力

动态设置迁移能力

从API version 10开始,提供了支持动态设置迁移能力的功能。即应用可以根据现实使用场景,在需要迁移时开启应用迁移能力;在业务不需要迁移时则可以关闭迁移能力。
开发者可以通过调用 setMissionContinueState() 接口对迁移能力进行设置。默认状态下,应用的迁移能力为ACTIVE状态,即迁移能力开启,可以迁移。
设置迁移能力的时机
迁移能力的改变可以根据现实业务需求和代码实现,发生在应用生命周期的绝大多数时机。本文先容常用的几种设置方式。
在UIAbility的 onCreate() 回调中调用接口,可以在应用创建时设置应用的迁移状态。
  1. // EntryAbility.ets
  2. import UIAbility from '@ohos.app.ability.UIAbility';
  3. import AbilityConstant from '@ohos.app.ability.AbilityConstant';
  4. import Want from '@ohos.app.ability.Want';
  5. export default class EntryAbility extends UIAbility {
  6.   onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  7.     // ...
  8.     this.context.setMissionContinueState(AbilityConstant.ContinueState.INACTIVE, (result) => {
  9.       console.info(`setMissionContinueState: ${JSON.stringify(result)}`);
  10.     });
  11.     // ...
  12.   }
  13. }
复制代码
在页面的onPageShow()回调中调用接口,可以设置单个页面出现时应用的迁移状态。
  1. // PageName.ets
  2. import AbilityConstant from '@ohos.app.ability.AbilityConstant';
  3. import common from '@ohos.app.ability.common';
  4. @Entry
  5. @Component
  6. struct PageName {
  7.   private context = getContext(this) as common.UIAbilityContext;
  8.   build() {
  9.     // ...
  10.   }
  11.   // ...
  12.   onPageShow(){
  13.   // 进入该页面时,将应用设置为可迁移状态
  14.     this.context.setMissionContinueState(AbilityConstant.ContinueState.ACTIVE, (result) => {
  15.       console.info(`setMissionContinueState ACTIVE result: ${JSON.stringify(result)}`);
  16.     });
  17.   }
  18. }
复制代码
在某个组件的触发事件中设置应用迁移能力。
  1. // PageName.ets
  2. import AbilityConstant from '@ohos.app.ability.AbilityConstant';
  3. import common from '@ohos.app.ability.common';
  4. @Entry
  5. @Component
  6. struct PageName {
  7.   private context = getContext(this) as common.UIAbilityContext;
  8.   build() {
  9.     // ...
  10.     Button() {
  11.       // ...
  12.     }.onClick(()=>{
  13.     // 点击该按钮时,将应用设置为可迁移状态
  14.       this.context.setMissionContinueState(AbilityConstant.ContinueState.ACTIVE, (result) => {
  15.         console.info(`setMissionContinueState ACTIVE result: ${JSON.stringify(result)}`);
  16.       });
  17.     })
  18.   }
  19. }
复制代码
保证迁移连续性
由于迁移加载时,对端拉起的应用可能执行过本身的迁移状态设置命令(比方,冷启动时对端在 onCreate() 中设置了 INACTIVE ;热启动时对端已打开了不可迁移的页面,迁移状态为 INACTIVE 等情况)。为了保证迁移过后的应用依然具有可以迁移回源端的能力,应在  onCreate()/ onNewWant() 的迁移调用判断中,将迁移状态设置为 ACTIVE 。
  1. // EntryAbility.ets
  2. import UIAbility from '@ohos.app.ability.UIAbility';
  3. import AbilityConstant from '@ohos.app.ability.AbilityConstant';
  4. import Want from '@ohos.app.ability.Want';
  5. export default class EntryAbility extends UIAbility {
  6.   // ...
  7.   onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  8.     // ...
  9.     // 调用原因为迁移时,设置状态为可迁移,应对冷启动情况
  10.     this.context.setMissionContinueState(AbilityConstant.ContinueState.INACTIVE, (result) => {
  11.         console.info(`setMissionContinueState INACTIVE result: ${JSON.stringify(result)}`);
  12.     });
  13.   }
  14.   onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  15.     // ...
  16.     // 调用原因为迁移时,设置状态为可迁移,应对热启动情况
  17.     if (launchParam.launchReason == AbilityConstant.LaunchReason.CONTINUATION) {
  18.       this.context.setMissionContinueState(AbilityConstant.ContinueState.ACTIVE, (result) => {
  19.         console.info(`setMissionContinueState ACTIVE result: ${JSON.stringify(result)}`);
  20.       });
  21.     }
  22.   }
  23.   // ...
  24. }
复制代码
按需迁移页面栈

支持应用动态选择是否进行页面栈规复(默认进行页面栈信息规复)。如果应用不想使用系统默认规复的页面栈,则可以设置不进行页面栈迁移,而需要在onWindowStageRestore()设置迁移后进入的页面,参数定义见SUPPORT_CONTINUE_PAGE_STACK_KEY。
应用在源端的页面栈中存在Index和Second路由,而在对端规复时不需要按照源端页面栈进行规复,需要规复到指定页面。
比方,UIAbility迁移不需要主动迁移页面栈信息。
  1. // EntryAbility.ets
  2. import UIAbility from '@ohos.app.ability.UIAbility';
  3. import AbilityConstant from '@ohos.app.ability.AbilityConstant';
  4. import wantConstant from '@ohos.app.ability.wantConstant';
  5. import window from '@ohos.window';
  6. export default class EntryAbility extends UIAbility {
  7.   // ...
  8.   onContinue(wantParam: Record<string, Object>) {
  9.     console.info(`onContinue version = ${wantParam.version}, targetDevice: ${wantParam.targetDevice}`);
  10.     wantParam[wantConstant.Params.SUPPORT_CONTINUE_PAGE_STACK_KEY] = false;
  11.     return AbilityConstant.OnContinueResult.AGREE;
  12.   }
  13.   onWindowStageRestore(windowStage: window.WindowStage) {
  14.       // 若不需要自动迁移页面栈信息,则需要在此处设置应用迁移后进入的页面
  15.     windowStage.loadContent('pages/Index', (err, data) => {
  16.       if (err.code) {
  17.         return;
  18.       }
  19.     });
  20.   }
  21. }
复制代码
按需退出

支持应用动态选择迁移成功后是否退出迁移源端应用(默认迁移成功后退出迁移源端应用)。如果应用不想让系统主动退出迁移源端应用,则可以设置不退出,参数定义见SUPPORT_CONTINUE_SOURCE_EXIT_KEY。
示例:UIAbility设置迁移成功后,源端不需要退出迁移应用。
  1. import UIAbility from '@ohos.app.ability.UIAbility';
  2. import AbilityConstant from '@ohos.app.ability.AbilityConstant';
  3. import wantConstant from '@ohos.app.ability.wantConstant';
  4. export default class EntryAbility extends UIAbility {
  5.   // ...
  6.   onContinue(wantParam: Record<string, Object>) {
  7.     console.info(`onContinue version = ${wantParam.version}, targetDevice: ${wantParam.targetDevice}`);
  8.     wantParam[wantConstant.Params.SUPPORT_CONTINUE_SOURCE_EXIT_KEY] = false;
  9.     return AbilityConstant.OnContinueResult.AGREE;
  10.   }
  11. }
复制代码
验证指导

为方便开发者验证已开发的可迁移应用,当前OpenHarmony提供了一个全局使掷中央demo作为迁移的入口。下面先容通过安装全局使掷中央来验证迁移的方式。
1. 编译安装全局使掷中央

设置情况

public-SDK不支持开发者使用全部的系统API,比方:全局使掷中央使用的**@ohos.distributedDeviceManager**不包罗在public_SDK中。因此为了精确编译安装全局使掷中央,开发者需要替换full-SDK,详细操作可参见 替换指南。
   阐明
本文中的截图仅为参考,详细的显示界面请以现实使用的DevEco Studio和SDK的版本为准。
  编译工程文件

​ a.新建OpenHarmony 空的工程,找到对应的文件夹替换下载文件

​ b.主动签名,编译安装。
​ DevEco的主动签名模板默认签名权限为normal级。而本应用计划到ohos.permission.MANAGE_MISSIONS权限为system_core级别。主动天生的签名无法得到足够的权限,以是需要将权限升级为system_core级别,然后签名。
​ c.系统权限设置(以api10目次为例): 将Sdk目次下的openharmony\api版本(如:10)\toolchains\lib\UnsgnedReleasedProfileTemplate.json文件中的”apl”:“normal_core”改为”apl”:“system_core”。

  • 点击file->roject Structure。


  • 点击Signing Configs 点击OK。


  • 毗连开发板运行天生demo。
2. 设备组网


  • 打开A,B两设备的计算器。
  • 点击右上角箭头选择B设备。
  • 在B设备选择信任设备,弹出PIN码。
  • 在A设备输入PIN码。
  • 已组网成功,验证方法:在A设备输入数字,B设备同步出现则证明组网成功。
3. 发起迁移


  • 在B设备打开多设备协同权限的应用,A设备打开全局使掷中央demo,A设备出现A设备名称(即:本机:OpenHarmony 3.2)和B设备名称(OpenHarmony 3.2)。


  • 点击B设备名称,然后出现B设备的应用。


  • 最后将应用拖拽到A设备名称处,A设备应用被拉起,B设备应用退出。

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05
《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05


  • 根本概念
  • 构建第一个ArkTS应用
  • ……

开发底子知识:https://qr21.cn/FV7h05


  • 应用底子知识
  • 设置文件
  • 应用数据管理
  • 应用安全管理
  • 应用隐私保护
  • 三方应用调用管控机制
  • 资源分类与访问
  • 学习ArkTS语言
  • ……

基于ArkTS 开发:https://qr21.cn/FV7h05


  • Ability开发
  • UI开发
  • 公共事件与关照
  • 窗口管理
  • 媒体
  • 安全
  • 网络与链接
  • 电话服务
  • 数据管理
  • 后台使命(Background Task)管理
  • 设备管理
  • 设备使用信息统计
  • DFX
  • 国际化开发
  • 折叠屏系列
  • ……

鸿蒙开发口试真题(含参考答案):https://qr18.cn/F781PH


鸿蒙开发口试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备口试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

自由的羽毛

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表