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

欠伸展肢体,吟咏心自愉。这篇文章主要讲述HarmonyOS基础技术赋能之分布式数据服务功能相关的知识,希望能为你提供帮助。
引言分布式数据服务(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; }

【HarmonyOS基础技术赋能之分布式数据服务功能】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< Entry> 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< DeviceInfo> deviceInfoList = kvManager.getConnectedDevicesInfo(DeviceFilterStrategy.NO_FILTER); List< String> deviceIdList = new ArrayList< > (); for (DeviceInfo deviceInfo : deviceInfoList) { deviceIdList.add(deviceInfo.getId()); } singleKvStore.sync(deviceIdList, SyncMode.PUSH_ONLY);

项目中采用在后台service中开启定时任务,实时保存数据到分布式数据库,然后在主界面,监听数据变化,实时更新数据。
结果演示1.刚开始安装完成后效果:
::: hljs-center
HarmonyOS基础技术赋能之分布式数据服务功能

文章图片

:::
2.每隔3秒,界面数据都会发生变化:
::: hljs-center
HarmonyOS基础技术赋能之分布式数据服务功能

文章图片

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

文章图片

:::
附上源码: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< Entry> 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布局文件
< ?xml version="1.0" encoding="utf-8"?> < DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos: ohos:orientation="vertical" ohos:> < DirectionalLayout ohos:padding="20vp" ohos: ohos: ohos:orientation="horizontal"> < Text ohos: ohos: ohos:text_size="20vp" ohos:text="温度:"/> < Text ohos:id="$+id:tvTemp" ohos: ohos: ohos:text_size="22vp" ohos:text_color="#00ff00" ohos:text="待采集..." ohos:weight="1"/> < /DirectionalLayout> < DirectionalLayout ohos: ohos: ohos:background_element="#cccccc"/> < DirectionalLayout ohos:padding="20vp" ohos: ohos: ohos:orientation="horizontal"> < Text ohos: ohos: ohos:text_size="20vp" ohos:text="湿度:"/> < Text ohos:id="$+id:tvHumi" ohos: ohos: ohos:text_size="22vp" ohos:text_color="#00ff00" ohos:text="待采集..." ohos:weight="1"/> < /DirectionalLayout> < DirectionalLayout ohos: ohos: ohos:background_element="#cccccc"/> < DirectionalLayout ohos:padding="20vp" ohos: ohos: ohos:orientation="horizontal"> < Text ohos: ohos: ohos:text_size="20vp" ohos:text="可燃气体:"/> < Text ohos:id="$+id:tvGas" ohos: ohos: ohos:text_size="22vp" ohos:text_color="#00ff00" ohos:text="待采集..." ohos:weight="1"/> < /DirectionalLayout> < DirectionalLayout ohos: ohos: ohos:background_element="#cccccc"/> < /DirectionalLayout>

更多原创内容请关注:软通动力HarmonyOS学院
想了解更多关于鸿蒙的内容,请访问:
51CTO和华为官方战略合作共建的鸿蒙技术社区
https://harmonyos.51cto.com/#bkwz

    推荐阅读