鸿蒙OS流转之跨端迁移

164 篇文章 0 订阅
154 篇文章 0 订阅

前言

流转在HarmonyOS中泛指多设备分布式操作,也是HarmonyOS的亮点之一。流转按体验可以分为跨端迁移和多端协同,这里主要跟大家讲一下如何进行跨端迁移,以及我在项目开发过程中,所遇到的问题与解决方法。

开发步骤

在开发过程中,我们可以根据业务需求分为以下两种场景:

  1. 同个FA之间的迁移(Ability1—Ability1);
  2. 不同FA之间的迁移(Ability1—Ability2);

下面给大家介绍一下以上两种场景的具体的开发步骤。

同个FA之间的迁移

同个FA之间的迁移是指不同设备端安装了同个FA,下面只给大家讲一下需要注意的事项及我所遇到的问题避免大家踩坑。

1.我们在创建完一个FA之后,因为我们大部门的业务逻辑都是在AbilitySlice,所以我们在Ability及AbilitySlice都要去实现IAbilityContinuation 接口,并且将Ability中实现的onStartContinuation()、onSaveData(IntentParams intentParams)、onRestoreData(IntentParams intentParams)的返回值,都设为true。

public class MainAbility extends Ability implements IAbilityContinuation {
	
    @Override
    public boolean onStartContinuation() {
        return true;
    }

    @Override
    public boolean onSaveData(IntentParams intentParams) {
        return true;
    }

    @Override
    public boolean onRestoreData(IntentParams intentParams) {
        return true;
    }
	//省略部分代码
 	...
}

2.在对应的FA模块的config.json中,配置对应的权限,且在代码中也需要动态申请。

"reqPermissions": [
 {
  "name": "ohos.permission.DISTRIBUTED_DATASYNC" },
 {
  "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE" },
 {
  "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"},
 {
  "name": "ohos.permission.GET_BUNDLE_INFO"}
]
if (canRequestPermission(SystemPermission.DISTRIBUTED_DATASYNC)) {
    // 是否可以申请弹框授权(首次申请或者用户未选择禁止且不再提示)
    requestPermissionsFromUser(
            new String[]{SystemPermission.DISTRIBUTED_DATASYNC}, PERMISSIONS_REQUEST_DISTRIBUTED);
}

3.定义相关参数、设置流转任务管理服务回调函数、注册流转任务管理服务、管理流转的目标设备,同时需要在流转结束时解注册流转任务管理服务。

	// 流转应用包名
    private String BUNDLE_NAME = "XXX.XXX.XXX"; 
    // 注册流转任务管理服务后返回的Ability token
    private int abilityToken; 
    // 用户在设备列表中选择设备后返回的设备ID
    private String selectDeviceId;
    // 获取流转任务管理服务管理类
    private IContinuationRegisterManager continuationRegisterManager;
	// 设置流转任务管理服务设备状态变更的回调
	private IContinuationDeviceCallback continuationDeviceCallback = new IContinuationDeviceCallback() {
    @Override
    public void onDeviceConnectDone(String deviceId, String deviceType) {
        selectDeviceId = deviceId;
        continuationRegisterManager.updateConnectStatus(abilityToken, selectDeviceId, DeviceConnectState.CONNECTING.getState(), null);
		...
    }

    @Override
    public void onDeviceDisconnectDone(String s) {
        getUITaskDispatcher().asyncDispatch(() -> {
            continuationRegisterManager.updateConnectStatus(abilityToken, selectDeviceId, DeviceConnectState.DIS_CONNECTING.getState(), null);
        });
        unRegisterContinuation();
    }
};
  // 设置注册流转任务管理服务回调
    private RequestCallback requestCallback = new RequestCallback() {
        @Override
        public void onResult(int result) {
            abilityToken = result;
        }
    };
    ...

    @Override
    public void onStart(Intent intent) {
        ...
        continuationRegisterManager = getContinuationRegisterManager();
    }

    @Override
    public void onStop() {
        super.onStop();
        // 解注册流转任务管理服务
        continuationRegisterManager.unregister(abilityToken, null);
        // 断开流转任务管理服务连接
        continuationRegisterManager.disconnect();
    }

在Api5的时候IContinuationDeviceCallback的回调接口跟官方文档有些出入,当你选择设备后会在onDeviceConnectDone返回你所选择的设备ID及设备类型。

4.注册流转服务之后我们便可以调起系统流转选择设备弹窗,可以通过ExtraParams对设备进行过滤,如不需要过滤,可不传。

ExtraParams params = new ExtraParams();
String[] devTypes = new String[]{ExtraParams.DEVICETYPE_SMART_PHONE, ExtraParams.DEVICETYPE_SMART_WATCH, ExtraParams.DEVICETYPE_SMART_PAD};
params.setDevType(devTypes);
registerContinuation();
// 显示选择设备列表
continuationRegisterManager.showDeviceList(abilityToken, params, new RequestCallback() {
    @Override
    public void onResult(int result) {
    }
});

5.选择完设备之后会通过上述的IContinuationDeviceCallback的onDeviceConnectDone方法进行回调,之后通过continueAbility方法传入目标设备的DeviceID,将运行的FA迁移到目标设备,实现业务在设备间无缝迁移。

// 设置流转任务管理服务设备状态变更的回调
private IContinuationDeviceCallback continuationDeviceCallback = new IContinuationDeviceCallback() {
    @Override
    public void onDeviceConnectDone(String deviceId, String deviceType) {
        selectDeviceId = deviceId;
        getUITaskDispatcher().asyncDispatch(() -> {
            continuationRegisterManager.updateConnectStatus(abilityToken, selectDeviceId, DeviceConnectState.CONNECTING.getState(), null);
        });
        if (selectDeviceId != null) {
            continueAbility(selectDeviceId);
        }
        ...
    }

    @Override
    public void onDeviceDisconnectDone(String s) {
      	...
        unRegisterContinuation();
    }

};

6.在FA迁移中我觉得最主要的部分就是状态和数据的传递,要让用户体验到”无缝“的用户体验,需要通过实现IAbilityContinuation接口来实现数据的传递,主要代码如下:

@Override
public boolean onSaveData(IntentParams saveData) {
      //根据业务需求,在这里去设置需要传递的数据
      saveData.setParam("continueParam", continueParam);
      return true;
 }
@Override
public boolean onRestoreData(IntentParams restoreData) {
      // 远端FA迁移传来的状态数据,开发者可以按照自身业务对这些数据进行处理
      Object data = restoreData.getParam("continueParam");
      getUITaskDispatcher().asyncDispatch(() -> {
          
        });
      return true;
 }

需要注意的是,在onRestoreData处理数据更新UI的时候,需要在UI线程中去更新,否则会报错。

不同FA之间的迁移

在实际开发中可能会因为设备端的部分需求、UI的不同,例如车机、手机、手表,从而开发了不同的FA。不同FA之间的迁移几乎与同个FA之间迁移配置一致,只是我们的AbilitySlice不需要再实现IAbilityContinuation接口来实现数据的同步,而是通过Intent,具体实现如下。

1.首先我们先在选择设备成功后的回调IContinuationDeviceCallback初始化分布式环境。

// 设置流转任务管理服务设备状态变更的回调
private IContinuationDeviceCallback continuationDeviceCallback = new IContinuationDeviceCallback() {
    @Override
    public void onDeviceConnectDone(String deviceId, String deviceType) {
        selectDeviceId = deviceId;
        //省略部分代码
      	...
        try {
            // 初始化分布式环境
            DeviceManager.initDistributedEnvironment(selectDeviceId, new IInitCallback() {
                @Override
                public void onInitSuccess(String success) {

                }

                @Override
                public void onInitFailure(String failure, int result) {
                }
            });
        } catch (RemoteException e) {
            e.printStackTrace();
        }
       ...
    }
  ....
};

2.之前我们是通过continueAbility()方法进行跳转,而现在我们需要通过Intent方法进行跳转。

Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
        .withDeviceId(deviceId)
        .withBundleName(bundleName)
        .withAbilityName(abilityName)
        .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
        .build();
intent.setOperation(operation);
IntentParams intentParams = new IntentParams();
//通过IntentParams传递参数
...
startAbility(intent);

在接收方,我们可以通过onStart(Intent intent)方法接受传递过来的参数,再根据自己的业务逻辑实现数据同步。

自定义设备选择弹窗

在实际项目开发中我们也可以自定义流转弹窗样式,但并不推荐这种方式,经测试发现只有在两个设备通过蓝牙连接的时候才能获取到设备列表,只有在特定的场景,例如手机与车机、手机与手表在实际使用过程中我们基本上是会保持蓝牙连接的,通过这种方式实现流转会更稳定。但如果不能保持蓝牙实时连接的场景则不推荐。

1.官方API提供了DeviceManager.getDeviceList()来获取远端设备,具体代码如下。

public static List<DeviceInfo> getDeviceList() {
    // 调用DeviceManager的getDeviceList接口,通过FLAG_GET_ONLINE_DEVICE标记获得在线设备列表
    List<DeviceInfo> onlineDevices = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
    // 判断组网设备是否为空
    if (onlineDevices == null) {
        LogUtil.e(TAG, "online devices is null");
        return new ArrayList<>();
    }
    return onlineDevices;
}

2.获取到设备列表后,我们就可以自行实现页面了,在上述的showDeviceList()弹出设备列表的位置替换成自己的弹窗即可。

效果展示

#星光计划1.0# HarmonyOS 流转之跨端迁移-鸿蒙开发者社区

最后

如果你想成为一名鸿蒙开发者,以下这些资料将是十分优质且有价值,让你的鸿蒙开发之路事半功倍!相对于网上那些碎片化的知识内容,这份学习资料的知识点更加系统化,更容易理解和记忆。

内容包含了:【OpenHarmony多媒体技术、Stage模型、ArkUI多端部署、分布式应用开发、音频、视频、WebGL、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战】等技术知识点。

鸿蒙Next全套VIP学习资料←点击领取!(安全链接,放心点击

1.鸿蒙核心技术学习路线

2.大厂面试必问面试题

3.鸿蒙南向开发技术

 4.鸿蒙APP开发必备

 5.HarmonyOS Next 最新全套视频教程

 6.鸿蒙生态应用开发白皮书V2.0PDF

这份全套完整版的学习资料已经全部打包好,朋友们如果需要可以点击鸿蒙Next全套VIP学习资料:免费领取(安全链接,放心点击

  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值