您现在的位置是:亿华云 > 数据库

鸿蒙应用开发入门(七):实现跨设备迁移

亿华云2025-10-03 18:20:53【数据库】5人已围观

简介想了解更多内容,请访问:和华为官方合作共建的鸿蒙技术社区https://harmonyos.51cto.com/#zz6.2 跨设备迁移1. 分布式任务调度概述在HarmonyOS中,分布式任务调度平

想了解更多内容,鸿蒙请访问:

和华为官方合作共建的应用移鸿蒙技术社区

https://harmonyos.51cto.com/#zz

6.2 跨设备迁移

1. 分布式任务调度概述

在HarmonyOS中,分布式任务调度平台对搭载HarmonyOS的开发跨设多设备构筑的“超级虚拟终端”提供统一的组件管理能力,为应用定义统一的入门能力基线、接口形式、实现数据结构、备迁服务描述语言,鸿蒙屏蔽硬件差异;支持远程启动、应用移远程调用、开发跨设业务无缝迁移等分布式任务。入门

2. 实现调度的实现约束与限制

1)远程调用PA/FA,开发者需要在Intent中设置支持分布式的备迁标记(例如:Intent.FLAG_ABILITYSLICE_MULTI_DEVICE表示该应用支持分布式调度),否则将无法获得分布式能力。鸿蒙

2)开发者通过在config.json中的应用移reqPermissions字段里添加权限申请:

(1)以获取跨设备连接的能力和分布式数据传输的权限。

分布式数据传输的开发跨设权限:

{ "name": "ohos.permission.servicebus.ACCESS_SERVICE"} 

三方应用使用权限:

{ "name": "ohos.permission.servicebus.DISTRIBUTED_DATASYNC"} 

系统应用使用权限:

{ "name": "com.huawei.hwddmp.servicebus.BIND_SERVICE"} 

(2)另外还有三个获取分布式设备信息需要的权限:

{ "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE"}, { "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO" }, {  "name": "ohos.permission.GET_BUNDLE_INFO"} 

 注意:还需要在开发的时候,要在Ability里主动声明,要用到的权限。

3)FA(Feature Ability,Page模板的Ability)的网站模板调用支持启动和迁移行为,在进行调度时:

(1)当启动FA时,需要开发者在Intent中指定对端设备的deviceId、bundleName和abilityName。

(2)FA的迁移实现相同bundleName和abilityName的FA跨设备迁移,因此需要指定迁移设备的deviceId。

3. 实现场景介绍

下面以设备A(本地设备)和设备B(远端设备)为例,介绍下面我们要实现的场景:

1)设备A启动设备B的FA:在设备A上通过本地应用提供的启动按钮,启动设备B上对应的FA。

2)设备A的FA迁移至设备B:设备A上通过本地应用提供的迁移按钮,将设备A的业务无缝迁移到设备B中。

3)设备A的FA迁移至设备B,还可以实现主动撤回迁移。

4. 具体实现前先了解要用的接口

1)启动远程FA

startAbility(Intent intent)接口提供启动指定设备上FA和PA的能力,Intent中指定待启动FA的设备deviceId、bundleName和abilityName。

2)迁移FA

continueAbility(String deviceId)接口提供将本地FA迁移到指定设备上的能力,云服务器提供商continueAbilityReversibly(String deviceId) 接口提供将本地FA迁移到指定设备上的能力,这种迁移可撤回, reverseContinueAbility()接口提供撤回迁移的能力。

5. 实战远程启动FA页面

1)编程实现上面场景的界面:

ability_main.xml 

<?xml version="1.0" encoding="utf-8"?> <DirectionalLayout     xmlns:ohos="http://schemas.huawei.com/res/ohos"     ohos:height="match_parent"     ohos:width="match_parent"     ohos:orientation="vertical">      <Button         ohos:id="$+id:migration_btn_01"         ohos:height="match_content"         ohos:width="300vp"         ohos:text="1.启动远程设备的FA"         ohos:text_size="20fp"         ohos:text_color="#ffffff"         ohos:background_element="$graphic:button_bg"         ohos:layout_alignment="horizontal_center"         ohos:top_padding="8vp"         ohos:bottom_padding="8vp"         ohos:left_padding="40vp"         ohos:right_padding="40vp"         ohos:top_margin="20vp"         />      <Button         ohos:id="$+id:migration_btn_02"         ohos:height="match_content"         ohos:width="300vp"         ohos:text="2.迁移到远程设备"         ohos:text_size="20fp"         ohos:text_color="#ffffff"         ohos:background_element="$graphic:button_bg"         ohos:layout_alignment="horizontal_center"         ohos:top_padding="8vp"         ohos:bottom_padding="8vp"         ohos:left_padding="40vp"         ohos:right_padding="40vp"         ohos:top_margin="20vp"         />       <Button         ohos:id="$+id:migration_btn_03"         ohos:height="match_content"         ohos:width="300vp"         ohos:text="3.可迁回的迁移远程设备"         ohos:text_size="20fp"         ohos:text_color="#ffffff"         ohos:background_element="$graphic:button_bg"         ohos:layout_alignment="horizontal_center"         ohos:top_padding="8vp"         ohos:bottom_padding="8vp"         ohos:left_padding="40vp"         ohos:right_padding="40vp"         ohos:top_margin="20vp"         /> </DirectionalLayou 

 button_bg.xml

<?xml version="1.0" encoding="utf-8"?> <shape  xmlns:ohos="http://schemas.huawei.com/res/ohos"         ohos:shape="rectangle">     <solid ohos:color="#007DFF"/>     <corners ohos:radius="40"/> </ 

 MigrationAbility和MigrationBackAbility

// 调用AbilitySlice模板实现一个用于控制基础功能的FA // Ability和AbilitySlice类均需要实现IAbilityContinuation及其方法,才可以实现FA迁移。AbilitySlice的代码示例如下 public class SampleSlice extends AbilitySlice implements IAbilityContinuation {      @Override     public void onStart(Intent intent) {          super.onStart(intent);                 super.setUIContent(layout);     } 

ability_migration.xml

<?xml version="1.0" encoding="utf-8"?> <DirectionalLayout     xmlns:ohos="http://schemas.huawei.com/res/ohos"     ohos:height="match_parent"     ohos:width="match_parent"     ohos:background_element="#00ffff"     ohos:orientation="vertical">      <Text         ohos:id="$+id:text_title"         ohos:height="match_content"         ohos:width="250vp"         ohos:background_element="#0088bb"         ohos:layout_alignment="horizontal_center"         ohos:text="下面是一个可编辑的文本框"         ohos:text_size="50"         ohos:padding="5vp"         ohos:top_margin="30vp"         />      <TextField         ohos:id="$+id:textfield_back"         ohos:height="250vp"         ohos:width="250vp"         ohos:hint="请输入..."         ohos:layout_alignment="horizontal_center"         ohos:background_element="#ffffff"         ohos:text_color="#888888"         ohos:text_size="20fp"         ohos:padding="5vp"         />     <Button         ohos:id="$+id:migration_button"         ohos:height="match_content"         ohos:width="match_content"         ohos:text="点击迁移"         ohos:text_size="20fp"         ohos:text_color="#ffffff"         ohos:background_element="$graphic:button_bg"         ohos:top_padding="8vp"         ohos:bottom_padding="8vp"         ohos:left_padding="50vp"         ohos:right_padding="50vp"         ohos:layout_alignment="horizontal_center"         ohos:top_margin="30vp"         /> </DirectionalLayou 

 ability_migration_back.xml比ability_migration.xml多一个迁回按钮,另外主页上点击按钮跳转等,略...

2)使用分布式能力要求开发者在Ability对应的config.json中声明多设备协同访问的权限:

(1)三方应用部署权限、分布式数据传输的权限、系统应用使用权限的申请。

{      "reqPermissions": [         { "name": "ohos.permission.DISTRIBUTED_DATASYNC"},         { "name": "ohos.permission.servicebus.ACCESS_SERVICE"},         { "name": "com.huawei.hwddmp.servicebus.BIND_SERVICE"}          ] } 

 (2)声明分布式获取设备列表及设备信息的权限,如下所示:

{      "reqPermissions": [         { "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE"},          { "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO" },          { "name": "ohos.permission.GET_BUNDLE_INFO"}     ] } 

 (3)对于三方应用还要求在实现Ability的代码中显式声明需要使用的权限。 

public class SampleSlice extends AbilitySlice implements IAbilityContinuation {      @Override     public void onStart(Intent intent) {          // 开发者显示声明需要使用的权限         requestPermissionsFromUser(new String[]{ "ohos.permission.DISTRIBUTED_DATASYNC",                                                 "ohos.permission.servicebus.ACCESS_SERVICE",                                                 "com.huawei.hwddmp.servicebus.BIND_SERVICE"}, 0);         super.onStart(intent);             } } 

 3) 为启动远程FA的按钮添加点击事件,获取设备信息,实现启动远程FA的亿华云能力。 

Button btn1 = (Button) findComponentById(ResourceTable.Id_migration_btn_01); btn1.setClickedListener(new Component.ClickedListener() {      @Override     public void onClick(Component component) {          // 调用DeviceManager的getDeviceList接口,通过FLAG_GET_ONLINE_DEVICE标记获得在线设备列表         List<DeviceInfo> onlineDevices = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);         // 判断组网设备是否为空         if (onlineDevices.isEmpty()) {              return;         }         int numDevices = onlineDevices.size();          ArrayList<String> deviceIds = new ArrayList<>(numDevices);         ArrayList<String> deviceNames = new ArrayList<>(numDevices);         onlineDevices.forEach((device) -> {              deviceIds.add(device.getDeviceId());             deviceNames.add(device.getDeviceName());         });         // 我们这里只有两个设备,所以选择首个设备作为目标设备         // 开发者也可按照具体场景,通过别的方式进行设备选择         String selectDeviceId = deviceIds.get(0);                  //获取设备ID,最好放到工具类里,很多地方要用!          if(selectDeviceId!=null){              Intent intent2 = new Intent();             Operation operation = new Intent.OperationBuilder()                     .withDeviceId(selectDeviceId)                     .withBundleName("cn.ybzy.hmsdemo")                     .withAbilityName("cn.ybzy.hmsdemo.RemoteAbility")                     .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)                     .build();             intent2.setOperation(operation);             // 通过AbilitySlice包含的startAbility接口实现跨设备启动FA             startAbility(intent2);         }     } }); 

 6. 实战将设备A运行时的FA迁移到设备B,实现业务在设备间无缝迁移。

MigrationAbility

public class MigrationAbility extends Ability implements IAbilityContinuation  {      @Override     public void onStart(Intent intent) {          super.onStart(intent);         super.setMainRoute(MigrationAbilitySlice.class.getName());     }      @Override     public boolean onStartContinuation() {          return true;     }      @Override     public boolean onSaveData(IntentParams intentParams) {          return true;     }      @Override     public boolean onRestoreData(IntentParams intentParams) {          return true;     }      @Override     public void onCompleteContinuation(int i) {       } } 

 MigrationAbilitySlice 

public class MigrationAbilitySlice extends AbilitySlice implements IAbilityContinuation {      TextField textField;     String textStr = "请输入数据...";     @Override     public void onStart(Intent intent) {          super.onStart(intent);         super.setUIContent(ResourceTable.Layout_ability_migration);         textField = (TextField)findComponentById(ResourceTable.Id_textfield_migration);         textField.setText(textStr);         Button btn = (Button) findComponentById(ResourceTable.Id_migration_button);         btn.setClickedListener(new Component.ClickedListener() {              @Override             public void onClick(Component component) {                  String deviceId = getDeviceId();                 if(deviceId!=null){                      continueAbility(deviceId);                 }             }         });      }      private String getDeviceId(){          // 调用DeviceManager的getDeviceList接口,通过FLAG_GET_ONLINE_DEVICE标记获得在线设备列表         List<DeviceInfo> onlineDevices = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);         // 判断组网设备是否为空         if (onlineDevices.isEmpty()) {              return null;         }         int numDevices = onlineDevices.size();          ArrayList<String> deviceIds = new ArrayList<>(numDevices);         ArrayList<String> deviceNames = new ArrayList<>(numDevices);         onlineDevices.forEach((device) -> {              deviceIds.add(device.getDeviceId());             deviceNames.add(device.getDeviceName());         });         // 我们这里只有两个设备,所以选择首个设备作为目标设备         // 开发者也可按照具体场景,通过别的方式进行设备选择         String selectDeviceId = deviceIds.get(0);         return selectDeviceId;     }      @Override     public boolean onStartContinuation() {          return true;     }      @Override     public boolean onSaveData(IntentParams intentParams) {          intentParams.setParam("data",textField.getText());         return true;     }      @Override     public boolean onRestoreData(IntentParams intentParams) {          textStr = intentParams.getParam("data").toString();         return true;     }      @Override     public void onCompleteContinuation(int i) {       }      @Override     public void onRemoteTerminated() {       } } 

 此外,不同于启动行为,FA的迁移还涉及到状态数据的传递。为此,继承的IAbilityContinuation接口为开发者提供迁移过程中特定事件的管理能力。通过自定义迁移事件相关的行为,最终实现对Ability的迁移。主要以较为常用的两个事件,包括迁移发起端完成迁移的回调onCompleteContinuation(int result)以及接收到远端迁移行为传递数据的回调onRestoreData(IntentParams restoreData)。其他还包括迁移到远端设备的FA关闭的回调onRemoteTerminated()、用于本地迁移发起时保存状态数据的回调onSaveData(IntentParams saveData)和本地发起迁移的回调onStartContinuation()。

7. 请求回迁

Button btn1 = (Button) findComponentById(ResourceTable.Id_migration_button_back); btn1.setClickedListener(new Component.ClickedListener() {      @Override     public void onClick(Component component) {          String deviceId = DeviceUtils.getDeviceId();         if(deviceId!=null){              continueAbilityReversibly(deviceId);  //可撤回迁移         }     } });  Button btn2 = (Button) findComponentById(ResourceTable.Id_migration_button_back2); btn2.setClickedListener(new Component.ClickedListener() {      @Override     public void onClick(Component component) {          reverseContinueAbility();  //撤回迁移     } }); 

 1)设备A上的Page请求回迁。

2)系统回调设备B上Page及其AbilitySlice栈中所有AbilitySlice实例的IAbilityContinuation.onStartContinuation()方法,以确认当前是否可以立即迁移。

3)如果可以立即迁移,则系统回调设备B上Page及其AbilitySlice栈中所有AbilitySlice实例的IAbilityContinuation.onSaveData()方法,以便保存回迁后恢复状态必须的数据。

4)如果保存数据成功,则系统在设备A上Page恢复AbilitySlice栈,然后回调IAbilityContinuation.onRestoreData()方法,传递此前保存的数据。

5)如果数据恢复成功,则系统终止设备B上Page的生命周期。

©著作权归作者和HarmonyOS技术社区共同所有,如需转载,请注明出处,否则将追究法律责任

想了解更多内容,请访问:

和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com/#zz

-->

很赞哦!(576)