鸿蒙OS流转之跨端迁移

news2024/10/5 19:09:15

前言

流转在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学习资料:免费领取(安全链接,放心点击

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1797988.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

剪画小程序:图片去除文字,我用它只要10秒!

Hello&#xff0c;大家好呀&#xff01;我是不会画画的小画~ 图片上的文字该如何去除&#xff1f; 在工作或者学习中&#xff0c;我们常常需要处理一些图片文件&#xff0c;比如扫描的文件、 电子文档等。有时候&#xff0c;图片上可能会有文字&#xff0c;这时候需要将图片…

源码!源码!商城源码!如何选择

选择合适的商城源码是电商平台成功运营的关键因素之一。下面将从多个维度分析如何选择适合的商城源码&#xff1a; 安全性与稳定性 安全机制&#xff1a;安全的商城源码能保护用户数据和交易安全&#xff0c;避免信息泄露和被黑风险。 稳定运行&#xff1a;稳定的商城系统可以…

JAVA-LeetCode 热题-第24题:两两交换链表中的节点

思路&#xff1a; 定义三个指针&#xff0c;其中一个临时指针&#xff0c;进行交换两个节点的值&#xff0c;重新给临时指针赋值&#xff0c;移动链表 class Solution {public ListNode swapPairs(ListNode head) {ListNode pre new ListNode(0,head);ListNode temp pre;wh…

Python代码限定抽奖次数的方法

在许多应用场景中&#xff0c;抽奖活动需要限定参与次数以确保公平性和控制成本。本文将介绍如何使用Python代码实现抽奖次数的限定。我们将讨论基本的实现方法&#xff0c;并展示一个完整的代码示例。 基本思路 限定抽奖次数的基本思路是使用一个计数器来记录每个用户已经参…

linux进程间通讯指南-打通IPC大门,高效沟通无阻

在现代操作系统中&#xff0c;进程就像独立的个体&#xff0c;有时需要相互合作、数据共享&#xff0c;这就要求进程间能够高效通信。本文将为你揭开Linux进程间通信(IPC)的神秘面纱&#xff0c;探讨各种IPC工具的运作原理&#xff0c;同步机制的重要性&#xff0c;以及如何规避…

uniapp录音播放功能

ui效果如上。 播放就开始倒计时&#xff0c;并且改变播放icon&#xff0c;另外录音则停止上一次录音。 播放按钮&#xff08;三角形&#xff09;是播放功能&#xff0c;两竖是暂停播放功能。 const innerAudioContext wx.createInnerAudioContext();export default{data(){ret…

20240607给Toybrick的TB-RK3588开发板在Buildroot下适配瑞芯微7.86寸QXGATFT-LCD EDP屏幕1536x2048

20240607给Toybrick的TB-RK3588开发板在Buildroot下适配瑞芯微7.86寸QXGATFT-LCD EDP屏幕1536x2048 2024/6/7 13:59 1、背光部分&#xff1a;&backlight { pwms <&pwm2 0 25000 0>; status "okay"; }; &pwm2 { status "okay&…

计算机网络(网络原理及应用)之路由器的基本配置(详细~)

路由器的基本配置 实验目的 熟悉路由各接口的外观、接口的功能、接口的表示方法&#xff1b;掌握带外的管理方法&#xff1a;通过接口console配置&#xff1b;掌握带内的管理方法&#xff1a;通过方式telnet配置&#xff1b;掌握带内的管理方法&#xff1a;通过方式web配置&…

机器学习之数学基础(六)~时间复杂度和空间复杂度

目录 算法背景 background 1. 时间复杂度 Time Complexity 1.1 时间复杂度分类 1.1.1 O(1) 常数阶 1.1.2 O(n) 线性阶 1.1.3 O(n^2) 平方阶 1.1.4 O(logn) 对数阶 1.1.5 O(nlogn) 线性对数阶 1.1.6 O(2^n) 指数阶 1.1.7 O(n!) 阶乘阶 1.1.8 时间复杂度分类 1.2 时…

python的line[:-1]和line[-1]

line[:-1]其实就是去除了这行文本的最后一个字符(换行符)后剩下的部分。 line = "abcde" line[:-1] 结果为:abcd line = "abcde" line[::-1] 结果为:edcba 示例3 [m : ] 代表列表中的第m+1项到最后一项 [ : n] 代表列表中的第一项到第n项 [-1] 代…

Facebook:社交世界的引领者

导语 在当今数字化时代&#xff0c;Facebook已经成为了人们社交生活的重要一环。然而&#xff0c;除了成为社交媒体的象征外&#xff0c;它还在不断探索并领导着社交世界的新方向。 1. 社交平台的发展者 Facebook不仅仅是一个社交平台&#xff0c;更是社交方式的引领者。从其…

世界坐标系和WGS84坐标系相互转换(2024-06-07)

WGS84弧度坐标系转世界坐标 const handelCartographic ()>{const a new Cesium.Cartesian3.fromDegrees(104.1, 30.6, 200);console.log("世界坐标",a);const b new Cesium.Cartographic.fromDegrees(104.1, 30.6, 200);console.log("WGS84弧度坐标系&qu…

什么是ESG?

什么是ESG&#xff1f; ESG的实施和发展是企业应对全球和国内环境、社会和治理挑战的关键路径。《ESG入门一本通》详细阐述了ESG的概念、发展历程和评价体系&#xff0c;并结合中国的实际情况&#xff0c;强调了ESG的重要性和必要性。企业需重视ESG管理和信息披露&#xff0c;…

视觉SLAM十四讲:从理论到实践(Chapter9:后端1)

前言 学习笔记&#xff0c;仅供学习&#xff0c;不做商用&#xff0c;如有侵权&#xff0c;联系我删除即可 一、目标 1.理解后端的概念。 2.理解以EKF为代表的滤波器后端的工作原理。 3.理解非线性优化的后端&#xff0c;明白稀疏性是如何利用的。 4.使用g2o和Ceres实际操作…

C# 集成 C++ 的方法和实践 - P/Invoke(平台调用)- 1

环境&#xff1a; 1 P/Invoke&#xff08;平台调用&#xff09;&#xff1a; C#可以通过P/Invoke调用C编写的DLL中的函数。 1.1 适用范围&#xff1a; P/Invoke 是一种在 C# 程序中调用非托管代码&#xff08;如 C 动态链接库&#xff09;的方式。这种方法适用于函数调用相对…

一文了解AI绘画两大鼻祖 Midjourney 和 Stable Diffusion的区别,超详细讲解小白入门必看教程!

大家好&#xff0c;我是画画的小强 要说AI绘画软件哪家强&#xff1f;有人说Midjoureny (MJ), 有人说Stable Diffuion(SD)&#xff0c;那他们到底有什么区别&#xff1f;应该选择哪款软件学习&#xff1f;今天带大家全面了解一下&#xff01;文末可白嫖AI资料哦&#xff5e; 一…

PVE安装CENTOS9提示“Fatal glibc error: CPU does not support x86-64-v2”

问题描述&#xff1a;PVE安装CENTOS9提示“Fatal glibc error: CPU does not support x86-64-v2” RHEL 9要求x86_64的CPU支持x86-64-v2&#xff0c;x86-64-v2需要处理器支持 CMPXCHG16B、LAHF-SAHF、POPCNT、SSE3、SSE4.1、SSE4.2、SSSE3 等现代指令集 解决方法&#xff1a;…

API接口测试工具:jmeter的安装、汉化、Jmeter桌面快捷图标和基本使用

文章目录 测试工具&#xff1a;JmeterJmeter安装和配置Jmeter汉化设置中文语言&#xff1a;永久方式设置中文语言&#xff1a;临时方式 设置Jmeter桌面快捷图标jmeter基本用法Jmeter无法保存测试问题解决 测试工具&#xff1a;Jmeter Jmeter依赖于JDK&#xff0c;所以必须确保…

SwiftUI获取用户的位置信息(CLLocationManager,CLLocationManagerDelegate)

本篇文章将会介绍一下在SwiftUI中如何通过CorLocation框架获取用户的位置信息&#xff0c;因为获取位置信息属于用户的隐私信息&#xff0c;所以需要在Info.plist文件里面加上访问位置权限的说明。 关于位置信息&#xff0c;可以请求两种级别的许可&#xff1a;always和when i…

项目经理进入职场都会经历的三个阶段

对于项目经理而言&#xff0c;进入职场是一个不断学习和成长的过程。在这个过程中&#xff0c;项目经理通常会经历三个主要阶段&#xff0c;每个阶段都有其独特的特点和挑战。 一、基础建设与学习阶段 对于新入行的项目经理来说&#xff0c;最初的阶段主要是基础技能的积累和…