引言
分布式数据服务(Distributed Data Service,DDS) 为应用程序提供不同设备间数据库数据分布式的能力。通过调用分布式数据接口,应用程序将数据保存到分布式数据库中。通过结合帐号、应用和数据库三元组,分布式数据服务对属于不同应用的数据进行隔离,保证不同应用之间的数据不能通过分布式数据服务互相访问。在通过可信认证的设备间,分布式数据服务支持应用数据相互同步,为用户提供在多种终端设备上最终一致的数据访问体验。
功能介绍
此次基于HarmonyOS的分布式数据服务能力,一方面模拟农业大棚的温度、湿度、二氧化碳浓度等数据的采集,并在手机端进行采集数据展示;另一方面,可以把手机端的数据,迁移到其他设备(如智慧屏、手表、PAD等),可以做一些数据分析展示。
前提:
在不同设备之间,要实现分布式数据服务的同步能力,需要同一个华为账号登录、并一个应用包名、同一个网络之间进行,也可以是两个设备同时开启蓝牙。
开发指南
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); //自动同步为true,手动同步为false
- singleKvStore = kvManager.getKvStore(options, storeId);
- return singleKvStore;
- }
4.将数据写入单版本分布式数据库
- //以key-value形式存储到分布式数据库
- try {
- //将采集的数据以key-value形式存入分布式数据库中
- DataModle dataModle=new DataModle();
- dataModle.setTemp(temp);
- dataModle.setHumi(humi);
- dataModle.setCo2(co2);
- String jsonString= ZSONObject.toZSONString(dataModle);
- singleKvStore.putString("data",jsonString);
- } catch (KvStoreException e) {
- LogUtils.debug(TAG, "DataServiceAbility::updateData()"+e.getMessage());
- }
5.订阅分布式数据变化。客户端需要实现KvStoreObserver接口,监听数据变化
- //订阅类型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.获取分布式数据库数据
- //查询分布式数据的数据,获取数据可以通过get(String key)或者 getEntries(String key)方法获取数据
- List<Entry> entries = singleKvStore.getEntries("data");
- if (entries.size() > 0) {
- ZSONObject zsonObject = ZSONObject.stringToZSON(entries.get(0).getValue().getString());
- double temp = zsonObject.getDouble("temp");
- double humi = zsonObject.getDouble("humi");
- double co2 = zsonObject.getDouble("co2");
- String strTemp = String.format("%.1f", temp);
- String strHumi = String.format("%.1f", humi);
- String strCO2 = String.format("%.1f", co2);
- tvTemp.setText(strTemp+"℃");
- tvHumi.setText(strHumi+"%RH");
- tvCo2.setText(strCO2+"ppm");
- }
7.解除订阅,一般在页面销毁时调用,也就是在onStop()中调用
- if (singleKvStore != null) {
- singleKvStore.unSubscribe(innerKvStoreObserver);
- }
8.同步数据到其他设备。获取已连接的设备列表,选择同步方式进行数据同步
- List<DeviceInfo> onlineDevices = DeviceManager
- .getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
- List<String> deviceIdList = new ArrayList<>();
- for (DeviceInfo deviceInfo : deviceInfoList) {
- deviceIdList.add(deviceInfo.getId());
- }
- //迁移到指定设备,传入设备ID列表
- singleKvStore.sync(deviceIdList, SyncMode.PUSH_ONLY);
项目中采用在后台service中开启定时任务,模拟农业大棚采集数据,实时保存数据到分布式数据库,然后在主界面,监听数据变化,实时更新数据。当选择迁移的设备时,就可以把数据迁移到相应设备。
手机侧应用刚打开时界面
TV侧应用刚打开时界面
点击右上角迁移按钮,并选择迁移设备(P40-0036)
迁移后的左侧设备数据和右侧设备数据就会同步一致
附上源码
手机端
1. PhoneAbilitySlice
- public class PhoneAbilitySlice extends AbilitySlice {
- private SingleKvStore singleKvStore;
- private InnerKvStoreObserver innerKvStoreObserver;
- private Intent serviceIntent;
- private Text tvTemp;
- private Text tvHumi;
- private Text tvCo2;
- private DeviceData chooseDevice;
- private DevicesProvider devicesProvider;
- private CommonDialog commonDialog;
- private String TAG="MainAbilitySlice";
- private List<String>deviceIdList;
- @Override
- public void onStart(Intent intent) {
- super.onStart(intent);
- super.setUIContent(ResourceTable.Layout_ability_main);
- //设置沉浸式状态栏 getWindow().addFlags(WindowManager.LayoutConfig.MARK_TRANSLUCENT_STATUS);
- initView();
- initService();
- try {
- //获取数据库
- singleKvStore = DBUtils.initOrGetDB(this, DBUtils.KV_STORE_NAME);
- innerKvStoreObserver = new InnerKvStoreObserver();
- //订阅分布式数据库
- singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL, innerKvStoreObserver);
- } catch (KvStoreException e) {
- LogUtils.debug(TAG, "MainAbilitySlice::onStart/"+e.getMessage());
- }
- }
- private void initService() {
- //启动ServiceAbility
- serviceIntent = new Intent();
- Operation operation = new Intent.OperationBuilder()
- .withDeviceId("")
- .withBundleName("com.isoftstone.distributeddata")
- .withAbilityName("com.isoftstone.distributeddata.DataServiceAbility")
- .build();
- serviceIntent.setOperation(operation);
- startAbility(serviceIntent);
- }
- private void initView() {
- tvTemp = (Text) findComponentById(ResourceTable.Id_text_temp);
- tvHumi = (Text) findComponentById(ResourceTable.Id_text_humi);
- tvCo2 = (Text) findComponentById(ResourceTable.Id_text_co2);
- Button bt = (Button) findComponentById(ResourceTable.Id_bt_continue);
- bt.setClickedListener(component -> {
- if (component.getId() == ResourceTable.Id_bt_continue) {
- //查看在线设备
- List<DeviceInfo> onlineDevices = DeviceManager
- .getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
- List<DeviceData> deviceDatas = new ArrayList<>();
- if (onlineDevices == null || onlineDevices.size() < 1) {
- CustomerDialog.showToastDialog(getAbility(), "无组网在线设备");
- } else {
- for (DeviceInfo deviceInfo : onlineDevices) {
- deviceDatas.add(new DeviceData(false, deviceInfo));
- }
- showDevices(deviceDatas);
- }
- }
- });
- }
- private void showDevices(List<DeviceData> deviceDatas) {
- chooseDevice = null;
- commonDialog = new CommonDialog(this);
- Component component = LayoutScatter.getInstance(this)
- .parse(ResourceTable.Layout_dialog_layout_device, null, true);
- ListContainer listContainer = (ListContainer) component.findComponentById(ResourceTable.Id_list_container_device);
- devicesProvider = new DevicesProvider(this, deviceDatas);
- listContainer.setItemProvider(devicesProvider);
- listContainer.setItemClickedListener((listContainer1, component1, position, l) -> {
- chooseDevice = deviceDatas.get(position);
- for (int i = 0; i < deviceDatas.size(); i++) {
- if (i == position) {
- deviceDatas.set(i, new DeviceData(true, deviceDatas.get(i).getDeviceInfo()));
- } else {
- deviceDatas.set(i, new DeviceData(false, deviceDatas.get(i).getDeviceInfo()));
- }
- }
- devicesProvider = new DevicesProvider(this, deviceDatas);
- listContainer1.setItemProvider(devicesProvider);
- });
- Text tvCancle = (Text) component.findComponentById(ResourceTable.Id_operate_no);
- Text tvSure = (Text) component.findComponentById(ResourceTable.Id_operate_yes);
- tvCancle.setClickedListener(component12 -> commonDialog.destroy());
- tvSure.setClickedListener(component13 -> {
- if (chooseDevice == null) {
- CustomerDialog.showToastDialog(this, "请选择设备");
- } else {
- try {
- deviceIdList=new ArrayList<>();
- deviceIdList.add(chooseDevice.getDeviceInfo().getDeviceId());
- //手动同步的设备列表
- singleKvStore.sync(deviceIdList, SyncMode.PUSH_ONLY);
- commonDialog.destroy();
- } catch (IllegalStateException e) {
- //流转异常捕获,防止进程存在再次发起流转
- LogUtils.debug(TAG, "MainAbilitySlice::singleKvStore.sync()/"+e.getMessage());
- }
- }
- });
- commonDialog.setSize(MATCH_PARENT, MATCH_CONTENT);
- commonDialog.setAlignment(LayoutAlignment.BOTTOM);
- commonDialog.setCornerRadius(10);
- commonDialog.setAutoClosable(true);
- commonDialog.setContentCustomComponent(component);
- commonDialog.setTransparent(true);
- commonDialog.show();
- }
- public class InnerKvStoreObserver implements KvStoreObserver {
- @Override
- public void onChange(ChangeNotification changeNotification) {
- //onChange方法实质上,在一个子线程里执行
- getUITaskDispatcher().asyncDispatch(() -> {
- //在这里执行页面ui组件的显示刷新
- asyncUpdateData();
- });
- }
- }
- public void asyncUpdateData(){
- //查询分布式数据的数据
- List<Entry> entries = singleKvStore.getEntries("data");
- if (entries.size() > 0) {
- ZSONObject zsonObject = ZSONObject.stringToZSON(entries.get(0).getValue().getString());
- double temp = zsonObject.getDouble("temp");
- double humi = zsonObject.getDouble("humi");
- double co2 = zsonObject.getDouble("co2");
- String strTemp = String.format("%.1f", temp);
- String strHumi = String.format("%.1f", humi);
- String strCO2 = String.format("%.1f", co2);
- tvTemp.setText(strTemp+"℃");
- tvHumi.setText(strHumi+"%RH");
- tvCo2.setText(strCO2+"ppm");
- //手动同步的设备列表
- if(singleKvStore!=null){
- if(deviceIdList!=null&&deviceIdList.size()>0){
- singleKvStore.sync(deviceIdList, SyncMode.PUSH_ONLY);
- }
- }
- }
- }
- @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) {
- if(innerKvStoreObserver!=null){
- singleKvStore.unSubscribe(innerKvStoreObserver);
- }
- }
- }
- }
2. DataServiceAbility
- public class DataServiceAbility extends Ability {
- private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "Demo");
- private SingleKvStore singleKvStore;
- private NotificationRequest request;
- private Timer mTimer;
- private TimerTask mTimerTask;
- private String TAG="DataServiceAbility";
- @Override
- public void onStart(Intent intent) {
- LogUtils.debug(TAG, "DataServiceAbility::onStart");
- super.onStart(intent);
- //创建前台service
- createForeService();
- try {
- singleKvStore = DBUtils.initOrGetDB(this, DBUtils.KV_STORE_NAME);
- } catch (Exception e) {
- LogUtils.debug(TAG, "DataServiceAbility::onStart()"+e.getMessage());
- }
- //每隔10秒,模拟传感器采集一次大棚数据。
- if(mTimer==null){
- mTimer=new Timer();
- }
- if(mTimerTask==null){
- mTimerTask=new TimerTask() {
- @Override
- public void run() {
- updateData();
- }
- };
- }
- mTimer.schedule(mTimerTask,0,1000*10);
- }
- private void updateData() {
- //获取随机温度0-100;
- double temp= new Random().nextDouble()*100;
- //获取随机湿度0-100;
- double humi= new Random().nextDouble()*100;
- //获取随机CO2浓度0-1000
- double co2= new Random().nextDouble()*1000;
- try {
- //将采集的数据以key-value形式存入分布式数据库中
- DataModle dataModle=new DataModle();
- dataModle.setTemp(temp);
- dataModle.setHumi(humi);
- dataModle.setCo2(co2);
- String jsonString= ZSONObject.toZSONString(dataModle);
- singleKvStore.putString("data",jsonString);
- } catch (KvStoreException e) {
- LogUtils.debug(TAG, "DataServiceAbility::updateData()"+e.getMessage());
- }
- }
- private void createForeService() {
- // 创建通知,其中1005为notificationId
- request = new NotificationRequest(1005);
- NotificationRequest.NotificationNormalContent content = new NotificationRequest.NotificationNormalContent();
- content.setTitle("农业大棚").setText("数据采集服务开启中");
- NotificationRequest.NotificationContent notificationContent = new NotificationRequest.NotificationContent(content);
- request.setContent(notificationContent);
- //绑定通知,1005为创建通知时传入的notificationId
- keepBackgroundRunning(1005, request);
- }
- @Override
- public void onBackground() {
- super.onBackground();
- LogUtils.debug(TAG, "DataServiceAbility::onBackground()");
- }
- @Override
- public void onStop() {
- super.onStop();
- if (mTimerTask != null) {
- mTimerTask.cancel();
- mTimerTask=null;
- } if (mTimer != null) {
- mTimer.cancel();
- mTimer=null;
- }
- //停止前台Service。
- cancelBackgroundRunning();
- LogUtils.debug(TAG, "DataServiceAbility::onStop()");
- }
- @Override
- public void onCommand(Intent intent, boolean restart, int startId) {
- }
- @Override
- public IRemoteObject onConnect(Intent intent) {
- return null;
- }
- @Override
- public void onDisconnect(Intent intent) {
- }
- }
3.DBUtils
- public class DBUtils {
- private static KvManager kvManager;
- private static SingleKvStore singleKvStore;
- public static String KV_STORE_NAME="farm_data";
- //具体的实现数据库的初始化
- 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(false);//自动同步为true,手动同步为false
- singleKvStore = kvManager.getKvStore(options, storeId);
- return singleKvStore;
- }
- // 如果数据库中的字段有修改,只能先关闭,后删除,然后重新创建才生效
- public static void clearDB() {
- kvManager.closeKvStore(singleKvStore);
- kvManager.deleteKvStore(KV_STORE_NAME);
- }
- }
4. MainAbility
- @Override
- public void onStart(Intent intent) {
- super.onStart(intent);
- super.setMainRoute(PhoneAbilitySlice.class.getName());
- //实现Ability的代码中显式声明需要使用多设备协同访问的权限
- requestPermissionsFromUser(new String[]{"ohos.permission.DISTRIBUTED_DATASYNC",}, 0);
- }
5. DataModle
- public class DataModle {
- private double temp;
- private double humi;
- private double co2;
- public double getTemp() {
- return temp;
- }
- public void setTemp(double temp) {
- this.temp = temp;
- }
- public double getHumi() {
- return humi;
- }
- public void setHumi(double humi) {
- this.humi = humi;
- }
- public double getCo2() {
- return co2;
- }
- public void setCo2(double co2) {
- this.co2 = co2;
- }
- }
6. DeviceData
- public class DeviceData {
- private boolean isChecked;
- private DeviceInfo deviceInfo;
- /**
- * DeviceData
- *
- * @param isChecked isChecked
- * @param deviceInfo deviceInfo
- */
- public DeviceData(boolean isChecked, DeviceInfo deviceInfo) {
- this.isChecked = isChecked;
- this.deviceInfo = deviceInfo;
- }
- public DeviceInfo getDeviceInfo() {
- return deviceInfo;
- }
- public void setDeviceInfo(DeviceInfo deviceInfo) {
- this.deviceInfo = deviceInfo;
- }
- public boolean isChecked() {
- return isChecked;
- }
- public void setChecked(boolean checked) {
- isChecked = checked;
- }
- }
7. DevicesProvider
- public class DevicesProvider extends BaseItemProvider {
- private List<DeviceData> data;
- private LayoutScatter layoutScatter;
- public DevicesProvider(Context context, List<DeviceData> data) {
- this.data = data;
- this.layoutScatter = LayoutScatter.getInstance(context);
- }
- @Override
- public int getCount() {
- return data.size();
- }
- @Override
- public Object getItem(int i) {
- return data.get(i);
- }
- @Override
- public long getItemId(int i) {
- return i;
- }
- @Override
- public Component getComponent(int position, Component component,
- ComponentContainer componentContainer) {
- ViewHolder viewHolder;
- // component相当于Android中的view,其他的和Android中ListView的适配器adapter差不多。
- // 名字区别也不大,不过Android中ListView基本被淘汰了。
- if (component == null) {
- component = layoutScatter.parse(ResourceTable.Layout_dialog_device_item, null, false);
- viewHolder = new ViewHolder();
- viewHolder.imgType = (Image) component.findComponentById(ResourceTable.Id_item_type);
- viewHolder.tvName = (Text) component.findComponentById(ResourceTable.Id_item_name);
- viewHolder.imgCheck = (Image) component.findComponentById(ResourceTable.Id_item_check);
- component.setTag(viewHolder);
- } else {
- viewHolder = (ViewHolder) component.getTag();
- }
- DeviceData deviceData = data.get(position);
- DeviceType deviceType=deviceData.getDeviceInfo().getDeviceType();
- switch (deviceType){
- case SMART_WATCH:
- viewHolder.imgType.setPixelMap(ResourceTable.Media_dv_watch);
- break;
- case SMART_PAD:
- viewHolder.imgType.setPixelMap(ResourceTable.Media_dv_pad);
- break;
- case SMART_PHONE:
- viewHolder.imgType.setPixelMap(ResourceTable.Media_dv_phone);
- break;
- }
- viewHolder.tvName.setText(deviceData.getDeviceInfo().getDeviceName());
- if(deviceData.isChecked()){
- viewHolder.imgCheck.setImageAndDecodeBounds(ResourceTable.Media_check2); }else { viewHolder.imgCheck.setImageAndDecodeBounds(ResourceTable.Media_uncheck2);
- }
- return component;
- }
- /**
- * 类似于Android中的listView缓存。 将已经显示在屏幕上的item缓存在ViewHolder中,下次再次出现直接从缓存中读取
- */
- private static class ViewHolder {
- private Image imgType;
- private Text tvName;
- private Image imgCheck;
- }
- }
8. CustomerDialog
- public class CustomerDialog {
- public static void showToastDialog(Context context, String str) {
- DirectionalLayout toastLayout = (DirectionalLayout) LayoutScatter.getInstance(context)
- .parse(ResourceTable.Layout_toast_dialog, null, false);
- Text text = (Text) toastLayout.findComponentById(ResourceTable.Id_toast);
- text.setText(str);
- new ToastDialog(context)
- .setContentCustomComponent(toastLayout)
- .setSize(DirectionalLayout.LayoutConfig.MATCH_CONTENT,
- DirectionalLayout.LayoutConfig.MATCH_CONTENT)
- .setAlignment(LayoutAlignment.CENTER)
- .show();
- }
- }
9. MyApplication
- @Override
- public void onInitialize() {
- super.onInitialize();
- }
- }
10. config.json 文件
- "app": {
- "bundleName": " com.isoftstone.distributeddata ",
- "vendor": "isoftstone",
- "version": {
- "code": 1000000,
- "name": "1.0.0"
- }
- },
- "deviceConfig": {},
- "module": {
- "package": "com.isoftstone.distributeddata",
- "name": ".MyApplication",
- "mainAbility": "com.isoftstone.distributeddata.MainAbility",
- "deviceType": [
- "phone"
- ],
- "distro": {
- "deliveryWithInstall": true,
- "moduleName": "entry",
- "moduleType": "entry",
- "installationFree": false
- },
- "reqPermissions": [
- {
- "name": "ohos.permission.DISTRIBUTED_DATASYNC"
- },
- {
- 添加此权限,才能查找分布式在线设备
- "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"
- },
- {
- 将service设置为前台服务,需要添加的权限
- "name": "ohos.permission.KEEP_BACKGROUND_RUNNING"
- }
- ],
- "abilities": [
- {
- "skills": [
- {
- "entities": [
- "entity.system.home"
- ],
- "actions": [
- "action.system.home"
- ]
- }
- ],
- "orientation": "unspecified",
- "name": "com.isoftstone.distributeddata.MainAbility",
- "icon": "$media:icon",
- "description": "$string:mainability_description",
- "label": "$string:entry_MainAbility",
- "type": "page",
- "launchType": "standard"
- },
- {
- "name": "com.isoftstone.distributeddata.DataServiceAbility",
- "icon": "$media:icon",
- "description": "$string:dataserviceability_description",
- "type": "service",
- "visible": true,
- "backgroundModes": [
- "dataTransfer",
- "location"
- ]
- }
- ],
- "metaData": {
- "customizeData": [
- {
- "name": "hwc-theme",
- "value": "androidhwext:style/Theme.Emui.NoTitleBar",
- "extra": ""
- }
- ]
- }
- }
11.ability_main.xml布局文件
- <?xml version="1.0" encoding="utf-8"?>
- <DirectionalLayout
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:orientation="vertical">
- <DependentLayout
- ohos:width="match_parent"
- ohos:height="match_content"
- ohos:orientation="horizontal"
- ohos:top_padding="50vp"
- ohos:bottom_padding="20vp"
- ohos:left_padding="20vp"
- ohos:right_padding="20vp"
- ohos:background_element="$graphic:background_ability_main">
- <Text
- ohos:width="match_content"
- ohos:height="match_content"
- ohos:text="农业大棚数据监测"
- ohos:text_size="26vp"
- ohos:text_color="#ffffff"
- ohos:center_in_parent="true"/>
- <Button
- ohos:id="$+id:bt_continue"
- ohos:width="25vp"
- ohos:height="25vp"
- ohos:background_element="$media:conti"
- ohos:align_parent_right="true"
- ohos:vertical_center="true"/>
- </DependentLayout>
- <DependentLayout
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:background_element="#f4f5f7"
- ohos:left_padding="15vp"
- ohos:right_padding="15vp"
- ohos:top_padding="10vp"
- ohos:bottom_padding="10vp">
- <Text
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="温度:"
- ohos:text_color="#000000"
- ohos:text_size="18fp"
- ohos:vertical_center="true"/>
- <Text
- ohos:id="$+id:text_temp"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="数据正在采集 "
- ohos:text_color="#00ff00"
- ohos:text_size="18fp"
- ohos:left_margin="50vp"
- ohos:vertical_center="true"/>
- </DependentLayout>
- <Component
- ohos:height="2vp"
- ohos:width="match_content"
- ohos:background_element="#FFFFFF"/>
- <DependentLayout
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:background_element="#f4f5f7"
- ohos:left_padding="15vp"
- ohos:right_padding="15vp"
- ohos:top_padding="10vp"
- ohos:bottom_padding="10vp">
- <Text
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="湿度:"
- ohos:text_color="#000000"
- ohos:text_size="18fp"
- ohos:vertical_center="true"/>
- <Text
- ohos:id="$+id:text_humi"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="数据正在采集 "
- ohos:text_color="#00ff00"
- ohos:text_size="18fp"
- ohos:left_margin="50vp"
- ohos:vertical_center="true"/>
- </DependentLayout>
- <Component
- ohos:height="2vp"
- ohos:width="match_content"
- ohos:background_element="#FFFFFF"/>
- <DependentLayout
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:background_element="#f4f5f7"
- ohos:left_padding="15vp"
- ohos:right_padding="15vp"
- ohos:top_padding="10vp"
- ohos:bottom_padding="10vp">
- <Text
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="CO2:"
- ohos:text_color="#000000"
- ohos:text_size="18fp"
- ohos:vertical_center="true"/>
- <Text
- ohos:id="$+id:text_co2"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="数据正在采集 "
- ohos:text_color="#00ff00"
- ohos:text_size="18fp"
- ohos:left_margin="50vp"
- ohos:vertical_center="true"/>
- </DependentLayout>
- </DirectionalLayout>
12. dialog_device_item.xml
- <?xml version="1.0" encoding="utf-8"?>
- <DirectionalLayout
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:height="70vp"
- ohos:width="match_parent"
- ohos:orientation="horizontal">
- <Image
- ohos:id="$+id:item_type"
- ohos:height="45vp"
- ohos:width="50vp"
- ohos:image_src="$media:dv_phone"
- ohos:layout_alignment="vertical_center"
- ohos:left_margin="10vp"
- ohos:scale_mode="inside"/>
- <Text
- ohos:id="$+id:item_name"
- ohos:height="match_parent"
- ohos:width="0vp"
- ohos:max_text_lines="1"
- ohos:text="Huawei P40"
- ohos:text_alignment="vertical_center"
- ohos:text_size="15fp"
- ohos:weight="1"/>
- <Image
- ohos:id="$+id:item_check"
- ohos:height="30vp"
- ohos:width="30vp"
- ohos:image_src="$media:uncheck2"
- <DirectionalLayout
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:height="340vp"
- ohos:width="match_parent"
- ohos:orientation="vertical">
- <DirectionalLayout
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:background_element="$graphic:background_white_radius_10"
- ohos:bottom_margin="50vp"
- ohos:left_margin="20vp"
- ohos:orientation="vertical"
- ohos:right_margin="20vp">
- <Text
- ohos:height="50vp"
- ohos:width="match_parent"
- ohos:left_padding="20vp"
- ohos:text="迁移到其他设备"
- ohos:text_alignment="vertical_center"
- ohos:text_color="#000000"
- ohos:text_size="16fp"/>
- <ListContainer
- ohos:id="$+id:list_container_device"
- ohos:height="0vp"
- ohos:width="match_parent"
- ohos:weight="1"/>
- <DirectionalLayout
- ohos:height="50vp"
- ohos:width="match_parent"
- ohos:orientation="horizontal">
- <Text
- ohos:id="$+id:operate_no"
- ohos:height="match_parent"
- ohos:width="0vp"
- ohos:text="取消"
- ohos:text_alignment="center"
- ohos:text_color="#1e90ff"
- ohos:text_size="17fp"
- ohos:weight="1"/>
- <Component
- ohos:height="25vp"
- ohos:width="1vp"
- ohos:background_element="#cccccc"
- ohos:layout_alignment="vertical_center"/>
- <Text
- ohos:id="$+id:operate_yes"
- ohos:height="match_parent"
- ohos:width="0vp"
- ohos:text="确定"
- ohos:text_alignment="center"
- ohos:text_color="#1e90ff"
- ohos:text_size="17fp"
- ohos:weight="1"/>
- </DirectionalLayout>
- </DirectionalLayout>
- </DirectionalLayout>
14. toast_dialog.xml
- <DirectionalLayout
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:orientation="vertical"
- ohos:background_element="$graphic:background_gray_circle">
- <Text
- ohos:id="$+id:toast"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:left_padding="16vp"
- ohos:right_padding="16vp"
- ohos:top_padding="4vp"
- ohos:bottom_padding="4vp"
- ohos:layout_alignment="center"
- ohos:text_size="20fp"/>
- </DirectionalLayout>
TV端
1. TVAbilitySlice
- private Text tvTemp;
- private Text tvTempMax;
- private Text tvTempMin;
- private Text tvHumi;
- private Text tvHumiMax;
- private Text tvHumiMin;
- private Text tvCgas;
- private Text tvCgasMax;
- private Text tvCgasMin;
- private Text tvTempStatus;
- private Text tvHumiStatus;
- private Text tvCgasStatus;
- private ProgressBar rgbTem;
- private ProgressBar rgbHumi;
- private ProgressBar rgbCgas;
- private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x0001, "my_log");
- private double temp;
- private double humi;
- private double cGas;
- private SingleKvStore singleKvStore;
- private KvStoreObserverClient kvStoreObserverClient;
- @Override
- public void onStart(Intent intent) {
- super.onStart(intent);
- super.setUIContent(ResourceTable.Layout_ability_tv);
- //设置沉浸式状态栏
- getWindow().addFlags(WindowManager.LayoutConfig.MARK_TRANSLUCENT_STATUS);
- tvTemp = (Text) findComponentById(ResourceTable.Id_tvTemp);
- tvTempMax = (Text) findComponentById(ResourceTable.Id_tvMaxTemp);
- tvTempMin = (Text) findComponentById(ResourceTable.Id_tvMinTemp);
- rgbTem = (RoundProgressBar) findComponentById(ResourceTable.Id_rgb_tem);
- tvHumi = (Text) findComponentById(ResourceTable.Id_tvHumi);
- tvHumiMax = (Text) findComponentById(ResourceTable.Id_tvMaxHumi);
- tvHumiMin = (Text) findComponentById(ResourceTable.Id_tvMinHumi);
- rgbHumi = (RoundProgressBar) findComponentById(ResourceTable.Id_rgb_humi);
- tvCgas = (Text) findComponentById(ResourceTable.Id_tvCgas);
- tvCgasMax = (Text) findComponentById(ResourceTable.Id_tvMaxCgas);
- tvCgasMin = (Text) findComponentById(ResourceTable.Id_tvMinCgas);
- rgbCgas = (RoundProgressBar) findComponentById(ResourceTable.Id_rgb_gas);
- tvTempStatus = (Text) findComponentById(ResourceTable.Id_tvTempStatus);
- tvHumiStatus = (Text) findComponentById(ResourceTable.Id_tvHumiStatus);
- tvCgasStatus = (Text) findComponentById(ResourceTable.Id_tvCgasStatus);
- try {
- KvManagerConfig config = new KvManagerConfig(getContext());
- KvManager kvManager = KvManagerFactory.getInstance().createKvManager(config);
- Options CREATE = new Options();
- CREATE.setCreateIfMissing(true).setEncrypt(false)
- .setKvStoreType(KvStoreType.SINGLE_VERSION)
- .setAutoSync(true);
- singleKvStore = kvManager.getKvStore(CREATE, DBUtils.KV_STORE_NAME);
- kvStoreObserverClient = new KvStoreObserverClient();
- singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL, kvStoreObserverClient);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- private class KvStoreObserverClient implements KvStoreObserver {
- @Override
- public void onChange(ChangeNotification notification) {
- //onChange方法实质上,在一个子线程里执行
- getUITaskDispatcher().asyncDispatch(() -> {
- //在这里执行页面ui组件的显示刷新
- asyncUpdateData();
- });
- }
- }
- public void asyncUpdateData(){
- //查询分布式数据的数据
- List<Entry> entries = singleKvStore.getEntries("data");
- if (entries.size() > 0) {
- ZSONObject zsonObject = ZSONObject.stringToZSON(entries.get(0).getValue().getString());
- double temp = zsonObject.getDouble("temp");
- double humi = zsonObject.getDouble("humi");
- double co2 = zsonObject.getDouble("co2");
- String strTemp = String.format("%.1f", temp);
- String strHumi = String.format("%.1f", humi);
- String strCO2 = String.format("%.1f", co2);
- initView(strTemp,strHumi,strCO2);
- }
- }
- private void initView(String strTemp,String strHumi,String strCO2) {
- temp = Double.valueOf(strTemp);
- int tempMax = 45;
- int tempMin = -10;
- humi = Double.valueOf(strHumi);
- int humiMax = 70;
- int humiMin = 10;
- cGas = Double.valueOf(strCO2);
- int cGasMax = 1000;
- if (temp > -100) {
- if (temp > tempMax || temp < tempMin) {
- tvTemp.setTextColor(Color.RED);
- tvTempStatus.setText("异常");
- tvTempStatus.setTextColor(Color.RED);
- rgbTem.setProgressColor(Color.RED);
- } else {
- tvTemp.setTextColor(Color.GREEN);
- tvTempStatus.setText("正常");
- tvTempStatus.setTextColor(Color.GREEN);
- rgbTem.setProgressColor(Color.GREEN);
- }
- } else {
- tvTemp.setTextColor(Color.BLACK);
- tvTempStatus.setTextColor(Color.BLACK);
- tvTempStatus.setText("未知");
- rgbTem.setProgressColor(Color.GREEN);
- }
- tvTempMax.setText(tempMax + "℃");
- tvTempMin.setText(tempMin + "℃");
- if (humi > -100) {
- if (humi > humiMax || humi < humiMin) {
- tvHumi.setTextColor(Color.RED);
- tvHumiStatus.setText("异常");
- tvHumiStatus.setTextColor(Color.RED);
- rgbHumi.setProgressColor(Color.RED);
- } else {
- tvHumi.setTextColor(Color.GREEN);
- tvHumiStatus.setText("正常");
- tvHumiStatus.setTextColor(Color.GREEN);
- rgbHumi.setProgressColor(Color.GREEN);
- }
- } else {
- tvHumi.setTextColor(Color.BLACK);
- tvHumiStatus.setText("未知");
- tvHumiStatus.setTextColor(Color.BLACK);
- rgbHumi.setProgressColor(Color.GREEN);
- }
- tvHumiMax.setText(humiMax + "% RH");
- tvHumiMin.setText(humiMin + "% RH");
- if (cGas > -100) {
- if (cGas > cGasMax) {
- tvCgas.setTextColor(Color.RED);
- tvCgasStatus.setText("异常");
- tvCgasStatus.setTextColor(Color.RED);
- rgbCgas.setProgressColor(Color.RED);
- } else {
- tvCgas.setTextColor(Color.GREEN);
- tvCgasStatus.setText("正常");
- tvCgasStatus.setTextColor(Color.GREEN);
- }
- } else {
- tvCgas.setTextColor(Color.BLACK);
- tvCgasStatus.setText("未知");
- tvCgasStatus.setTextColor(Color.BLACK);
- rgbCgas.setProgressColor(Color.GREEN);
- }
- tvCgasMax.setText(cGasMax + " ppm");
- tvCgasMin.setText(0 + " ppm");
- if (temp <= -100) {
- tvTemp.setText("未知");
- rgbTem.setProgressValue(0);
- } else {
- tvTemp.setText(temp + "℃");
- rgbTem.setProgressValue((int) temp);
- }
- if (humi <= -100) {
- tvHumi.setText("未知");
- rgbHumi.setProgressValue(0);
- } else {
- tvHumi.setText(humi + "% RH");
- rgbHumi.setProgressValue((int) humi);
- }
- if (cGas <= -100) {
- tvCgas.setText("未知");
- rgbCgas.setProgressValue(0);
- } else {
- tvCgas.setText(cGas + " ppm");
- rgbCgas.setProgressValue((int) cGas);
- }
- }
- @Override
- protected void onStop() {
- super.onStop();
- //解除订阅
- // if (singleKvStore != null) {
- // if(kvStoreObserverClient!=null){
- // singleKvStore.unSubscribe(kvStoreObserverClient);
- // }
- // }
- }
- }
2. TVAbility
- public class TVAbility extends Ability {
- @Override
- public void onStart(Intent intent) {
- super.onStart(intent);
- super.setMainRoute(TVAbilitySlice.class.getName());
- //实现Ability的代码中显式声明需要使用多设备协同访问的权限
- requestPermissionsFromUser(new String[]{"ohos.permission.DISTRIBUTED_DATASYNC",}, 0);
- }
- }
3. ability_tv.xml
- <?xml version="1.0" encoding="utf-8"?>
- <DirectionalLayout
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:orientation="vertical"
- ohos:background_element="$media:haibao">
- <Text
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="大棚数据监测"
- ohos:text_color="#ffffff"
- ohos:text_size="26vp"
- ohos:layout_alignment="center"
- ohos:top_margin="50vp"/>
- <DependentLayout
- ohos:height="match_parent"
- ohos:width="match_parent">
- <DirectionalLayout
- ohos:height="match_content"
- ohos:width="match_parent"
- ohos:left_padding="10vp"
- ohos:right_padding="10vp"
- ohos:center_in_parent="true"
- ohos:orientation="horizontal">
- <DirectionalLayout
- ohos:height="match_content"
- ohos:width="0"
- ohos:weight="1"
- ohos:layout_alignment="center"
- ohos:orientation="vertical">
- <Text
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="温度数据"
- ohos:text_size="20vp"
- ohos:padding="5vp"
- ohos:text_color="#ffffff"
- ohos:layout_alignment="center"/>
- <DirectionalLayout
- ohos:height="3vp"
- ohos:width="match_parent"
- ohos:background_element="#ffffff"
- ohos:top_margin="15vp"
- ohos:left_margin="20vp"
- ohos:right_margin="20vp"
- ohos:layout_alignment="center"
- ohos:bottom_margin="15vp"
- ohos:visibility="invisible"/>
- <DirectionalLayout
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:layout_alignment="center"
- ohos:orientation="horizontal">
- <DirectionalLayout
- ohos:height="match_parent"
- ohos:width="match_content"
- ohos:orientation="vertical">
- <Text
- ohos:height="0"
- ohos:width="match_content"
- ohos:text="最高温度阀值:"
- ohos:text_size="16vp"
- ohos:weight="1"
- ohos:text_color="#000000"/>
- <Text
- ohos:height="0"
- ohos:width="match_content"
- ohos:text="当前温度:"
- ohos:text_size="16vp"
- ohos:weight="1"
- ohos:text_color="#000000"/>
- <Text
- ohos:height="0"
- ohos:width="match_content"
- ohos:text="最低温度阀值:"
- ohos:text_size="16vp"
- ohos:weight="1"
- ohos:text_color="#000000"/>
- </DirectionalLayout>
- <DependentLayout
- ohos:height="100vp"
- ohos:width="100vp">
- <RoundProgressBar
- ohos:id="$+id:rgb_tem"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:progress_width="10vp"
- ohos:progress="0"
- ohos:max="100"
- ohos:start_angle="215"
- ohos:max_angle="290"
- ohos:progress_color="#00ff00"
- ohos:center_in_parent="true"/>
- <Text
- ohos:id="$+id:tvMaxTemp"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text_size="15vp"
- ohos:text_color="#000000"
- ohos:align_parent_top="true"
- ohos:text="未知"
- ohos:top_margin="8vp"
- ohos:horizontal_center="true"/>
- <Text
- ohos:id="$+id:tvTemp"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text_size="15vp"
- ohos:text_color="#000000"
- ohos:text="未知"
- ohos:center_in_parent="true"/>
- <Text
- ohos:id="$+id:tvMinTemp"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text_size="14vp"
- ohos:text_color="#000000"
- ohos:text="未知"
- ohos:bottom_margin="8vp"
- ohos:align_parent_bottom="true"
- ohos:horizontal_center="true"/>
- </DependentLayout>
- </DirectionalLayout>
- <DirectionalLayout
- ohos:height="3vp"
- ohos:width="match_parent"
- ohos:background_element="#ffffff"
- ohos:top_margin="15vp"
- ohos:left_margin="20vp"
- ohos:right_margin="20vp"
- ohos:layout_alignment="center"
- ohos:bottom_margin="15vp"
- ohos:visibility="invisible"/>
- <DirectionalLayout
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:layout_alignment="center"
- ohos:orientation="horizontal">
- <Text
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="温度状态:"
- ohos:text_size="18vp"
- ohos:text_color="#000000"/>
- <Text
- ohos:id="$+id:tvTempStatus"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="未知"
- ohos:text_size="18vp"
- ohos:text_color="#000000"/>
- </DirectionalLayout>
- </DirectionalLayout>
- <DirectionalLayout
- ohos:height="90vp"
- ohos:width="1vp"
- ohos:background_element="#000000"
- ohos:top_margin="6vp"
- ohos:layout_alignment="center"/>
- <DirectionalLayout
- ohos:height="match_content"
- ohos:width="0"
- ohos:weight="1"
- ohos:layout_alignment="center"
- ohos:orientation="vertical">
- <Text
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="湿度数据"
- ohos:text_size="20vp"
- ohos:padding="5vp"
- ohos:text_color="#ffffff"
- ohos:layout_alignment="center"/>
- <DirectionalLayout
- ohos:height="3vp"
- ohos:width="match_parent"
- ohos:background_element="#ffffff"
- ohos:top_margin="15vp"
- ohos:left_margin="20vp"
- ohos:right_margin="20vp"
- ohos:layout_alignment="center"
- ohos:bottom_margin="15vp"
- ohos:visibility="invisible"/>
- <DirectionalLayout
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:layout_alignment="center"
- ohos:orientation="horizontal">
- <DirectionalLayout
- ohos:height="match_parent"
- ohos:width="match_content"
- ohos:orientation="vertical">
- <Text
- ohos:height="0"
- ohos:width="match_content"
- ohos:text="最大湿度阀值:"
- ohos:text_size="16vp"
- ohos:weight="1"
- ohos:text_color="#000000"/>
- <Text
- ohos:height="0"
- ohos:width="match_content"
- ohos:text="当前湿度:"
- ohos:text_size="16vp"
- ohos:weight="1"
- ohos:text_color="#000000"/>
- <Text
- ohos:height="0"
- ohos:width="match_content"
- ohos:text="最小湿度阀值:"
- ohos:text_size="16vp"
- ohos:weight="1"
- ohos:text_color="#000000"/>
- </DirectionalLayout>
- <DependentLayout
- ohos:height="100vp"
- ohos:width="100vp">
- <RoundProgressBar
- ohos:id="$+id:rgb_humi"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:progress_width="10vp"
- ohos:progress="0"
- ohos:max="100"
- ohos:start_angle="215"
- ohos:max_angle="290"
- ohos:progress_color="#00ff00"
- ohos:center_in_parent="true"/>
- <Text
- ohos:id="$+id:tvMaxHumi"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text_size="15vp"
- ohos:text_color="#000000"
- ohos:text="未知"
- ohos:top_margin="8vp"
- ohos:horizontal_center="true"
- ohos:align_parent_top="true"/>
- <Text
- ohos:id="$+id:tvHumi"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text_size="15vp"
- ohos:text_color="#000000"
- ohos:text="未知"
- ohos:center_in_parent="true"/>
- <Text
- ohos:id="$+id:tvMinHumi"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text_size="15vp"
- ohos:text_color="#000000"
- ohos:horizontal_center="true"
- ohos:text="未知"
- ohos:bottom_margin="8vp"
- ohos:align_parent_bottom="true"/>
- </DependentLayout>
- </DirectionalLayout>
- <DirectionalLayout
- ohos:height="3vp"
- ohos:width="match_parent"
- ohos:background_element="#ffffff"
- ohos:top_margin="15vp"
- ohos:left_margin="20vp"
- ohos:right_margin="20vp"
- ohos:layout_alignment="center"
- ohos:bottom_margin="15vp"
- ohos:visibility="invisible"/>
- <DirectionalLayout
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:layout_alignment="center"
- ohos:orientation="horizontal">
- <Text
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="湿度状态:"
- ohos:text_size="18vp"
- ohos:text_color="#000000"/>
- <Text
- ohos:id="$+id:tvHumiStatus"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="未知"
- ohos:text_size="18vp"
- ohos:text_color="#000000"/>
- </DirectionalLayout>
- </DirectionalLayout>
- <DirectionalLayout
- ohos:height="90vp"
- ohos:width="1vp"
- ohos:background_element="#000000"
- ohos:top_margin="6vp"
- ohos:layout_alignment="center"/>
- <DirectionalLayout
- ohos:height="match_content"
- ohos:width="0"
- ohos:weight="1"
- ohos:layout_alignment="center"
- ohos:orientation="vertical">
- <Text
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="CO2数据"
- ohos:text_size="20vp"
- ohos:padding="5vp"
- ohos:text_color="#ffffff"
- ohos:layout_alignment="center"/>
- <DirectionalLayout
- ohos:height="3vp"
- ohos:width="match_parent"
- ohos:background_element="#ffffff"
- ohos:top_margin="15vp"
- ohos:left_margin="20vp"
- ohos:right_margin="20vp"
- ohos:layout_alignment="center"
- ohos:bottom_margin="15vp"
- ohos:visibility="invisible"/>
- <DirectionalLayout
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:layout_alignment="center"
- ohos:orientation="horizontal">
- <DirectionalLayout
- ohos:height="match_parent"
- ohos:width="match_content"
- ohos:orientation="vertical">
- <Text
- ohos:height="0"
- ohos:width="match_content"
- ohos:text="最大气体增量:"
- ohos:text_size="16vp"
- ohos:weight="1"
- ohos:text_color="#000000"/>
- <Text
- ohos:height="0"
- ohos:width="match_content"
- ohos:text="当前增量:"
- ohos:text_size="16vp"
- ohos:weight="1"
- ohos:text_color="#000000"/>
- <Text
- ohos:height="0"
- ohos:width="match_content"
- ohos:text="最小气体增量:"
- ohos:text_size="16vp"
- ohos:weight="1"
- ohos:text_color="#000000"/>
- </DirectionalLayout>
- <DependentLayout
- ohos:height="100vp"
- ohos:width="100vp">
- <RoundProgressBar
- ohos:id="$+id:rgb_gas"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:progress_width="10vp"
- ohos:progress="0"
- ohos:max="1000"
- ohos:start_angle="215"
- ohos:max_angle="290"
- ohos:progress_color="#00ff00"
- ohos:center_in_parent="true"/>
- <Text
- ohos:id="$+id:tvMaxCgas"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text_size="15vp"
- ohos:text="未知"
- ohos:text_color="#000000"
- ohos:top_margin="8vp"
- ohos:horizontal_center="true"
- ohos:align_parent_top="true"/>
- <Text
- ohos:id="$+id:tvCgas"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text_size="15vp"
- ohos:text="未知"
- ohos:text_color="#000000"
- ohos:center_in_parent="true"/>
- <Text
- ohos:id="$+id:tvMinCgas"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text_size="15vp"
- ohos:text="未知"
- ohos:text_color="#000000"
- ohos:bottom_margin="8vp"
- ohos:horizontal_center="true"
- ohos:align_parent_bottom="true"/>
- </DependentLayout>
- </DirectionalLayout>
- <DirectionalLayout
- ohos:height="3vp"
- ohos:width="match_parent"
- ohos:background_element="#ffffff"
- ohos:top_margin="15vp"
- ohos:left_margin="20vp"
- ohos:right_margin="20vp"
- ohos:layout_alignment="center"
- ohos:bottom_margin="15vp"
- ohos:visibility="invisible"/>
- <DirectionalLayout
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:layout_alignment="center"
- ohos:orientation="horizontal">
- <Text
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="气体状态:"
- ohos:text_size="18vp"
- ohos:text_color="#000000"/>
- <Text
- ohos:id="$+id:tvCgasStatus"
- ohos:height="match_content"
- ohos:width="match_content"
- ohos:text="未知"
- ohos:text_size="18vp"
- ohos:text_color="#000000"/>
- </DirectionalLayout>
- </DirectionalLayout>
- </DirectionalLayout>
- </DependentLayout>
- </DirectionalLayout>
4.config.json
- {
- "app": {
- "bundleName": "com.isoftstone. distributeddata ",
- "vendor": "isoftstone",
- "version": {
- "code": 1000000,
- "name": "1.0.0"
- }
- },
- "deviceConfig": {},
- "module": {
- "package": "com.isoftstone.distributeddata",
- "name": ".MyApplication",
- "mainAbility": "com.isoftstone.distributeddata.com.isoftstone.distributeddata.TVAbility",
- "deviceType": [
- "phone"
- ],
- "distro": {
- "deliveryWithInstall": true,
- "moduleName": "entry",
- "moduleType": "entry",
- "installationFree": false
- },
- "reqPermissions": [
- {
- "name": "ohos.permission.DISTRIBUTED_DATASYNC"
- }
- ],
- "abilities": [
- {
- "skills": [
- {
- "entities": [
- "entity.system.home"
- ],
- "actions": [
- "action.system.home"
- ]
- }
- ],
- "orientation": "landscape",
- "name": "com.isoftstone.distributeddata.TVAbility",
- "icon": "$media:icon",
- "description": "$string:tvability_description",
- "label": "$string:entry_TVAbility",
- "type": "page",
- "launchType": "standard"
- }
- ],
- "metaData": {
- "customizeData": [
- {
- "name": "hwc-theme",
- "value": "androidhwext:style/Theme.Emui.NoTitleBar",
- "extra": ""
- }
- ]
- }
- }
- }