HarmonyOS分布式應(yīng)用智能三角警示牌解讀
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
前言
HarmonyOS是 一款面向萬(wàn)物互聯(lián)時(shí)代的、全新的分布式操作系統(tǒng),其分布式技術(shù)能力(分布式軟總線、分布式設(shè)備虛擬化、分布式數(shù)據(jù)管理、分布式任務(wù)調(diào)度)一直受到廣大開(kāi)發(fā)者的極大關(guān)注,使用戶對(duì)HarmonyOS有著很高的贊許。
我們開(kāi)發(fā)的《分布式智能三角警示牌應(yīng)用》,以在日常生活中,公路上發(fā)生交通事故時(shí)通常是事故相關(guān)人員手持三角反光警示牌步行至目的地處放置,人為放置具有引發(fā)二次事故的風(fēng)險(xiǎn),因此我們?cè)O(shè)計(jì)了智能移動(dòng)三角警示牌以解決該問(wèn)題。本智能三角警示牌通過(guò)手機(jī)HAP可以與其相連,控制運(yùn)動(dòng)方向和速度,使其停放在事故現(xiàn)場(chǎng)后方合適的位置,從而能夠保障用戶的人身和財(cái)產(chǎn)安全。
當(dāng)在控制警示牌運(yùn)動(dòng)過(guò)程中,有緊急事情或其它情況,可以將當(dāng)前的操作流轉(zhuǎn)到另外一臺(tái)設(shè)備中進(jìn)行操作,其運(yùn)動(dòng)軌跡就是通過(guò)分布式數(shù)據(jù)服務(wù)來(lái)保證兩臺(tái)設(shè)備間數(shù)據(jù)的一致性。
效果展示


一、創(chuàng)建“智能三角警示牌”HAP工程
1、安裝和配置DevEco Studio
2.1 Release
安裝的鏈接:https://developer.harmonyos.com/cn/develop/deveco-studio
IDE的使用指南,很詳細(xì):https://developer.harmonyos.com/cn/docs/documentation/doc-guides/tools_overview-0000001053582387
我的本案例使用的最新的 2.1.0.501版本,SDK:API Version 5
2、選擇一個(gè)模版,創(chuàng)建一個(gè)Java Phone應(yīng)用

==點(diǎn)擊Next ==

點(diǎn)擊Finish完成創(chuàng)建HAP工程
3、智能三角警示牌應(yīng)用包結(jié)構(gòu)
首先完成智能三角警示牌應(yīng)用包結(jié)構(gòu)設(shè)計(jì),結(jié)構(gòu)如下:

二、智能三角警示牌應(yīng)用核心代碼實(shí)現(xiàn)
1、config.json權(quán)限配置
- "reqPermissions": [
- {
- "name": "ohos.permission.INTERNET"
- },
- {
- "name": "ohos.permission.GET_NETWORK_INFO"
- },
- {
- "name": "ohos.permission.MICROPHONE"
- },
- {
- "name": "android.permission.RECORD_AUDIO"
- },
- {
- "name": "ohos.permission.DISTRIBUTED_DATASYNC"
- },
- {
- "name": "ohos.permission.servicebus.ACCESS_SERVICE"
- },
- {
- "name": "com.huawei.hwddmp.servicebus.BIND_SERVICE"
- },
- {
- "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE"
- },
- {
- "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"
- },
- {
- "name": "ohos.permission.GET_BUNDLE_INFO"
- },
- {
- "name": "ohos.p
- ermission.LOCATION"
- }
- ]
2、分布式數(shù)據(jù)服務(wù)核心代碼
- import com.google.gson.Gson;
- import com.google.gson.reflect.TypeToken;
- import com.isoftstone.smartcar.app.common.Constant;
- import com.isoftstone.smartcar.app.model.DrivingMap;
- import com.isoftstone.smartcar.app.model.DrivingRecord;
- import com.isoftstone.smartcar.app.model.ReportRecord;
- import com.isoftstone.smartcar.app.utils.DrivingReportComparator;
- import com.isoftstone.smartcar.app.utils.ReportRecordComparator;
- import com.isoftstone.smartcar.app.utils.StringUtils;
- import ohos.app.Context;
- import ohos.data.distributed.common.*;
- import ohos.data.distributed.device.DeviceFilterStrategy;
- import ohos.data.distributed.device.DeviceInfo;
- import ohos.data.distributed.user.SingleKvStore;
- import ohos.hiviewdfx.HiLog;
- import ohos.hiviewdfx.HiLogLabel;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * 分布式數(shù)據(jù)庫(kù)類(lèi)服務(wù)
- */
- public class SmartShareService {
- private static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00201, "SmartshareService");
- private static SmartShareService smartShareService;
- private static SingleKvStore singleKvStore;
- private static KvManager kvManager;
- private final Context context;
- public static SmartShareService getInstance(Context context) {
- if (smartShareService == null) {
- smartShareService = new SmartShareService(context);
- }
- return smartShareService;
- }
- private SmartShareService(Context context){
- this.context = context;
- }
- /**
- * 分布式數(shù)據(jù)庫(kù)初始化
- */
- public void init() {
- KvManagerConfig config = new KvManagerConfig(context);
- kvManager = KvManagerFactory.getInstance().createKvManager(config);
- Options options = new Options(); options.setCreateIfMissing(true).setEncrypt(false).setKvStoreType(KvStoreType.SINGLE_VERSION).setAutoSync(true);
- singleKvStore = kvManager.getKvStore(options, Constant.SMART_SHARE_NAME);
- HiLog.info(label,"初始化成功!");
- //return singleKvStore;
- }
- /**
- * 新增行駛記錄
- * @param drivingRecord 行駛記錄對(duì)象
- */
- public void insertDrivingRecord(DrivingRecord drivingRecord){
- Gson gson = new Gson();
- String resultJson = gson.toJson(drivingRecord); singleKvStore.putString(Constant.DRIVING_REPORT_PREFIX+drivingRecord.getId(),resultJson);
- HiLog.info(label,"新增行駛記錄成功!");
- }
- /**
- * 批量新增行駛記錄軌跡
- * @param drivingId 行駛記錄標(biāo)識(shí)
- * @param drivingMapLst 行駛記錄軌跡列表
- */
- public void insertDrivingMap(String drivingId, List<DrivingMap> drivingMapLst){
- Gson gson = new Gson();
- String resultJson = gson.toJson(drivingMapLst); singleKvStore.putString(Constant.DRIVING_MAP_PREFIX+drivingId,resultJson);
- HiLog.info(label,"批量新增行駛記錄軌跡成功!");
- }
- /**
- * 新增上報(bào)記錄
- * @param drivingId 行駛記錄標(biāo)識(shí)
- * @param reportRecord 上報(bào)記錄對(duì)象
- */
- public void insertReportRecord(String drivingId, ReportRecord reportRecord){
- Gson gson = new Gson();
- List<Entry> entrys = singleKvStore.getEntries(Constant.REPORT_RECORD_PREFIX+drivingId);
- if (entrys == null || entrys.size() == 0){
- List<ReportRecord> reportRecordLst = new ArrayList<>();
- reportRecordLst.add(reportRecord);
- String resultJson1 = gson.toJson(reportRecordLst); singleKvStore.putString(Constant.REPORT_RECORD_PREFIX+drivingId,resultJson1);
- HiLog.info(label,"新增上報(bào)記錄成功!");
- } else {
- String resultJson = entrys.get(0).getValue().getString();
- List<ReportRecord> reportRecordLst = gson.fromJson(resultJson, new TypeToken<List<ReportRecord>>() {}.getType());
- reportRecordLst.add(reportRecord);
- String resultJson1 = gson.toJson(reportRecordLst);
- singleKvStore.putString(Constant.REPORT_RECORD_PREFIX+drivingId,resultJson1);
- HiLog.info(label,"新增上報(bào)記錄列表成功!");
- }
- }
- /**
- * 設(shè)置保險(xiǎn)電話
- * @param key 保險(xiǎn)key
- * @param telphone 保險(xiǎn)key對(duì)應(yīng)的值
- */
- public void setupInsuranceTelphone(String key,String telphone){
- singleKvStore.putString(Constant.TEL_PREFIX+key,telphone);
- HiLog.info(label,"設(shè)置保險(xiǎn)電話成功!");
- }
- /**
- * 獲取保險(xiǎn)電話
- * @param key 保險(xiǎn)電話key
- * @return 保險(xiǎn)電話
- */
- public String getInsuranceTelphone(String key){
- String tel = "";
- List<Entry> entrys = singleKvStore.getEntries(Constant.TEL_PREFIX+key);
- if (entrys != null && entrys.size()>0) {
- tel = entrys.get(0).getValue().getString();
- HiLog.info(label,"獲取保險(xiǎn)電話成功!"+tel);
- } else {
- HiLog.info(label,"沒(méi)有獲取保險(xiǎn)電話!");
- }
- return tel;
- }
- /**
- * 設(shè)置IP
- * @param key IP的key
- * @param value IP的value
- */
- public void setIp(String key,String value){
- singleKvStore.putString(Constant.IP_PREFIX+key,value);
- HiLog.info(label,"設(shè)置IP成功!");
- }
- /**
- * 獲取IP
- * @param key IP的key
- * @return IP的值
- */
- public String getIp(String key){
- String tmpIp = "";
- List<Entry> entrys = singleKvStore.getEntries(Constant.IP_PREFIX+key);
- if (entrys != null && entrys.size()>0) {
- tmpIp = entrys.get(0).getValue().getString();
- HiLog.info(label,"獲取IP成功!"+tmpIp);
- } else {
- HiLog.info(label,"沒(méi)有獲取到IP!");
- }
- return tmpIp;
- }
- /**
- * 獲取行駛記錄列表
- * @return 行駛記錄列表
- */
- public List<DrivingRecord> getDrivingRecords(){
- List<DrivingRecord> drivingReporList = new ArrayList<>();
- List<Entry> entrys = singleKvStore.getEntries(Constant.DRIVING_REPORT_PREFIX);
- for(Entry entry:entrys){
- String key = entry.getKey();
- String value = entry.getValue().getString();
- HiLog.info(label,"獲取到行駛記錄的數(shù)據(jù):key:" + key+",value:"+value);
- Gson gson = new Gson();
- DrivingRecord drivingRecord = gson.fromJson(value, DrivingRecord.class);
- //HiLog.info(label,drivingRecord.getId());
- drivingReporList.add(drivingRecord);
- }
- //排序
- if (drivingReporList.size() > 0) {
- DrivingReportComparator drivingReportComparator = new DrivingReportComparator();
- drivingReporList.sort(drivingReportComparator);
- }
- return drivingReporList;
- }
- /**
- * 獲取行駛記錄軌跡列表
- * @param drivingId 行駛記錄標(biāo)識(shí)
- * @return 行駛記錄軌跡列表
- */
- public List<DrivingMap> getDrivingMap(String drivingId){
- String resultJson = singleKvStore.getString(Constant.DRIVING_MAP_PREFIX+drivingId);
- Gson gson = new Gson();
- return gson.fromJson(resultJson, new TypeToken<List<DrivingMap>>() {}.getType());
- }
- /**
- * 獲取上報(bào)記錄列表
- * @param drivingId 行駛記錄標(biāo)識(shí)
- * @return 上報(bào)記錄列表
- */
- public List<ReportRecord> getReportRecords(String drivingId){
- List<Entry> entrys = singleKvStore.getEntries(Constant.REPORT_RECORD_PREFIX+drivingId);
- if (entrys == null || entrys.size() == 0){
- HiLog.info(label,"獲取上報(bào)記錄為空!");
- return null;
- } else {
- Gson gson = new Gson();
- Entry entry = entrys.get(0);
- String resultJson = entry.getValue().getString();
- List<ReportRecord> reportRecordLst = gson.fromJson(resultJson, new TypeToken<List<ReportRecord>>() {}.getType());
- HiLog.info(label,"獲取上報(bào)記錄成功!"+reportRecordLst.size());
- if (reportRecordLst!=null && reportRecordLst.size() > 0) {
- //排序
- ReportRecordComparator reportRecordComparator = new ReportRecordComparator();
- reportRecordLst.sort(reportRecordComparator);
- }
- return reportRecordLst;
- }
- }
- /**
- * 同步數(shù)據(jù)
- */
- public void syncData() {
- List<DeviceInfo> deviceInfoList = kvManager.getConnectedDevicesInfo(DeviceFilterStrategy.NO_FILTER);
- List<String> deviceIdList = new ArrayList<>();
- String deviceId;
- for (DeviceInfo deviceInfo : deviceInfoList) {
- deviceId = deviceInfo.getId();
- HiLog.info(label,"deviceId = " + deviceId);
- deviceIdList.add(deviceId);
- }
- HiLog.info(label,"deviceIdList.size() = " + deviceIdList.size());
- if (deviceIdList.size() > 0) {
- singleKvStore.sync(deviceIdList, SyncMode.PUSH_ONLY);
- } else {
- HiLog.error(label,"沒(méi)有共享設(shè)備");
- }
- }
- /**
- * 注冊(cè)回調(diào)接口
- * @param kvStoreObserver kvStore對(duì)象
- */
- public void registerCallback(KvStoreObserver kvStoreObserver) {
- singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL, kvStoreObserver);
- }
- /**
- * 清空數(shù)據(jù)
- */
- public void clearAllData() {
- List<Entry> entrys = singleKvStore.getEntries("");
- if (entrys!=null && entrys.size()>0){
- for(Entry entry:entrys){
- singleKvStore.delete(entry.getKey());
- }
- HiLog.info(label,"清空數(shù)據(jù)成功");
- } else {
- HiLog.info(label,"沒(méi)有數(shù)據(jù)要清空");
- }
- }
- /**
- * 從現(xiàn)有的行駛記錄中獲取drivingId
- * @return 返回行駛記錄標(biāo)識(shí)
- */
- public String getDrivingId(){
- String drivingId = "";
- List<Entry> entrys = singleKvStore.getEntries(Constant.DRIVING_REPORT_PREFIX);
- if (entrys != null && entrys.size() > 0){
- List<DrivingRecord> drivingReporList = new ArrayList<>();
- for(Entry entry:entrys){
- String value = entry.getValue().getString();
- Gson gson = new Gson();
- DrivingRecord drivingRecord = gson.fromJson(value, DrivingRecord.class);
- String dateStr = drivingRecord.getDrivingDate();
- if (StringUtils.isDiffHour(dateStr)){
- drivingReporList.add(drivingRecord);
- }
- HiLog.info(label,drivingRecord.getId());
- drivingReporList.add(drivingRecord);
- }
- if (drivingReporList.size() > 0) {
- //排序
- DrivingReportComparator drivingReportComparator = new DrivingReportComparator();
- drivingReporList.sort(drivingReportComparator);
- drivingId = drivingReporList.get(0).getId();
- HiLog.info(label,"找到符合條件的drivingId:"+drivingId);
- } else {
- HiLog.info(label,"沒(méi)有找到符合條件的drivingId");
- }
- } else {
- HiLog.info(label,"行駛記錄為空,沒(méi)有找到符合條件的drivingId");
- }
- return drivingId;
- }
- }
3、行駛記錄代碼
- import com.isoftstone.smartcar.app.ResourceTable;
- import com.isoftstone.smartcar.app.model.DrivingRecord;
- import com.isoftstone.smartcar.app.provider.DrivingRecordProvider;
- import com.isoftstone.smartcar.app.service.SmartShareService;
- import ohos.aafwk.ability.AbilitySlice;
- import ohos.aafwk.content.Intent;
- import ohos.aafwk.content.Operation;
- import ohos.agp.components.Component;
- import ohos.agp.components.Image;
- import ohos.agp.components.ListContainer;
- import java.util.List;
- /**
- * 行駛記錄
- */
- public class DrivingRecordsAbilitySlice extends AbilitySlice implements Component.ClickedListener {
- private ListContainer lcRecords;
- private SmartShareService shareService;
- private List<DrivingRecord> drivingRecordList;
- private DrivingRecordProvider drivingRecordProvider;
- @Override
- public void onStart(Intent intent) {
- super.onStart(intent);
- super.setUIContent(ResourceTable.Layout_ability_driving_records);
- initUI();
- }
- private void initUI() {
- shareService = SmartShareService.getInstance(this);
- shareService.init();
- Image iBack = (Image) findComponentById(ResourceTable.Id_i_back);
- iBack.setClickedListener(this);
- lcRecords = (ListContainer) findComponentById(ResourceTable.Id_lc_records);
- drivingRecordList = getData();
- drivingRecordProvider = new DrivingRecordProvider(drivingRecordList, this);
- lcRecords.setItemProvider(drivingRecordProvider);
- lcRecords.setItemClickedListener(new ListContainer.ItemClickedListener() {
- @Override
- public void onItemClicked(ListContainer listContainer, Component component, int i, long l) {
- Intent intent = new Intent();
- DrivingRecord drivingRecord = (DrivingRecord) drivingRecordProvider.getItem(i);
- intent.setParam("drivingId", drivingRecord.getId());
- intent.setParam("lat", drivingRecord.getLatitude());
- intent.setParam("lng", drivingRecord.getLongitude());
- Operation operation = new Intent.OperationBuilder()
- .withDeviceId("")
- .withBundleName("com.isoftstone.smartcar.app")
- .withAbilityName("com.isoftstone.smartcar.app.DrivingRecordsDetailAbility")
- .build();
- intent.setOperation(operation);
- startAbility(intent);
- //terminate();
- }
- });
- }
- @Override
- public void onActive() {
- super.onActive();
- drivingRecordList = getData();
- drivingRecordProvider = new DrivingRecordProvider(drivingRecordList, this);
- lcRecords.setItemProvider(drivingRecordProvider);
- }
- @Override
- public void onForeground(Intent intent) {
- super.onForeground(intent);
- }
- @Override
- public void onClick(Component component) {
- if (component.getId() == ResourceTable.Id_i_back) {
- terminateAbility();
- }
- }
- private List<DrivingRecord> getData() {
- return shareService.getDrivingRecords();
- }
- }
4、行駛記錄詳情代碼
- import com.isoftstone.smartcar.app.ResourceTable;
- import com.isoftstone.smartcar.app.model.DrivingMap;
- import com.isoftstone.smartcar.app.model.ReportRecord;
- import com.isoftstone.smartcar.app.provider.ReportRecordProvider;
- import com.isoftstone.smartcar.app.service.SmartShareService;
- import com.isoftstone.smartcar.app.utils.CoordinateConverter;
- import com.isoftstone.smartcar.app.widget.carmap.LatLng;
- import com.isoftstone.smartcar.app.widget.carmap.TinyMap;
- import ohos.aafwk.ability.AbilitySlice;
- import ohos.aafwk.content.Intent;
- import ohos.agp.components.Component;
- import ohos.agp.components.Image;
- import ohos.agp.components.ListContainer;
- import ohos.agp.utils.Point;
- import ohos.hiviewdfx.HiLog;
- import ohos.hiviewdfx.HiLogLabel;
- import ohos.multimodalinput.event.KeyEvent;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Timer;
- import java.util.TimerTask;
- /**
- * 行駛記錄詳情
- */
- public class DrivingRecordsDetailAbilitySlice extends AbilitySlice implements Component.ClickedListener {
- private static final HiLogLabel logLabel = new HiLogLabel(HiLog.LOG_APP, 0x00100, "DrivingRecordsDetailAbilitySlice");
- private TinyMap map;
- private String drivingId;
- private SmartShareService shareService;
- @Override
- protected void onStart(Intent intent) {
- super.onStart(intent);
- super.setUIContent(ResourceTable.Layout_ability_driving_records_detail);
- initUI(intent);
- }
- private void initUI(Intent intent) {
- Image iBack = (Image) findComponentById(ResourceTable.Id_i_back);
- iBack.setClickedListener(this);
- map = (TinyMap) findComponentById(ResourceTable.Id_map);
- ListContainer reportListContainer = (ListContainer) findComponentById(ResourceTable.Id_report_records);
- drivingId = intent.getStringParam("drivingId");
- shareService = SmartShareService.getInstance(this);
- shareService.init();
- new Timer().schedule(new TimerTask() {
- @Override
- public void run() {
- getUITaskDispatcher().asyncDispatch(new Runnable() {
- @Override
- public void run() {
- setMap();
- }
- });
- }
- },500);
- List<ReportRecord> reportRecords = shareService.getReportRecords(drivingId);
- ReportRecordProvider reportRecordProvider = new ReportRecordProvider(reportRecords, this);
- reportListContainer.setItemProvider(reportRecordProvider);
- }
- @Override
- public void onClick(Component component) {
- if (component.getId() == ResourceTable.Id_i_back) {//present(new DrivingRecordsAbilitySlice(), new Intent());
- terminate();
- }
- }
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent keyEvent) {
- HiLog.error(logLabel,keyEvent.getKeyCode()+"");
- if (keyCode==KeyEvent.KEY_BACK){
- //present(new DrivingRecordsAbilitySlice(), new Intent());
- terminate();
- return true;
- }
- return super.onKeyDown(keyCode, keyEvent);
- }
- private LatLng WGS84ToMercator(LatLng latLng) {
- return CoordinateConverter.WGS84ToMercator(latLng.getLng(), latLng.getLat());
- }
- private void setMap() {
- map.initMap();
- List<DrivingMap> drivingMaps = shareService.getDrivingMap(drivingId);
- LatLng startLatLng0 = new LatLng(Double.parseDouble(drivingMaps.get(0).getLatitude()), Double.parseDouble(drivingMaps.get(0).getLongitude()));
- LatLng startLatLng = new LatLng((float) WGS84ToMercator(startLatLng0).getLat(), (float) WGS84ToMercator(startLatLng0).getLng());
- map.setCenterPoint((float) startLatLng.getLng(), (float) startLatLng.getLat());
- LatLng endLatLng0 = new LatLng(Double.parseDouble(drivingMaps.get(drivingMaps.size() - 1).getLatitude()), Double.parseDouble(drivingMaps.get(drivingMaps.size() - 1).getLongitude()));
- LatLng endLatLng = new LatLng((float) WGS84ToMercator(endLatLng0).getLat(), (float) WGS84ToMercator(endLatLng0).getLng());
- map.setStartElement((float) startLatLng.getLng(), (float) startLatLng.getLat(), ResourceTable.Media_start_location);
- map.setEndElement((float) endLatLng.getLng(), (float) endLatLng.getLat(), ResourceTable.Media_end_location);
- List<LatLng> latLngs = new ArrayList<>();
- for (DrivingMap drivingMap : drivingMaps) {
- LatLng latLng = new LatLng(Double.parseDouble(drivingMap.getLatitude()), Double.parseDouble(drivingMap.getLongitude()));
- Point p = new Point((float) WGS84ToMercator(latLng).getLng(), (float) WGS84ToMercator(latLng).getLat());
- latLngs.add(new LatLng(p.getPointY(), p.getPointX()));
- }
- map.setPaths(latLngs);
- }
- }
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)