更多内容请访问:与华为官方共建的HarmonyOS技术社区https://harmonyos.51cto.com前言这里是HarmonyOS文档学习|TaskScheduling|MindMap是关于文档部分的思维导图,里面的知识也用于跨设备调用。本文只是一个使用手册和代码的补充部分。不建议只根据本文练习。正确的做法是下载附件中的源码,对照源码和文章的步骤,进行实践复现。跨设备跳转是页面跳转的高级版本。如果你不熟悉页面跳转,可以在我的第一个镜头上练习。由于Android中没有跨设备接口,需要自己写实现。在鸿蒙中,只需要一两行代码就可以实现跨设备的核心操作。内容迁移到过去,可以撤回迁移。仅支持单向控制文本。一、实现步骤跨设备调用属于不同的页面跳转,所以必须有两个以上的Abilities第一步:创建多个Abilities。创建完成后,会在自动生成slice、layout、graphic中对应的文件Step2:编写xml布局文件,这里只是一个简单的例子,所以只有简单的内容Step3:编写业务逻辑代码1.声明权限因为涉及到跨设备调度,所以为了安全,需要获取权限交互声明获取设备列表的权限,即设备信息config.json"reqPermissions":[{"name":"ohos.permission.DISTRIBUTED_DATASYNC"},{"name":"ohos.permission.GET_BUNDLE_INFO"},{"name":"ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE"},{"name":"ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"}]注意:第三方应用使用:ohos.permission.DISTRIBUTED_DATASYNC也需要在main的Ability代码中显式声明publicclassMainAbilityextendsAbility{@OverridepublicvoidonStart(Intentintent){super.onStart(intent);super.setMainRoute(MainAbilitySlice.class.getName());//一个第三方应用程序权限的主动声明requestPermissionsFromUser(newString[]{"ohos.permission.DISTRIBUTED_DATASYNC"},0);}}2.获取设备ID只有获取设备ID并跳转才会root根据Id进行页面迁移3.实现迁移功能代码...补充模拟器如何分布式跨设备测试:如何开启更多的模拟器进行分布式应用开发(DES2.1版本之前,只能使用真机进行分布式跨设备测试)devicetesting)Devicedevelopment)1.确保你的DES版本在2.1以上,可以通过Help>CheckforUpdates进行更新2.更新后,你还可以更新自己的SDK和Previewer(Previewer很好用,你可以不用开模拟器直接写layoutPreview)3.点击SDKPlatforms和SDKTools查看,我这里已经更新了,反正内存多~4.更新完成后,可以到File>Settings或者按Ctrl+Alt+S快捷键进入设置面板,点击DevEcoLabs,勾选EnableSuperDevice(其他的也可以勾选,JavaPreviewer好用,写好xml布局文件后,点击最右边的导航酒吧或按铝t+3topreview)5.然后你可以看到模拟器上有更多的SuperDevices。核心代码部分2.1。只迁移页面内容到MainAbilitySlice.java//通过组件id获取组件btn1=(Button)findComponentById(ResourceTable.Id_migration_btn_01);//设置按钮的点击监听事件btn1.setClickedListener(component->{//To实现跨设备开启FA//第一步当然是获取设备id//通过设备管理获取设备列表方法ListdeviceList=DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);//判断为空if(deviceList.isEmpty()){returnnull;}//获取设备数量intdeviceNum=deviceList.size();//创建两个列表,存储设备id和设备名称ArrayListdeviceIds=newArrayList<>(deviceNum);大批ListdeviceNames=newArrayList<>(deviceNum);//遍历设备列表,将设备id和设备名称分别存入两个列表deviceList.forEach(device->{deviceIds.add(device.getDeviceId());deviceNames.add(device.getDeviceName());});//我直接使用deviceIds的第一个元素作为目标id来启动远程deviceStringdeviceId=deviceIds.get(0);if(deviceId!=null){//NewIntent,intent:信息载体Intentbtn_1_intent=newIntent();//OperationBuilder()方法Operationoperation=newIntent.OperationBuilder().withDeviceId(deviceId)//获取设备id,本地可以为空withBundleName("com.anzia.study_2")//包名,可以在config.json.withAbilityName("com.anzia.study_2.RemoteAbility")//设置目标页面,路径名必填!!!.withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)//设置标签允许跨设备。build();//构建btn_1_intent.setOperation(operation);//保存操作到intentstartAbility(btn_1_intent);}});测试结果:这里使用的是模拟器。该项目需要打包并安装在两个模拟上。安装完成后,会提示用户获取权限。只有获得权限后才能获取设备Id,从而跳转到跨设备页面。单击第一个按钮以查看在另一台设备上启动2.2。迁移编辑内容,支持双向控制由于这部分获取设备Id的代码经常用到,所以可以封装成一个工具类。如果想获取设备Id,只需要实现这个工具类即可DeviceUtils.javapublicclassDeviceUtils{publicstaticStringgetDeviceId(){//通过设备管理方法获取设备列表获取ListdeviceList=DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);//判断为空if(deviceList.isEmpty()){returnnull;}//获取设备个数intdeviceNum=deviceList.size();//创建两个列表,分别存放设备id和设备名称ArrayListdeviceIds=newArrayList<>(deviceNum);ArrayListdeviceNames=newArrayList<>(deviceNum);//遍历设备列表,将设备id和设备名称分别存储在两个列表中deviceList.forEach(device->{deviceIds.add(device.getDeviceId());deviceNames.add(device.getDeviceName());});//我直接以deviceIds的第一个元素为目标,启动远程设备idStringdeviceIdStr=deviceIds.get(0);returndeviceIdStr;}}实现交互页面使用新的ElementName()设备模板页面路径跳入MainAbilitySlice.javabtn2=(Button)findComponentById(ResourceTable.Id_migration_btn_02);btn2.setClickedListener(component->{Intentbtn_2_intent=newIntent();ElementNamemigrationSliceEn=newElementName("","com.anzia.study_2","MigrationAbility");btn_2_intent.setElement(migrationSliceEn);startAbility(btn_2_intent);});要将正在编辑的文本迁移到其他设备,需要为目标Ability和Slice实现IAbilityContinuation接口,构造方法设置为trueMigrationAbility.javaMigrationAbilitySlice.javapublicclassMigrationAbilitySliceextendsAbilitySliceimplementsIAbilityContinuation{BprivateStringFieldnutttextField;"";@OverridepublicvoidonStart(Intentintent){super.onStart(intent);super.setUIContent(ResourceTable.Layout_ability_migration);//编辑文本textField=(TextField)findComponentById(ResourceTable.Id_textfield_migration);//默认为空textField。setText(tfStr);mgBtn=(Button)findComponentById(ResourceTable.Id_migration_button);mgBtn.setClickedListener(component->{//核心代码,点击按钮实现FA的迁移//第一步获取设备idStringdeviceId=DeviceUtils.getDeviceId();if(deviceId!=null){//实现设备迁移continueAbility(deviceId);}});}@OverridepublicvoidonActive(){super.onActive();}@OverridepublicvoidonForeground(Intentintent){super.onForeground(intent);}@OverridepublicbooleanonStartContinuation(){returntrue;}@Override//保持数据publicbooleanonSaveData(IntentParamsintentParams){//获取文本框中的文本并保存到data中,键值对形式intentParams.setParam("data",textField.getText());返回真;}@Override//恢复数据publicbooleanonRestoreData(IntentParamsintentParams){//当其他设备恢复数据时,从数据中读取内容tfStr=intentParams.getParam("data").toString();returntrue;}@OverridepublicvoidonCompleteContinuation(inti){}}测试结果点击按钮进入MigrationAbility页面,在输入框中输入文本内容,然后点击按钮,可以看到内容已经迁移完成。在目标设备上添加新内容,然后单击迁移以更新源设备的内容。修改是双向控制是可能的。2.3.迁移正在编辑的内容,可以撤销迁移。仅支持单向控制。实现方法和上面基本一样,同样要实现IAbilityContinuation接口。一些细节上的不同:1.在页面中多了一个返回按钮2.Slice中跨设备的方法由continueAbility()改为continueAbilityReversibly(),用于撤回迁移的方法为reverseContinueAbility()MigrationBackAbilitySlice.java测试结果:在文本框中输入数据后,点击Migrate按钮调用目标设备上的应用程序。点击撤回按钮,也可以撤回目标设备的页面。此操作是单向的。迁移完成后,修改目标设备的内容,点击迁移即可修改源设备的内容。这样做会闪退3.总结因为涉及到设备之间的传递和安全,所以需要在config.json中声明权限。如果要使用第三方设备,除了在config.json中声明外,还需要在代码中明确声明需要跨设备获取设备ID。如果想获取多个分片中的设备ID,可以将这个步骤封装成一个工具类,进行简单的跨设备调用。您可以使用OperationBuilder()方法跨设备编辑设备中的内容。需要为目标页面的Ability和Slice实现IAbilityContinuation()接口,使用newElementName()使用continueAbility进行双向交互使用continueAbilityReversibly()和reverseContinueAbility()进行单向跨设备跳转和撤回内容.com