HarmonyOS基础技术赋能之分布式数据服务功能

开发 前端 分布式 OpenHarmony
分布式数据服务(Distributed Data Service,DDS) 为应用程序提供不同设备间数据库数据分布式的能力。通过调用分布式数据接口,应用程序将数据保存到分布式数据库中。

[[419727]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

引言

分布式数据服务(Distributed Data Service,DDS) 为应用程序提供不同设备间数据库数据分布式的能力。通过调用分布式数据接口,应用程序将数据保存到分布式数据库中。通过结合帐号、应用和数据库三元组,分布式数据服务对属于不同应用的数据进行隔离,保证不同应用之间的数据不能通过分布式数据服务互相访问。在通过可信认证的设备间,分布式数据服务支持应用数据相互同步,为用户提供在多种终端设备上最终一致的数据访问体验。

功能介绍

此次通过HarmonyOS的分布式数据服务能力,一方面可以实现自身应用界面的数据实时更新;另一方面也可以实现不同设备之间的数据实时更新。前提是在不同设备之间,要实现分布式数据服务的同步能力,需要同一个华为账号登录、并一个应用包名、同一个网络之间进行,也可以两个设备同时开启蓝牙。

开发指南

1. 在config.json中添加permisssion权限。

  1. // 添加在abilities同一目录层级 
  2. "reqPermissions": [ 
  3.     { 
  4.         "name""ohos.permission.DISTRIBUTED_DATASYNC" 
  5.     } 

2. 在MainAbility中添加权限

  1. @Override 
  2. public void onStart(Intent intent) { 
  3.   super.onStart(intent); 
  4.   super.setMainRoute(MainAbilitySlice.class.getName()); 
  5.   //实现Ability的代码中显式声明需要使用多设备协同访问的权限 
  6.   requestPermissionsFromUser(new String[]{ 
  7.       "ohos.permission.DISTRIBUTED_DATASYNC"}, 0); 
  8.  

3. 根据配置构造分布式数据库管理类实例KvManager以及创建分布式数据库对象SingleKvStore。

  1. //实现数据库的初始化 
  2. // 初入的参数context: Context context = getApplicationContext()获得;storeId为分布式数据库id,String类型,可自行定义,例如“testApp”。 
  3. public static SingleKvStore initOrGetDB(Context context, String storeId) { 
  4.   KvManagerConfig kvManagerConfig = new KvManagerConfig(context); 
  5.   kvManager = KvManagerFactory.getInstance().createKvManager(kvManagerConfig); 
  6.   Options options = new Options(); 
  7.   options.setCreateIfMissing(true
  8.     .setEncrypt(false
  9.     .setKvStoreType(KvStoreType.SINGLE_VERSION) //数据库类型:单版本分布式数据库 
  10.     .setAutoSync(true);//设置数据为自动同步 
  11.   singleKvStore = kvManager.getKvStore(options, storeId); 
  12.   return singleKvStore; 

4. 将数据写入单版本分布式数据库。

  1. //以key-value形式存储到分布式数据库 
  2. try { 
  3.   long id = System.currentTimeMillis(); 
  4.   singleKvStore.putString("key"
  5.       "{\"id\":" + id + 
  6.           ",\"temp\":" + temperature + 
  7.           ",\"humidity\":" + humidity + 
  8.           ",\"NH4\":" + 0.0 + 
  9.           ",\"H2S\":" + 0.0 + 
  10.           ",\"other\":" + gas + "}"); 
  11. } catch (KvStoreException e) { 
  12.   e.printStackTrace(); 

5.订阅分布式数据变化。客户端需要实现KvStoreObserver接口,监听数据变化。

  1. try { 
  2. //订阅类型SubscribeType.SUBSCRIBE_TYPE_ALL意思可以同步到本机和其他外围设备 
  3.   innerKvStoreObserver = new InnerKvStoreObserver(); 
  4.   singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL, innerKvStoreObserver); 
  5. } catch (KvStoreException e) { 
  6.   e.printStackTrace(); 
  7.  
  8. public class InnerKvStoreObserver implements KvStoreObserver { 
  9.  
  10.   @Override 
  11.   public void onChange(ChangeNotification changeNotification) { 
  12.     //刷新页面上的数据,同样有一个坑,onChange方法实质上,在一个子线程里执行 
  13.     MainAbilitySlice.taskDispatcher.asyncDispatch(() -> { 
  14.       //在这里执行页面ui组件的显示刷新 
  15.       flushUIData(); 
  16.     }); 
  17.   } 

6.获取分布式数据库数据

  1. private void flushUIData() { 
  2.   //查询分布式数据的数据,获取数据可以通过get(String key)/ getEntries(String key)方法获取数据 
  3.   List<Entry> entries = singleKvStore.getEntries(“key”); 
  4.   if (entries.size() > 0) { 
  5.     ZSONObject zsonObject = ZSONObject.stringToZSON(entries.get(0).getValue().getString()); 
  6.     int temp = zsonObject.getIntValue("temp"); 
  7.     int humidity = zsonObject.getIntValue("humidity"); 
  8.     int other = zsonObject.getIntValue("other"); 
  9.     tvTemp.setText(temp+"℃"); 
  10.     tvHumi.setText(humidity+"% RH"); 
  11.     tvGas.setText(other+"% LEL"); 
  12.   } 

7. 解除订阅。一般在页面销毁时调用,也就是MainAbilitySlice的onStop()中调用

  1. if (singleKvStore != null) { 
  2.   singleKvStore.unSubscribe(innerKvStoreObserver); 

8. 同步数据到其他设备。获取已连接的设备列表,选择同步方式进行数据同步

  1. List<DeviceInfo> deviceInfoList = kvManager.getConnectedDevicesInfo(DeviceFilterStrategy.NO_FILTER); 
  2. List<String> deviceIdList = new ArrayList<>(); 
  3. for (DeviceInfo deviceInfo : deviceInfoList) { 
  4.     deviceIdList.add(deviceInfo.getId()); 
  5. singleKvStore.sync(deviceIdList, SyncMode.PUSH_ONLY); 

项目中采用在后台service中开启定时任务,实时保存数据到分布式数据库,然后在主界面,监听数据变化,实时更新数据。

结果演示

1.刚开始安装完成后效果:

HarmonyOS基础技术赋能之分布式数据服务功能-鸿蒙HarmonyOS技术社区

2.每隔3秒,界面数据都会发生变化:

HarmonyOS基础技术赋能之分布式数据服务功能-鸿蒙HarmonyOS技术社区
HarmonyOS基础技术赋能之分布式数据服务功能-鸿蒙HarmonyOS技术社区

附上源码:

1.MainAbilitySlice

  1. public class MainAbilitySlice extends AbilitySlice { 
  2.   private SingleKvStore singleKvStore; 
  3.   private Text tvTemp; 
  4.   private Text tvHumi; 
  5.   private Text tvGas; 
  6.   private Intent serviceIntent; 
  7.   private InnerKvStoreObserver innerKvStoreObserver; 
  8.  
  9.   @Override 
  10.   public void onStart(Intent intent) { 
  11.     super.onStart(intent); 
  12.     super.setUIContent(ResourceTable.Layout_ability_main); 
  13.     tvTemp=(Text)findComponentById(ResourceTable.Id_tvTemp); 
  14.     tvHumi=(Text)findComponentById(ResourceTable.Id_tvHumi); 
  15.     tvGas=(Text)findComponentById(ResourceTable.Id_tvGas); 
  16.     initService(); 
  17.  
  18.     try { 
  19.       //获取数据库 
  20.       singleKvStore = DBUtils.initOrGetDB(this, DBUtils.STORE_ID); 
  21.       innerKvStoreObserver = new InnerKvStoreObserver(); 
  22.       singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL, innerKvStoreObserver); 
  23.     } catch (KvStoreException e) { 
  24.       e.printStackTrace(); 
  25.     } 
  26.   } 
  27.  
  28.   public class InnerKvStoreObserver implements KvStoreObserver { 
  29.  
  30.     @Override 
  31.     public void onChange(ChangeNotification changeNotification) { 
  32.       //刷新页面上的数据,同样有一个坑,onChange方法实质上,在一个子线程里执行 
  33.       getUITaskDispatcher().asyncDispatch(() -> { 
  34.         //在这里执行页面ui组件的显示刷新 
  35.         flushUIData(); 
  36.       }); 
  37.     } 
  38.   } 
  39.  
  40.   private void flushUIData() { 
  41.     //查询分布式数据的数据 
  42.     List<Entry> entries = singleKvStore.getEntries("key"); 
  43.     if (entries.size() > 0) { 
  44.       ZSONObject zsonObject = ZSONObject.stringToZSON(entries.get(0).getValue().getString()); 
  45.       int temp = zsonObject.getIntValue("temp"); 
  46.       int humidity = zsonObject.getIntValue("humidity"); 
  47.       int other = zsonObject.getIntValue("other"); 
  48.       tvTemp.setText(temp+"℃"); 
  49.       tvHumi.setText(humidity+"% RH"); 
  50.       tvGas.setText(other+"% LEL"); 
  51.     } 
  52.  
  53.  
  54.  
  55.   } 
  56.  
  57.   private void initService() { 
  58.     //启动ServiceAbility 
  59.      serviceIntent = new Intent(); 
  60.     Operation operation = new Intent.OperationBuilder() 
  61.         .withDeviceId(""
  62.         .withBundleName("com.isoftstone.kvstoreapp"
  63.         .withAbilityName("com.isoftstone.kvstoreapp.ServiceAbility"
  64.         .build(); 
  65.     serviceIntent.setOperation(operation); 
  66.     startAbility(serviceIntent); 
  67.   } 
  68.  
  69.   @Override 
  70.   public void onActive() { 
  71.     super.onActive(); 
  72.   } 
  73.  
  74.   @Override 
  75.   public void onForeground(Intent intent) { 
  76.     super.onForeground(intent); 
  77.   } 
  78.  
  79.   @Override 
  80.   protected void onStop() { 
  81.     super.onStop(); 
  82.     //销毁service 
  83.    stopAbility(serviceIntent); 
  84.    //删除数据库 
  85.    DBUtils.clearDB(); 
  86.     //解除订阅 
  87.     if (singleKvStore != null) { 
  88.       singleKvStore.unSubscribe(innerKvStoreObserver); 
  89.     } 
  90.   } 

2.ServiceAbility

  1. public class ServiceAbility extends Ability { 
  2.  
  3.   private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "Demo"); 
  4.   private SingleKvStore singleKvStore; 
  5.   private Timer timer; 
  6.   private MyTimerTask myTimerTask; 
  7.   private int temperature; 
  8.   private int humidity; 
  9.   private int gas; 
  10.  
  11.   @Override 
  12.   public void onStart(Intent intent) { 
  13.     super.onStart(intent); 
  14.     singleKvStore = DBUtils.initOrGetDB(this, DBUtils.STORE_ID); 
  15.     timer=new Timer(); 
  16.     myTimerTask=new MyTimerTask(); 
  17.     timer.schedule(myTimerTask,0,3000); 
  18.  
  19.   } 
  20.  
  21.   @Override 
  22.   public void onBackground() { 
  23.     super.onBackground(); 
  24.     HiLog.info(LABEL_LOG, "ServiceAbility::onBackground"); 
  25.   } 
  26.  
  27.   @Override 
  28.   public void onStop() { 
  29.     super.onStop(); 
  30.     if(myTimerTask!=null){ 
  31.       myTimerTask.cancel(); 
  32.     } 
  33.     if(timer!=null){ 
  34.       timer.cancel(); 
  35.     } 
  36.   } 
  37.  
  38.   @Override 
  39.   public void onCommand(Intent intent, boolean restart, int startId) { 
  40.   } 
  41.  
  42.   @Override 
  43.   public IRemoteObject onConnect(Intent intent) { 
  44.     return null
  45.   } 
  46.  
  47.   @Override 
  48.   public void onDisconnect(Intent intent) { 
  49.   } 
  50.  
  51.   private class MyTimerTask extends TimerTask{ 
  52.  
  53.     @Override 
  54.     public void run() { 
  55.       temperature++; 
  56.       humidity++; 
  57.       gas++; 
  58.       try { 
  59.         long id = System.currentTimeMillis(); 
  60.         singleKvStore.putString("key"
  61.             "{\"id\":" + id + 
  62.                 ",\"temp\":" + temperature + 
  63.                 ",\"humidity\":" + humidity + 
  64.                 ",\"NH4\":" + 0.0 + 
  65.                 ",\"H2S\":" + 0.0 + 
  66.                 ",\"other\":" + gas + "}"); 
  67.       } catch (KvStoreException e) { 
  68.         e.printStackTrace(); 
  69.       } 
  70.  
  71.     } 
  72.   } 

3.DBUtils

  1. public class DBUtils { 
  2.   //分布式数据库storeId 
  3.   public static final String STORE_ID="kvStoreDB"
  4.   private static KvManager kvManager; 
  5.   private static SingleKvStore singleKvStore; 
  6.  
  7.  
  8.   //具体的实现数据库的初始化 
  9.   public static SingleKvStore initOrGetDB(Context context, String storeId) { 
  10.  
  11.     KvManagerConfig kvManagerConfig = new KvManagerConfig(context); 
  12.     kvManager = KvManagerFactory.getInstance().createKvManager(kvManagerConfig); 
  13.     Options options = new Options(); 
  14.     options.setCreateIfMissing(true
  15.         .setEncrypt(false
  16.         .setKvStoreType(KvStoreType.SINGLE_VERSION) 
  17.         .setAutoSync(true);//设置数据为自动同步 
  18.     singleKvStore = kvManager.getKvStore(options, storeId); 
  19.     return singleKvStore; 
  20.   } 
  21.  
  22.   // 如果数据库中的字段有修改,只能先关闭,后删除,然后重新创建才生效 
  23.   public static void clearDB() { 
  24.     kvManager.closeKvStore(singleKvStore); 
  25.     kvManager.deleteKvStore(STORE_ID); 
  26.   } 
  27.  
  28.  

4. MainAbility

  1. public class MainAbility extends Ability { 
  2.  
  3.   @Override 
  4.   public void onStart(Intent intent) { 
  5.     super.onStart(intent); 
  6.     super.setMainRoute(MainAbilitySlice.class.getName()); 
  7.     //实现Ability的代码中显式声明需要使用多设备协同访问的权限 
  8.     requestPermissionsFromUser(new String[]{ 
  9.         "ohos.permission.DISTRIBUTED_DATASYNC"}, 0); 
  10.   } 

5. MyApplication

  1. public class MyApplication extends AbilityPackage { 
  2.  
  3.   @Override 
  4.   public void onInitialize() { 
  5.     super.onInitialize(); 
  6.   } 

6. config.json 文件

  1.   "app": { 
  2.     "bundleName""com.isoftstone.healthdata"
  3.     "vendor""isoftstone"
  4.     "version": { 
  5.       "code": 1000000, 
  6.       "name""1.0" 
  7.     }, 
  8.     "apiVersion": { 
  9.       "compatible": 4, 
  10.       "target": 5, 
  11.       "releaseType""Release" 
  12.     } 
  13.   }, 
  14.   "deviceConfig": {}, 
  15.   "module": { 
  16.     "package""com.isoftstone.kvstoreapp"
  17.     "name"".MyApplication"
  18.     "deviceType": [ 
  19.       "phone" 
  20.     ], 
  21.     "distro": { 
  22.       "deliveryWithInstall"true
  23.       "moduleName""entry"
  24.       "moduleType""entry" 
  25.     }, 
  26.     "reqPermissions": [ 
  27.       { 
  28.         "name""ohos.permission.DISTRIBUTED_DATASYNC" 
  29.       } 
  30.     ], 
  31.     "abilities": [ 
  32.       { 
  33.         "skills": [ 
  34.           { 
  35.             "entities": [ 
  36.               "entity.system.home" 
  37.             ], 
  38.             "actions": [ 
  39.               "action.system.home" 
  40.             ] 
  41.           } 
  42.         ], 
  43.         "orientation""unspecified"
  44.         "name""com.isoftstone.kvstoreapp.MainAbility"
  45.         "icon""$media:icon"
  46.         "description""$string:mainability_description"
  47.         "label""$string:app_name"
  48.         "type""page"
  49.         "launchType""standard" 
  50.       }, 
  51.       { 
  52.         "name""com.isoftstone.kvstoreapp.ServiceAbility"
  53.         "icon""$media:icon"
  54.         "description""$string:serviceability_description"
  55.         "type""service" 
  56.       } 
  57.     ] 
  58.   } 

7.xml布局文件

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <DirectionalLayout 
  3.   xmlns:ohos="http://schemas.huawei.com/res/ohos" 
  4.   ohos:height="match_parent" 
  5.   ohos:orientation="vertical" 
  6.   ohos:width="match_parent"
  7.  
  8. <DirectionalLayout 
  9.   ohos:padding="20vp" 
  10.   ohos:height="match_content" 
  11.   ohos:width="match_parent" 
  12.   ohos:orientation="horizontal"
  13.   <Text 
  14.     ohos:width="match_content" 
  15.     ohos:height="match_content" 
  16.     ohos:text_size="20vp" 
  17.     ohos:text="温度:"/> 
  18.   <Text 
  19.     ohos:id="$+id:tvTemp" 
  20.     ohos:width="0" 
  21.     ohos:height="match_content" 
  22.     ohos:text_size="22vp" 
  23.     ohos:text_color="#00ff00" 
  24.     ohos:text="待采集..." 
  25.     ohos:weight="1"/> 
  26. </DirectionalLayout> 
  27.   <DirectionalLayout 
  28.     ohos:height="1vp" 
  29.     ohos:width="match_parent" 
  30.     ohos:background_element="#cccccc"/> 
  31.  
  32.   <DirectionalLayout 
  33.     ohos:padding="20vp" 
  34.     ohos:height="match_content" 
  35.     ohos:width="match_parent" 
  36.     ohos:orientation="horizontal"
  37.     <Text 
  38.       ohos:width="match_content" 
  39.       ohos:height="match_content" 
  40.       ohos:text_size="20vp" 
  41.       ohos:text="湿度:"/> 
  42.     <Text 
  43.       ohos:id="$+id:tvHumi" 
  44.       ohos:width="0" 
  45.       ohos:height="match_content" 
  46.       ohos:text_size="22vp" 
  47.       ohos:text_color="#00ff00" 
  48.       ohos:text="待采集..." 
  49.       ohos:weight="1"/> 
  50.   </DirectionalLayout> 
  51.   <DirectionalLayout 
  52.     ohos:height="1vp" 
  53.     ohos:width="match_parent" 
  54.     ohos:background_element="#cccccc"/> 
  55.  
  56.  
  57.   <DirectionalLayout 
  58.     ohos:padding="20vp" 
  59.     ohos:height="match_content" 
  60.     ohos:width="match_parent" 
  61.     ohos:orientation="horizontal"
  62.     <Text 
  63.       ohos:width="match_content" 
  64.       ohos:height="match_content" 
  65.       ohos:text_size="20vp" 
  66.       ohos:text="可燃气体:"/> 
  67.     <Text 
  68.       ohos:id="$+id:tvGas" 
  69.       ohos:width="0" 
  70.       ohos:height="match_content" 
  71.       ohos:text_size="22vp" 
  72.       ohos:text_color="#00ff00" 
  73.       ohos:text="待采集..." 
  74.       ohos:weight="1"/> 
  75.   </DirectionalLayout> 
  76.   <DirectionalLayout 
  77.     ohos:height="1vp" 
  78.     ohos:width="match_parent" 
  79.     ohos:background_element="#cccccc"/> 
  80.  
  81. </DirectionalLayout> 

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2020-11-06 12:12:35

HarmonyOS

2015-05-20 15:54:04

Openstack分布式存储

2020-09-29 19:20:05

鸿蒙

2022-06-15 16:16:21

分布式数据库鸿蒙

2022-06-28 08:16:35

MySQL数据容灾

2024-01-08 08:05:08

分开部署数据体系系统拆分

2024-01-09 08:00:58

2023-02-11 00:04:17

分布式系统安全

2018-05-31 08:57:59

分布式块存储元数据

2021-08-26 08:03:30

大数据Zookeeper选举

2021-09-07 10:43:25

EverDB分布式执行

2019-10-10 09:16:34

Zookeeper架构分布式

2021-12-14 10:16:00

鸿蒙HarmonyOS应用

2021-01-19 05:43:33

分布式2PC3PC

2022-09-25 22:19:24

Dapr分布式追踪

2023-02-23 07:55:41

2022-04-08 07:22:15

分布式计数器系统设计

2023-05-29 14:07:00

Zuul网关系统

2019-08-07 10:44:28

MySQLGoogle

2023-12-08 07:31:19

服务网格协同分布式
点赞
收藏

51CTO技术栈公众号