HarmonyOS 应用开发之同应用跨设备数据同步

概述

场景介绍

跨设备数据同步功能(即分布式功能),指将数据同步到一个组网环境中的其他设备。常用于用户应用程序数据内容在可信认证的不同设备间,进行自由同步、修改和查询。

例如:当设备1上的应用A在分布式数据库中增、删、改数据后,设备2上的应用A也可以获取到该数据库变化。可在分布式图库、备忘录、联系人、文件管理器等场景中使用。

根据跨设备同步数据生命周期的不同,可以分为:

  • 临时数据生命周期较短,通常保存到内存中。比如游戏应用产生的过程数据,建议使用分布式数据对象。

  • 持久数据生命周期较长,需要保存到存储的数据库中,根据数据关系和特点,可以选择关系型数据库或者键值型数据库。比如图库应用的各种相册、封面、图片等属性信息,建议使用关系型数据库;图库应用的具体图片缩略图,建议使用键值型数据库。

基本概念

在分布式场景中,会涉及多个设备,组网内设备之间看到的数据是否一致称为分布式数据库的一致性。

分布式数据库一致性可以分为强一致性、弱一致性和最终一致性。

  • 强一致性:是指某一设备成功增、删、改数据后,组网内设备对该数据的读取操作都将得到更新后的值。对于已改变写的数据的读取,最终都能取得已更新的数据,但不完全保证能立即取得已更新的数据。

  • 弱一致性:是指某一设备成功增、删、改数据后,组网内设备可能读取到本次更新后的数据,也可能读取不到,不能保证在多长时间后每个设备的数据一定是一致的。

  • 最终一致性:是指某一设备成功增、删、改数据后,组网内设备可能读取不到本次更新后的数据,但在某个时间窗口之后组网内设备的数据能够达到一致状态。

强一致性对分布式数据的管理要求非常高,在服务器的分布式场景可能会遇到。因为移动终端设备的不常在线、以及无中心的特性,所以同应用跨设备数据同步不支持强一致性,只支持最终一致性。

跨设备同步访问控制机制

数据跨设备同步时,数据管理基于设备等级和数据安全标签进行访问控制。

键值型数据库跨设备数据同步

场景介绍

键值型数据库适合不涉及过多数据关系和业务关系的业务数据存储,比SQL数据库存储拥有更好的读写性能,同时因其在分布式场景中降低了解决数据库版本兼容问题的复杂度,和数据同步过程中冲突解决的复杂度而被广泛使用。

基本概念

在使用键值型数据库跨设备数据同步前,请先了解以下概念。

单版本数据库

单版本是指数据在本地是以单个条目为单位的方式保存,当数据在本地被用户修改时,不管它是否已经被同步出去,均直接在这个条目上进行修改。多个设备全局只保留一份数据,多个设备的相同记录(主码相同)会按时间最新保留一条记录,数据不分设备,设备之间修改相同的key会覆盖。同步也以此为基础,按照它在本地被写入或更改的顺序将当前最新一次修改逐条同步至远端设备,常用于联系人、天气等应用存储场景。

多设备协同数据库

多设备协同分布式数据库建立在单版本数据库之上,对应用程序存入的键值型数据中的Key前面拼接了本设备的DeviceID标识符,这样能保证每个设备产生的数据严格隔离。数据以设备的维度管理,不存在冲突;支持按照设备的维度查询数据。

底层按照设备的维度管理这些数据,多设备协同数据库支持以设备的维度查询分布式数据,但是不支持修改远端设备同步过来的数据。需要分开查询各设备数据的可以使用设备协同版本数据库。常用于图库缩略图存储场景。

同步方式

数据管理服务提供了两种同步方式:手动同步和自动同步。键值型数据库可选择其中一种方式实现同应用跨设备数据同步。

  • 手动同步:由应用程序调用sync接口来触发,需要指定同步的设备列表和同步模式。同步模式分为PULL_ONLY(将远端数据拉取到本端)、PUSH_ONLY(将本端数据推送到远端)和PUSH_PULL(将本端数据推送到远端同时也将远端数据拉取到本端)。 带有Query参数的同步接口 ,支持按条件过滤的方法进行同步,将符合条件的数据同步到远端。

  • 自动同步:由分布式数据库自动将本端数据推送到远端,同时也将远端数据拉取到本端来完成数据同步,同步时机包括设备上线、应用程序更新数据等,应用不需要主动调用sync接口。

运作机制

底层通信组件完成设备发现和认证,会通知上层应用程序设备上线。收到设备上线的消息后数据管理服务可以在两个设备之间建立加密的数据传输通道,利用该通道在两个设备之间进行数据同步。

数据跨设备同步机制

如图所示,通过put、delete接口触发自动同步,将分布式数据通过通信适配层发送给对端设备,实现分布式数据的自动同步;

手动同步则是手动调用sync接口触发同步,将分布式数据通过通信适配层发送给对端设备。

数据变化通知机制

增、删、改数据库时,会给订阅者发送数据变化的通知。主要分为本地数据变化通知和分布式数据变化通知。

  • 本地数据变化通知:本地设备的应用内订阅数据变化通知,数据库增删改数据时,会收到通知。

  • 分布式数据变化通知:同一应用订阅组网内其他设备数据变化的通知,其他设备增删改数据时,本设备会收到通知。

约束限制

  • 设备协同数据库,针对每条记录,Key的长度≤896 Byte,Value的长度<4 MB。

  • 单版本数据库,针对每条记录,Key的长度≤1 KB,Value的长度<4 MB。

  • 键值型数据库不支持应用程序自定义冲突解决策略。

  • 每个应用程序最多支持同时打开16个键值型分布式数据库。

  • 单个数据库最多支持注册8个订阅数据变化的回调。

接口说明

以下是单版本键值型分布式数据库跨设备数据同步功能的相关接口,大部分为异步接口。异步接口均有callback和Promise两种返回形式,下表均以callback形式为例。

接口名称描述
createKVManager(config: KVManagerConfig): KVManager创建一个KVManager对象实例,用于管理数据库对象。
getKVStore<T>(storeId: string, options: Options, callback: AsyncCallback<T>): void指定Options和storeId,创建并得到指定类型的KVStore数据库。
put(key: string, value: Uint8Array|string|number|boolean, callback: AsyncCallback<void>): void插入和更新数据。
on(event: ‘dataChange’, type: SubscribeType, listener: Callback<ChangeNotification>): void订阅数据库中数据的变化。
get(key: string, callback: AsyncCallback<boolean | string | number | Uint8Array>): void查询指定Key键的值。
sync(deviceIds: string[], mode: SyncMode, delayMs?: number): void在手动模式下,触发数据库同步。

开发步骤

此处以单版本键值型数据库跨设备数据同步的开发为例。以下是具体的开发流程和开发步骤。

说明:
数据只允许向数据安全标签不高于对端设备安全等级的设备同步数据,具体规则可见 跨设备同步访问控制机制 。

  1. 导入模块。
   import distributedKVStore from '@ohos.data.distributedKVStore';
  1. 请求权限。

    1. 需要申请ohos.permission.DISTRIBUTED_DATASYNC权限。
    2. 同时需要在应用首次启动时弹窗向用户申请授权。
  2. 根据配置构造分布式数据库管理类实例。

    1. 根据应用上下文创建kvManagerConfig对象。
    2. 创建分布式数据库管理器实例。
   // Stage模型获取contextimport window from '@ohos.window';import UIAbility from '@ohos.app.ability.UIAbility';import { BusinessError } from '@ohos.base';let kvManager: distributedKVStore.KVManager | undefined = undefined;class EntryAbility extends UIAbility {onWindowStageCreate(windowStage:window.WindowStage) {let context = this.context;}}// FA模型获取contextimport featureAbility from '@ohos.ability.featureAbility';import { BusinessError } from '@ohos.base';let context = featureAbility.getContext();// 获取context之后,构造分布式数据库管理类实例try {const kvManagerConfig: distributedKVStore.KVManagerConfig = {bundleName: 'com.example.datamanagertest',context: context}kvManager = distributedKVStore.createKVManager(kvManagerConfig);console.info('Succeeded in creating KVManager.');// 继续创建获取数据库} catch (e) {let error = e as BusinessError;console.error(`Failed to create KVManager. Code:${error.code},message:${error.message}`);}if (kvManager !== undefined) {kvManager = kvManager as distributedKVStore.KVManager;// 进行后续创建数据库等相关操作// ...}
  1. 获取并得到指定类型的键值型数据库。

    1. 声明需要创建的分布式数据库ID描述(例如示例代码中的’storeId’)。
    2. 创建分布式数据库,建议关闭自动同步功能(autoSync:false),方便后续对同步功能进行验证,需要同步时主动调用sync接口。
   let kvStore: distributedKVStore.SingleKVStore | undefined = undefined;try {const options: distributedKVStore.Options = {createIfMissing: true,encrypt: false,backup: false,autoSync: false,// kvStoreType不填时,默认创建多设备协同数据库kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,// 多设备协同数据库:kvStoreType: distributedKVStore.KVStoreType.DEVICE_COLLABORATION,securityLevel: distributedKVStore.SecurityLevel.S1};kvManager.getKVStore<distributedKVStore.SingleKVStore>('storeId', options, (err, store: distributedKVStore.SingleKVStore) => {if (err) {console.error(`Failed to get KVStore: Code:${err.code},message:${err.message}`);return;}console.info('Succeeded in getting KVStore.');kvStore = store;// 请确保获取到键值数据库实例后,再进行相关数据操作});} catch (e) {let error = e as BusinessError;console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);}if (kvStore !== undefined) {kvStore = kvStore as distributedKVStore.SingleKVStore;// 进行后续相关数据操作,包括数据的增、删、改、查、订阅数据变化等操作// ...}
  1. 订阅分布式数据变化,如需关闭订阅分布式数据变化,调用 off(‘dataChange’) 关闭。
   try {kvStore.on('dataChange', distributedKVStore.SubscribeType.SUBSCRIBE_TYPE_ALL, (data) => {console.info(`dataChange callback call data: ${data}`);});} catch (e) {let error = e as BusinessError;console.error(`An unexpected error occurred. code:${error.code},message:${error.message}`);}
  1. 将数据写入分布式数据库。

    1. 构造需要写入分布式数据库的Key(键)和Value(值)。
    2. 将键值数据写入分布式数据库。
   const KEY_TEST_STRING_ELEMENT = 'key_test_string';const VALUE_TEST_STRING_ELEMENT = 'value_test_string';try {kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (err) => {if (err !== undefined) {console.error(`Failed to put data. Code:${err.code},message:${err.message}`);return;}console.info('Succeeded in putting data.');});} catch (e) {let error = e as BusinessError;console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);}
  1. 查询分布式数据库数据。

    1. 构造需要从单版本分布式数据库中查询的Key(键)。
    2. 从单版本分布式数据库中获取数据。
   const KEY_TEST_STRING_ELEMENT = 'key_test_string';const VALUE_TEST_STRING_ELEMENT = 'value_test_string';try {kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (err) => {if (err !== undefined) {console.error(`Failed to put data. Code:${err.code},message:${err.message}`);return;}console.info('Succeeded in putting data.');kvStore = kvStore as distributedKVStore.SingleKVStore;kvStore.get(KEY_TEST_STRING_ELEMENT, (err, data) => {if (err != undefined) {console.error(`Failed to get data. Code:${err.code},message:${err.message}`);return;}console.info(`Succeeded in getting data. Data:${data}`);});});} catch (e) {let error = e as BusinessError;console.error(`Failed to get data. Code:${error.code},message:${error.message}`);}
  1. 同步数据到其他设备。

选择同一组网环境下的设备以及同步模式(需用户在应用首次启动的弹窗中确认选择同步模式),进行数据同步。

说明:
在手动同步的方式下,其中的deviceIds通过调用 devManager.getAvailableDeviceListSync 方法得到。

   import deviceManager from '@ohos.distributedDeviceManager';let devManager: deviceManager.DeviceManager;try {// create deviceManagerdevManager = deviceManager.createDeviceManager(context.applicationInfo.name);// deviceIds由deviceManager调用getAvailableDeviceListSync方法得到let deviceIds: string[] = [];if (devManager != null) {let devices = devManager.getAvailableDeviceListSync();for (let i = 0; i < devices.length; i++) {deviceIds[i] = devices[i].networkId as string;}}try {// 1000表示最大延迟时间为1000mskvStore.sync(deviceIds, distributedKVStore.SyncMode.PUSH_ONLY, 1000);} catch (e) {let error = e as BusinessError;console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);}} catch (err) {let error = err as BusinessError;console.error("createDeviceManager errCode:" + error.code + ",errMessage:" + error.message);}

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

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

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

相关文章

打印日志(JAVA)

1、通过导入包的形式 package com.example.demo;import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; RequestMapping("/log&q…

信息系统项目管理师——第17章项目干系人管理

本章节内容属于10大管理知识领域&#xff0c;选择、案例、论文都会考。 选择题&#xff0c;稳定考1-2分左右&#xff0c;新教材基本考课本原话&#xff0c;这个分不能丢。 案例题&#xff0c;本期考的概率一般。 论文题&#xff0c;202205期考过。 1管理基础 管理的重要性 为…

北京可安可智能科技有限公司:创新巡检,智慧守护

在智能化的浪潮中&#xff0c;北京可安可智能科技有限公司以其创新的机器人巡检产品和方案&#xff0c;正引领安防巡检领域迈向一个新的里程碑。作为人工智能科技创新的先锋&#xff0c;我们专注于利用科技力量提升行业标准&#xff0c;降低用人成本&#xff0c;为安保场景提供…

番外篇 | 引入RepVGG重参数化模块 | 即插即用,实现有效涨点

前言:Hello大家好,我是小哥谈。重参数化模块(RepVGG)是一种深度学习模型,它借鉴了卷积神经网络(CNN)中的卷积操作,并对其进行了一些改进,以提高模型的性能和计算效率。RepVGG的核心思想是通过重参数化技术,对卷积操作中的权重进行重新配置,以适应不同的数据集和任务…

file_get_contents(‘php://input‘); 这个postman要如何传参

在 Postman 中传递参数给 file_get_contents(php://input); 是通过请求的 Body 部分来实现的。使用 Postman 进行 API 接口测试时&#xff0c;可以按照以下步骤来传递参数&#xff1a; 打开 Postman 并创建一个新的请求。在请求的 URL 地址栏输入你的 API 地址。选择请求方法为…

基于java的java二手手机回收平台系统

开发语言&#xff1a;Java 框架&#xff1a;ssm 技术&#xff1a;JSP JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclip…

【力扣】11. 盛最多水的容器

11. 盛最多水的容器 题目描述 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&…

day10 java封装性

封装性 为什么有封装性&#xff1f; 为了保护数据不被随意修改&#xff0c;隐藏类的实现细节。增强了代码的安全性和可维护性。 该隐藏隐藏 该暴露暴露 封装性的实现&#xff1f; 让调用者只能通过方法操作属性。可以在方法中加入一些限制条件或数据检查的操作。 封装性的直…

Java获取IP地址以及MAC地址(附Demo)

目录 前言1. IP及MAC2. 特定适配器 前言 需要获取客户端的IP地址以及MAC地址 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;public class test {public static void main(String[] args) {try {// 执行命令Process process…

AI 论道|极狐GitLab 客户私享会上海站成功举办

3 月 22 日下午&#xff0c;极狐GitLab 在上海办公室举办了客户私享会&#xff0c;邀请了来自多个行业的多家客户&#xff0c;围绕 AI 提升研发效率的道法术器进行了充分交流。整个交流时长达两个多小时。 极狐GitLab 战略业务与区域发展副总裁何庆出席了此次活动并致开场辞。他…

成员变量、局部变量

变量分类 定义位置不同 成员变量定义在类中&#xff0c;成员方法之外 局部变量定义在局部范围内&#xff0c;如方法参数&#xff0c;方法内部&#xff0c;循环结构中等 作用范围不同&#xff08;空间&#xff09; 成员变量在整个类内有效&#xff0c;与声明位置无关 局部变…

软考高级架构师:系统性能设计-阿姆达尔定律概念和例题

一、AI 讲解 系统性能设计中的一个重要概念是阿姆达尔定律&#xff08;Amdahl’s Law&#xff09;。阿姆达尔定律是由吉恩阿姆达尔&#xff08;Gene Amdahl&#xff09;在1967年提出的&#xff0c;用于评估系统性能提升的理论上限&#xff0c;特别是在考虑并行计算时。该定律表…

线性数据结构

1.数组 数组使用一块连续的内存来存储元素&#xff0c;并且元素的类型都是相同的。可以通过索引来访问。 2.链表 链表由一系列节点组成&#xff0c;每个节点包含两部分&#xff1a;数据部分和指针部分。数据部分用于存储元素的值&#xff0c;指针部分则指向下一个节点。没有使…

真·面试题总结——JVM虚拟机

JVM虚拟机 JVM虚拟机规范与实现 JVM虚拟机规范 JVM虚拟机实现 JVM的常见实现 JVM虚拟机物理架构 JVM虚拟机的运转流程 JVM类加载过程 JVM类加载器及类加载器类型 JVM类加载器双亲委派机制 JVM运行时数据区的内存模型 JVM运行时数据区的内存模型&#xff1a;程序计数器…

【JavaScript】函数 ③ ( 形参 与 实参 匹配问题 | 实参个数 = 形参个数 | 实参个数 > 形参个数 | 实参个数 < 形参个数 )

文章目录 一、JavaScript 函数 形参 与 实参 匹配问题1、函数形参与实参不匹配问题2、形参与实参个数匹配3、实参个数 > 形参个数4、实参个数 < 形参个数5、完整代码示例 一、JavaScript 函数 形参 与 实参 匹配问题 1、函数形参与实参不匹配问题 在 其它语言 中 , 如 Ja…

【面试题】spring 事务在哪些情况下会失效?

以下几种情况&#xff0c;会造成事务失效 直接new出来的对象添加事务不起作用&#xff0c;因为只有spring定义的bean才接受事务。 由于mysql的引擎用Myisam不支持事务&#xff0c;所以如果使用mysql的myisam引擎的话&#xff0c;事务不起作用。 如果Transaction注解到非publi…

ABAP 时间函数-F4

屏幕时间函数 操作 1.屏幕字段属性设置&#xff0c;如图: 2.代码: DATA L_TIME TYPE SY-UZEIT. CALL FUNCTION F4_CLOCK EXPORTING START_TIME SY-UZEIT DISPLAY IMPORTING SELECTED_TIME L_TIME.

h5 笔记1

Internet是InternationalNetwork的缩写&#xff0c;又称“因特网”。它是将全世界数以千计的上网设备通过TCP/IP通信协议连接在一起。Internet上的服务众多&#xff0c;主要的服务有WWW(万维网)、E-Mail(电子邮件)、FTP(FileTransferProtocol&#xff0c;文件传输协议)、Telnet…

PEFT-LISA

LISA是LoRA的简化版&#xff0c;但其抓住了LoRA微调的核心&#xff0c;即LoRA侧重更新LLM的底层embedding和顶层head。 根据上述现象&#xff0c;LISA提出两点改进&#xff1a; 始终更新LLM的底层embedding和顶层head随机更新中间层的hidden state 实验结果 显存占用 毕竟模型…

【C++】二分查找算法(模板)

重点 只需要记住两点&#xff1a; 1.left right 时&#xff0c;一定就是最终结果&#xff08;包括找不到目标值&#xff09;&#xff0c;无需再次判断&#xff0c;如果判断就会死循环 2.求中点如果是求左端点 mid left (right - left)/2 如果是求右端点 mid left (right -…