HarmonyOSApp开发入门(七):实现跨设备迁移Migration一、分布式任务调度概述在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(FeatureAbility,PageTemplateAbility)的调用支持启动和迁移行为。调度时:(1)启动FA时,开发者需要在Intent中指定对端设备的deviceId、bundleName和abilityName。(2)FA迁移实现FA跨设备迁移,bundleName和abilityName相同,所以需要指定迁移设备的deviceId。3、实现场景介绍下面以设备A(本地设备)和设备B(远程设备)为例,介绍以下我们要实现的场景:1)设备A激活设备B的FA:在设备A上通过a提供按钮上的本地应用启动按钮,启动设备B上对应的FA。2)设备A的FA迁移到设备B:设备A的服务通过本地应用提供的迁移按钮无缝迁移到设备B3)将设备A的FA迁移到设备B,也可以实现主动退出和迁移。4、在具体实现之前了解要使用的接口1)启动远程FAstartAbility(Intent意图)接口,提供在指定设备上启动FA和PA的能力。Intent中指定了要启动的设备FA的deviceId、bundleName和abilityName。2)MigrateFAcontinueAbility(StringdeviceId)接口提供了将本地FA迁移到指定设备的能力,continueAbilityReversibly(StringdeviceId)接口提供了将本地FA迁移到指定设备的能力,本次迁移可以撤销,reverseContinueAbility()接口提供撤消迁移的能力。五、实战远程启动FA页面1)实现上述场景界面的程序:ability_main.xml.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);//判断联网设备是否为空);ArrayListdeviceNames=newArrayList<>(numDevices);onlineDevices.forEach((device)->{deviceIds.add(device.getDeviceId());deviceNames.add(device.getDeviceName());});//我们这里只有两个设备,所以选择第一个设备作为目标设备//开发者也可以根据具体场景通过其他方式选择设备StringselectDeviceId=deviceIds.get(0);//获取设备ID,就是最好放在工具类里,有很多地方可以使用!if(selectDeviceId!=null){Intentintent2=newIntent();Operationoperation=newIntent.OperationBuilder().withDeviceId(selectDeviceId).withBundleName("cn.ybzy.hmsdemo").withAbilityName("cn.ybzy.hmsdemo.RemoteAbility").withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE).build();intent2.setOperation(operation);//通过AbilitySlice自带的startAbility接口启动跨设备FAstartAbility(intent2);}}});6.将设备A运行时的FA迁移到设备B,实现设备间业务的无缝迁移MigrationAbilitypublicclassMigrationAbilityextendsAbilityimplementsIAbilityContinuation{@OverridepublicvoidonStart(Intentintent){super.onStart(intent);super.setMainRoute(MigrationAbilitySlice.class.getName());}@OverridepublicbooleanonStartContinuation(){returntrue;}@OverridepublicbooleanonSaveData(IntentParamsintentParamSaveData(IntentParamsintentParamParams)@returnrideParams@returnrideParams@returntrue;}){returntrue;}@OverridepublicvoidonCompleteContinuation(inti){}}MigrationAbilitySlicepublicclassMigrationAbilitySliceextendsAbilitySliceimplementsIAbilityContinuation{TextFieldtextField;StringtextStr="请输入数据...";@OverridepublicvoidonStart(Intentent){super.onStart(intent);super.ResourceTablemigration.Layout(intent);textField=(TextField)findComponentById(ResourceTable.Id_textfield_migration);textField.setText(textStr);Buttonbtn=(Button)findComponentById(ResourceTable.Id_migration_button);btn.setClickedListener(newComponent.ClickedListener(){@OverridepublicvoidonClick(Componentcomponent){StringdeviceId=getDeviceId();if(deviceId!=null){continueAbility(deviceId);}}});}privateStringgetDeviceId(){//调用DeviceManager的getDeviceList接口并标记withFLAG_GET_ONLINE_DEVICE获取在线设备列表ListonlineDevices=DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);//判断联网设备是否为空if(onlineDevices.isEmpty()){returnnull;}intnumDevices=onlineDevices.size();ArrayListdeviceIds=newArrayList<>(numDevices);ArrayListdeviceNames=newArrayList<>(numDevices);onlineDevices.forEach((device)->{deviceIds.add(device.getDeviceId());deviceNames。add(device.getDeviceName());});//我们这里只有两个设备,所以选择第一个设备作为目标设备//开发者也可以根据具体场景通过其他方式选择设备StringselectDeviceId=deviceIds.get(0);returnselectDeviceId;}@OverridepublicbooleanonStartContinuation(){returntrue;}@OverridepublicbooleanonSaveData(IntentParamsintentParams){intentParams.setParam("data",textField.getText());返回true;}@OverridepublicbooleanonRestoreData(IntentParamsintentParams){textStr=intentParams.getParam("data").toString();returntrue;}@OverridepublicvoidonCompleteContinuation(inti){}@OverridepublicvoidonRemoteTerminated(){}}此外,与启动行为不同,FA的迁移还涉及状态数据的传输。为此,继承的IAbilityContinuation接口为开发者提供了在迁移过程中管理特定事件的能力。通过自定义迁移事件相关的行为,最终实现Ability的迁移。常用的事件主要有两个,一个是迁移发起者完成迁移的回调onCompleteContinuation(intresult),另一个是接收远程迁移行为下发数据的回调onRestoreData(IntentParamsrestoreData)。其他还有迁移到远程设备时FA关闭的回调onRemoteTerminated(),本地迁移启动时保存状态数据的回调onSaveData(IntentParamssaveData),本地启动迁移的回调onStartContinuation()。7.请求回滚Buttonbtn1=(Button)findComponentById(ResourceTable.Id_migration_button_back);btn1.setClickedListener(newComponent.ClickedListener(){@OverridepublicvoidonClick(Componentcomponent){StringdeviceId=DeviceUtils.getDeviceId();if(deviceIdtin=Abil){condeviceId);//可以撤销迁移}}});Buttonbtn2=(Button)findComponentById(ResourceTable.Id_migration_button_back2);btn2.setClickedListener(newComponent.ClickedListener(){@OverridepublicvoidonClick(Componentcomponent){reverseContinueAbility();//撤销迁移}});1)设备A上的页面请求抓取。2)系统回调Page中所有AbilitySlice实例的IAbilityContinuation.onStartContinuation()方法及其在设备B上的AbilitySlice栈,确认当前是否可以立即迁移。3)如果可以立即迁移,则系统回调Page中所有AbilitySlice实例的IAbilityContinuation.onSaveData()方法及其在设备B上的AbilitySlice栈,以保存恢复fetch后状态所需的数据。4)如果数据保存成功,系统在设备A上恢复Page上的AbilitySlice栈,然后回调IAbilityContinuation.onRestoreData()方法传递之前保存的数据。5)如果数据恢复成功,则系统终止Page在设备B上的生命周期。?版权归作者和HarmonyOS技术社区共同所有。如需转载请注明出处,否则追究责任。51cto.com/#zz