#星光计划2.0#HarmonyOS分布式应用农业大棚数据监测解读 原创 精华
软通动力HOS
发布于 2021-12-13 11:34
浏览
9收藏
【本文正在参与51CTO HarmonyOS技术社区创作者激励计划-星光计划2.0】
引言
分布式数据服务(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"
ohos:layout_alignment="vertical_center"
ohos:right_margin="15vp"/>
</DirectionalLayout>
13.dialog_layout_device.xml
<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": ""
}
]
}
}
}
更多原创内容请关注:软通动力HarmonyOS学院
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
标签
已于2021-12-13 11:34:53修改
赞
11
收藏 9
回复
相关推荐
厉害呀,有具体试点没有,想去参观一下。
大赛获奖项目!
感谢分享
感谢分享,就贼细节
那必须的!
感谢分享!!!
谢谢支持