#星光计划2.0#HarmonyOS分布式应用智能三角警示牌解读 原创 精华

软通动力HOS
发布于 2021-12-9 10:28
浏览
9收藏

【本文正在参与51CTO HarmonyOS技术社区创作者激励计划-星光计划2.0】

#星光计划2.0#HarmonyOS分布式应用智能三角警示牌解读-鸿蒙开发者社区

前言

HarmonyOS是 一款面向万物互联时代的、全新的分布式操作系统,其分布式技术能力(分布式软总线、分布式设备虚拟化、分布式数据管理、分布式任务调度)一直受到广大开发者的极大关注,使用户对HarmonyOS有着很高的赞许。
我们开发的《分布式智能三角警示牌应用》,以在日常生活中,公路上发生交通事故时通常是事故相关人员手持三角反光警示牌步行至目的地处放置,人为放置具有引发二次事故的风险,因此我们设计了智能移动三角警示牌以解决该问题。本智能三角警示牌通过手机HAP可以与其相连,控制运动方向和速度,使其停放在事故现场后方合适的位置,从而能够保障用户的人身和财产安全。
当在控制警示牌运动过程中,有紧急事情或其它情况,可以将当前的操作流转到另外一台设备中进行操作,其运动轨迹就是通过分布式数据服务来保证两台设备间数据的一致性。

效果展示

#星光计划2.0#HarmonyOS分布式应用智能三角警示牌解读-鸿蒙开发者社区
#星光计划2.0#HarmonyOS分布式应用智能三角警示牌解读-鸿蒙开发者社区

一、创建“智能三角警示牌”HAP工程

1、安装和配置DevEco Studio 2.1 Release

安装的链接:https://developer.harmonyos.com/cn/develop/deveco-studio
 IDE的使用指南,很详细:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/tools_overview-0000001053582387
我的本案例使用的最新的 2.1.0.501版本,SDK:API Version 5

2、选择一个模版,创建一个Java Phone应用

#星光计划2.0#HarmonyOS分布式应用智能三角警示牌解读-鸿蒙开发者社区
==点击Next ==
#星光计划2.0#HarmonyOS分布式应用智能三角警示牌解读-鸿蒙开发者社区
点击Finish完成创建HAP工程

3、智能三角警示牌应用包结构

首先完成智能三角警示牌应用包结构设计,结构如下:
#星光计划2.0#HarmonyOS分布式应用智能三角警示牌解读-鸿蒙开发者社区

包结构 说明
com.isoft.smartcar.app 应用的核心类
com.isoft.smartcar.app.base 应用中使用的基本接口
com.isoft.smartcar.app.common 应用中使用的公共类
com.isoft.smartcar.app.fraction 应用中使用的核心fraction类
com.isoft.smartcar.app.service 应用中服务使用的服务类
com.isoft.smartcar.app.model 应用中使用的model类
com.isoft.smartcar.app.soundcontrol 应用中使用的语音控制核心类
com.isoft.smartcar.app.widget 应用中使用的地图核心类
com.isoft.smartcar.app.wifimanager 应用中使用的wifi通信核心类
com.isoft.smartcar.app.utils 应用中使用的工具类

二、智能三角警示牌应用核心代码实现

1、config.json权限配置

"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、分布式数据服务核心代码


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;
/**
 * 分布式数据库类服务
 */
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;
    }
    /**
     * 分布式数据库初始化
     */
    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 行驶记录对象
     */
    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 行驶记录标识
     * @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,"批量新增行驶记录轨迹成功!");
    }
    /**
     * 新增上报记录
     * @param drivingId 行驶记录标识
     * @param reportRecord 上报记录对象
     */
    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,"新增上报记录成功!");
        } 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,"新增上报记录列表成功!");
        }
    }
    /**
     * 设置保险电话
     * @param key       保险key
     * @param telphone  保险key对应的值
     */
    public void setupInsuranceTelphone(String key,String telphone){
        singleKvStore.putString(Constant.TEL_PREFIX+key,telphone);
        HiLog.info(label,"设置保险电话成功!");
    }
    /**
     * 获取保险电话
     * @param key 保险电话key
     * @return 保险电话
     */
    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,"获取保险电话成功!"+tel);
        } else {
            HiLog.info(label,"没有获取保险电话!");
        }
        return tel;
    }
    /**
     * 设置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,"设置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,"没有获取到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,"获取到行驶记录的数据: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 行驶记录标识
     * @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());
    }
    /**
     * 获取上报记录列表
     * @param drivingId 行驶记录标识
     * @return 上报记录列表
     */
    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,"获取上报记录为空!");
            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,"获取上报记录成功!"+reportRecordLst.size());

            if (reportRecordLst!=null && reportRecordLst.size() > 0) {
                //排序
                ReportRecordComparator reportRecordComparator = new ReportRecordComparator();
                reportRecordLst.sort(reportRecordComparator);
            }
            return reportRecordLst;
        }
    }
    /**
     * 同步数据
     */
    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,"没有共享设备");
        }
    }
    /**
     * 注册回调接口
     * @param kvStoreObserver  kvStore对象
     */
    public void registerCallback(KvStoreObserver kvStoreObserver) {
        singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL, kvStoreObserver);
    }
    /**
     * 清空数据
     */
    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,"清空数据成功");
        } else {
            HiLog.info(label,"没有数据要清空");
        }
    }
    /**
     * 从现有的行驶记录中获取drivingId
     * @return 返回行驶记录标识
     */
    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,"没有找到符合条件的drivingId");
            }
        } else {
            HiLog.info(label,"行驶记录为空,没有找到符合条件的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);
    }
}


更多原创内容请关注:软通动力HarmonyOS学院

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
已于2021-12-9 10:28:16修改
10
收藏 9
回复
举报
6条回复
按时间正序
/
按时间倒序
软通田可辉
软通田可辉

软通的小伙伴们加油!

回复
2021-12-9 11:45:10
软通张二龙
软通张二龙

赞一个!

回复
2021-12-9 14:16:18
粉粉gg
粉粉gg

啥时候发个小车呀

回复
2021-12-9 14:23:43
芳芳爱学习
芳芳爱学习

赞一个!

回复
2021-12-9 15:03:30
李皓6222
李皓6222

是那个获得三等奖的《智能三角警示牌》吗?

回复
2021-12-11 13:49:19
软通动力HOS
软通动力HOS 回复了 李皓6222
是那个获得三等奖的《智能三角警示牌》吗?

对的哦

回复
2021-12-13 09:04:20
回复
    相关推荐