十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
作者:软通张二龙 2021-08-27 09:57:18
开发
前端
分布式
OpenHarmony 分布式数据服务(Distributed Data Service,DDS) 为应用程序提供不同设备间数据库数据分布式的能力。通过调用分布式数据接口,应用程序将数据保存到分布式数据库中。

想了解更多内容,请访问:
51CTO和华为官方合作共建的鸿蒙技术社区
分布式数据服务(Distributed Data Service,DDS) 为应用程序提供不同设备间数据库数据分布式的能力。通过调用分布式数据接口,应用程序将数据保存到分布式数据库中。通过结合帐号、应用和数据库三元组,分布式数据服务对属于不同应用的数据进行隔离,保证不同应用之间的数据不能通过分布式数据服务互相访问。在通过可信认证的设备间,分布式数据服务支持应用数据相互同步,为用户提供在多种终端设备上最终一致的数据访问体验。
此次通过HarmonyOS的分布式数据服务能力,一方面可以实现自身应用界面的数据实时更新;另一方面也可以实现不同设备之间的数据实时更新。前提是在不同设备之间,要实现分布式数据服务的同步能力,需要同一个华为账号登录、并一个应用包名、同一个网络之间进行,也可以两个设备同时开启蓝牙。
1. 在config.json中添加permisssion权限。
- // 添加在abilities同一目录层级
 - "reqPermissions": [
 - {
 - "name": "ohos.permission.DISTRIBUTED_DATASYNC"
 - }
 - ]
 
2. 在MainAbility中添加权限
- @Override
 - public void onStart(Intent intent) {
 - super.onStart(intent);
 - super.setMainRoute(MainAbilitySlice.class.getName());
 - //实现Ability的代码中显式声明需要使用多设备协同访问的权限
 - requestPermissionsFromUser(new String[]{
 - "ohos.permission.DISTRIBUTED_DATASYNC"}, 0);
 - }
 
3. 根据配置构造分布式数据库管理类实例KvManager以及创建分布式数据库对象SingleKvStore。
- //实现数据库的初始化
 - // 初入的参数context: Context context = getApplicationContext()获得;storeId为分布式数据库id,String类型,可自行定义,例如“testApp”。
 - public static SingleKvStore initOrGetDB(Context context, String storeId) {
 - KvManagerConfig kvManagerConfig = new KvManagerConfig(context);
 - kvManager = KvManagerFactory.getInstance().createKvManager(kvManagerConfig);
 - Options options = new Options();
 - options.setCreateIfMissing(true)
 - .setEncrypt(false)
 - .setKvStoreType(KvStoreType.SINGLE_VERSION) //数据库类型:单版本分布式数据库
 - .setAutoSync(true);//设置数据为自动同步
 - singleKvStore = kvManager.getKvStore(options, storeId);
 - return singleKvStore;
 - }
 
4. 将数据写入单版本分布式数据库。
- //以key-value形式存储到分布式数据库
 - try {
 - long id = System.currentTimeMillis();
 - singleKvStore.putString("key",
 - "{\"id\":" + id +
 - ",\"temp\":" + temperature +
 - ",\"humidity\":" + humidity +
 - ",\"NH4\":" + 0.0 +
 - ",\"H2S\":" + 0.0 +
 - ",\"other\":" + gas + "}");
 - } catch (KvStoreException e) {
 - e.printStackTrace();
 - }
 
5.订阅分布式数据变化。客户端需要实现KvStoreObserver接口,监听数据变化。
- try {
 - //订阅类型SubscribeType.SUBSCRIBE_TYPE_ALL意思可以同步到本机和其他外围设备
 - innerKvStoreObserver = new InnerKvStoreObserver();
 - singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL, innerKvStoreObserver);
 - } catch (KvStoreException e) {
 - e.printStackTrace();
 - }
 - public class InnerKvStoreObserver implements KvStoreObserver {
 - @Override
 - public void onChange(ChangeNotification changeNotification) {
 - //刷新页面上的数据,同样有一个坑,onChange方法实质上,在一个子线程里执行
 - MainAbilitySlice.taskDispatcher.asyncDispatch(() -> {
 - //在这里执行页面ui组件的显示刷新
 - flushUIData();
 - });
 - }
 - }
 
6.获取分布式数据库数据
- private void flushUIData() {
 - //查询分布式数据的数据,获取数据可以通过get(String key)/ getEntries(String key)方法获取数据
 - List
 entries = singleKvStore.getEntries(“key”); - if (entries.size() > 0) {
 - ZSONObject zsonObject = ZSONObject.stringToZSON(entries.get(0).getValue().getString());
 - int temp = zsonObject.getIntValue("temp");
 - int humidity = zsonObject.getIntValue("humidity");
 - int other = zsonObject.getIntValue("other");
 - tvTemp.setText(temp+"℃");
 - tvHumi.setText(humidity+"% RH");
 - tvGas.setText(other+"% LEL");
 - }
 
7. 解除订阅。一般在页面销毁时调用,也就是MainAbilitySlice的onStop()中调用
- if (singleKvStore != null) {
 - singleKvStore.unSubscribe(innerKvStoreObserver);
 - }
 
8. 同步数据到其他设备。获取已连接的设备列表,选择同步方式进行数据同步
- List
 deviceInfoList = kvManager.getConnectedDevicesInfo(DeviceFilterStrategy.NO_FILTER); - List
 deviceIdList = new ArrayList<>(); - for (DeviceInfo deviceInfo : deviceInfoList) {
 - deviceIdList.add(deviceInfo.getId());
 - }
 - singleKvStore.sync(deviceIdList, SyncMode.PUSH_ONLY);
 
项目中采用在后台service中开启定时任务,实时保存数据到分布式数据库,然后在主界面,监听数据变化,实时更新数据。
1.刚开始安装完成后效果:
2.每隔3秒,界面数据都会发生变化:
附上源码:
1.MainAbilitySlice
- public class MainAbilitySlice extends AbilitySlice {
 - private SingleKvStore singleKvStore;
 - private Text tvTemp;
 - private Text tvHumi;
 - private Text tvGas;
 - private Intent serviceIntent;
 - private InnerKvStoreObserver innerKvStoreObserver;
 - @Override
 - public void onStart(Intent intent) {
 - super.onStart(intent);
 - super.setUIContent(ResourceTable.Layout_ability_main);
 - tvTemp=(Text)findComponentById(ResourceTable.Id_tvTemp);
 - tvHumi=(Text)findComponentById(ResourceTable.Id_tvHumi);
 - tvGas=(Text)findComponentById(ResourceTable.Id_tvGas);
 - initService();
 - try {
 - //获取数据库
 - singleKvStore = DBUtils.initOrGetDB(this, DBUtils.STORE_ID);
 - innerKvStoreObserver = new InnerKvStoreObserver();
 - singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL, innerKvStoreObserver);
 - } catch (KvStoreException e) {
 - e.printStackTrace();
 - }
 - }
 - public class InnerKvStoreObserver implements KvStoreObserver {
 - @Override
 - public void onChange(ChangeNotification changeNotification) {
 - //刷新页面上的数据,同样有一个坑,onChange方法实质上,在一个子线程里执行
 - getUITaskDispatcher().asyncDispatch(() -> {
 - //在这里执行页面ui组件的显示刷新
 - flushUIData();
 - });
 - }
 - }
 - private void flushUIData() {
 - //查询分布式数据的数据
 - List
 entries = singleKvStore.getEntries("key"); - if (entries.size() > 0) {
 - ZSONObject zsonObject = ZSONObject.stringToZSON(entries.get(0).getValue().getString());
 - int temp = zsonObject.getIntValue("temp");
 - int humidity = zsonObject.getIntValue("humidity");
 - int other = zsonObject.getIntValue("other");
 - tvTemp.setText(temp+"℃");
 - tvHumi.setText(humidity+"% RH");
 - tvGas.setText(other+"% LEL");
 - }
 - }
 - private void initService() {
 - //启动ServiceAbility
 - serviceIntent = new Intent();
 - Operation operation = new Intent.OperationBuilder()
 - .withDeviceId("")
 - .withBundleName("com.isoftstone.kvstoreapp")
 - .withAbilityName("com.isoftstone.kvstoreapp.ServiceAbility")
 - .build();
 - serviceIntent.setOperation(operation);
 - startAbility(serviceIntent);
 - }
 - @Override
 - public void onActive() {
 - super.onActive();
 - }
 - @Override
 - public void onForeground(Intent intent) {
 - super.onForeground(intent);
 - }
 - @Override
 - protected void onStop() {
 - super.onStop();
 - //销毁service
 - stopAbility(serviceIntent);
 - //删除数据库
 - DBUtils.clearDB();
 - //解除订阅
 - if (singleKvStore != null) {
 - singleKvStore.unSubscribe(innerKvStoreObserver);
 - }
 - }
 - }
 
2.ServiceAbility
- public class ServiceAbility extends Ability {
 - private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "Demo");
 - private SingleKvStore singleKvStore;
 - private Timer timer;
 - private MyTimerTask myTimerTask;
 - private int temperature;
 - private int humidity;
 - private int gas;
 - @Override
 - public void onStart(Intent intent) {
 - super.onStart(intent);
 - singleKvStore = DBUtils.initOrGetDB(this, DBUtils.STORE_ID);
 - timer=new Timer();
 - myTimerTask=new MyTimerTask();
 - timer.schedule(myTimerTask,0,3000);
 - }
 - @Override
 - public void onBackground() {
 - super.onBackground();
 - HiLog.info(LABEL_LOG, "ServiceAbility::onBackground");
 - }
 - @Override
 - public void onStop() {
 - super.onStop();
 - if(myTimerTask!=null){
 - myTimerTask.cancel();
 - }
 - if(timer!=null){
 - timer.cancel();
 - }
 - }
 - @Override
 - public void onCommand(Intent intent, boolean restart, int startId) {
 - }
 - @Override
 - public IRemoteObject onConnect(Intent intent) {
 - return null;
 - }
 - @Override
 - public void onDisconnect(Intent intent) {
 - }
 - private class MyTimerTask extends TimerTask{
 - @Override
 - public void run() {
 - temperature++;
 - humidity++;
 - gas++;
 - try {
 - long id = System.currentTimeMillis();
 - singleKvStore.putString("key",
 - "{\"id\":" + id +
 - ",\"temp\":" + temperature +
 - ",\"humidity\":" + humidity +
 - ",\"NH4\":" + 0.0 +
 - ",\"H2S\":" + 0.0 +
 - ",\"other\":" + gas + "}");
 - } catch (KvStoreException e) {
 - e.printStackTrace();
 - }
 - }
 - }
 - }
 
3.DBUtils
- public class DBUtils {
 - //分布式数据库storeId
 - public static final String STORE_ID="kvStoreDB";
 - private static KvManager kvManager;
 - private static SingleKvStore singleKvStore;
 - //具体的实现数据库的初始化
 - public static SingleKvStore initOrGetDB(Context context, String storeId) {
 - KvManagerConfig kvManagerConfig = new KvManagerConfig(context);
 - kvManager = KvManagerFactory.getInstance().createKvManager(kvManagerConfig);
 - Options options = new Options();
 - options.setCreateIfMissing(true)
 - .setEncrypt(false)
 - .setKvStoreType(KvStoreType.SINGLE_VERSION)
 - .setAutoSync(true);//设置数据为自动同步
 - singleKvStore = kvManager.getKvStore(options, storeId);
 - return singleKvStore;
 - }
 - // 如果数据库中的字段有修改,只能先关闭,后删除,然后重新创建才生效
 - public static void clearDB() {
 - kvManager.closeKvStore(singleKvStore);
 - kvManager.deleteKvStore(STORE_ID);
 - }
 - }
 
4. MainAbility
- public class MainAbility extends Ability {
 - @Override
 - public void onStart(Intent intent) {
 - super.onStart(intent);
 - super.setMainRoute(MainAbilitySlice.class.getName());
 - //实现Ability的代码中显式声明需要使用多设备协同访问的权限
 - requestPermissionsFromUser(new String[]{
 - "ohos.permission.DISTRIBUTED_DATASYNC"}, 0);
 - }
 - }
 
5. MyApplication
- public class MyApplication extends AbilityPackage {
 - @Override
 - public void onInitialize() {
 - super.onInitialize();
 - }
 - }
 
6. config.json 文件
- {
 - "app": {
 - "bundleName": "com.isoftstone.healthdata",
 - "vendor": "isoftstone",
 - "version": {
 - "code": 1000000,
 - "name": "1.0"
 - },
 - "apiVersion": {
 - "compatible": 4,
 - "target": 5,
 - "releaseType": "Release"
 - }
 - },
 - "deviceConfig": {},
 - "module": {
 - "package": "com.isoftstone.kvstoreapp",
 - "name": ".MyApplication",
 - "deviceType": [
 - "phone"
 - ],
 - "distro": {
 - "deliveryWithInstall": true,
 - "moduleName": "entry",
 - "moduleType": "entry"
 - },
 - "reqPermissions": [
 - {
 - "name": "ohos.permission.DISTRIBUTED_DATASYNC"
 - }
 - ],
 - "abilities": [
 - {
 - "skills": [
 - {
 - "entities": [
 - "entity.system.home"
 - ],
 - "actions": [
 - "action.system.home"
 - ]
 - }
 - ],
 - "orientation": "unspecified",
 - "name": "com.isoftstone.kvstoreapp.MainAbility",
 - "icon": "$media:icon",
 - "description": "$string:mainability_description",
 - "label": "$string:app_name",
 - "type": "page",
 - "launchType": "standard"
 - },
 - {
 - "name": "com.isoftstone.kvstoreapp.ServiceAbility",
 - "icon": "$media:icon",
 - "description": "$string:serviceability_description",
 - "type": "service"
 - }
 - ]
 - }
 - }
 
7.xml布局文件
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
 - ohos:height="match_parent"
 - ohos:orientation="vertical"
 - ohos:width="match_parent">
 - ohos:padding="20vp"
 - ohos:height="match_content"
 - ohos:width="match_parent"
 - ohos:orientation="horizontal">
 - ohos:width="match_content"
 - ohos:height="match_content"
 - ohos:text_size="20vp"
 - ohos:text="温度:"/>
 - ohos:id="$+id:tvTemp"
 - ohos:width="0"
 - ohos:height="match_content"
 - ohos:text_size="22vp"
 - ohos:text_color="#00ff00"
 - ohos:text="待采集..."
 - ohos:weight="1"/>
 - ohos:height="1vp"
 - ohos:width="match_parent"
 - ohos:background_element="#cccccc"/>
 - ohos:padding="20vp"
 - ohos:height="match_content"
 - ohos:width="match_parent"
 - ohos:orientation="horizontal">
 - ohos:width="match_content"
 - ohos:height="match_content"
 - ohos:text_size="20vp"
 - ohos:text="湿度:"/>
 - ohos:id="$+id:tvHumi"
 - ohos:width="0"
 - ohos:height="match_content"
 - ohos:text_size="22vp"
 - ohos:text_color="#00ff00"
 - ohos:text="待采集..."
 - ohos:weight="1"/>
 - ohos:height="1vp"
 - ohos:width="match_parent"
 - ohos:background_element="#cccccc"/>
 - ohos:padding="20vp"
 - ohos:height="match_content"
 - ohos:width="match_parent"
 - ohos:orientation="horizontal">
 - ohos:width="match_content"
 - ohos:height="match_content"
 - ohos:text_size="20vp"
 - ohos:text="可燃气体:"/>
 - ohos:id="$+id:tvGas"
 - ohos:width="0"
 - ohos:height="match_content"
 - ohos:text_size="22vp"
 - ohos:text_color="#00ff00"
 - ohos:text="待采集..."
 - ohos:weight="1"/>
 - ohos:height="1vp"
 - ohos:width="match_parent"
 - ohos:background_element="#cccccc"/>