PDA/Android数据离线同步数据实现

一、运行截图

二、实现原理

简易图,用画图随手画了一个,正规的还是推荐大家思考的时候使用PDM,接口序列图来描述实现过程。

实现步骤:

  1. 调用业务数据接口获取基础业务数据
  2. 将获取的业务数据存储为json格式文件
  3. 将json数据文件推送至PDA或Android设备固定目录
  4. 获取PDA指定目录或者android设备中产生的业务数据
  5. 调用业务数据接口上传json文件数据或者音视频图像资料

限制条件:

  1. 目前程序运用场景:离线PDA数据同步
  2. 目前程序内调用android设备使用adb(安卓调试桥)
  3. 程序运行依赖jre环境

三、配置文件及文件结构

四、核心代码实现

4.1操作程序界面

package com.jsonliu.rest;

import com.jsonliu.config.PropertiesConf;
import com.jsonliu.service.PdaOperateDao;
import com.jsonliu.service.SafeServerDao;
import com.jsonliu.service.impl.PdaOperateDaoImpl;
import com.jsonliu.service.impl.SafeServerDaoImpl;

import java.io.IOException;
import java.util.Properties;
import java.util.Scanner;

public class OperateFile {
    private static Properties properties = null;
    private static PropertiesConf conf=null;

    private static PdaOperateDao pdaOperateDao = null;

    private static SafeServerDao safeServerDao = null;

    private static Scanner scanner = new Scanner(System.in);

    private static String token = "";

    public static void main(String[] args) throws IOException {
        //加载配置文件
        properties = PropertiesConf.getInstance().getProp();
        conf = PropertiesConf.getInstance();
        switch (properties.getProperty("env")) {
            case "1"://不能与服务相连
            {
                //加载配置文件
                if (!initPda()) return;
                //选择操作菜单
                menuPda();
            }
            break;
            case "2"://与服务同一网络(不可连接PDA)
            {
                //登录服务获取token
                if (!initSafe()) return;
                //选择操作菜单
                menuServer();
            }
            break;
            case "3"://与服务同一网络(可以连接PDA)
            {
                //加载配置文件
                if (!initPda()) return;
                //登录服务获取token
                if (!initSafe()) return;
                //选择操作菜单
                menuAll();
            }
            break;
            default:
                break;
        }

    }

    /**
     * 初始化PDA
     *
     * @return
     */
    private static boolean initPda() {
        //加载PDA文件
        pdaOperateDao = new PdaOperateDaoImpl();
        //判断PDA是否连接
        boolean res = pdaOperateDao.connection();
        if (!res) {
            System.out.println("PDA连接失败");
            return false;
        }
        return true;
    }

    /**
     * 选择Pda操作菜单
     */
    private static void menuPda() {
        f:
        while (true) {
            System.out.println("请选择以下操作:1-导入PDA数据 2-导出PDA数据 0-退出");
            String s = scanner.nextLine();
            switch (s) {
                case "1"://导入PDA数据
                {
                    if (pdaOperateDao.pushFiles()) {
                        System.out.println("导入成功,导入目录:" + properties.getProperty("androidDir"));
                    }
                }
                break;
                case "2"://导出PDA业务数据
                {
                    if (pdaOperateDao.pullFiles()) {
                        System.out.println("导出成功,导出目录:" + conf.getPcSerDir());
                    }
                }
                break;
                case "0"://退出
                    System.out.println("谢谢使用!");
                    break f;
                default:
                    System.out.println("输入错误,请重新输入");
                    break;
            }
        }
    }

    /**
     * 初始化Safe:获取token
     *
     * @return
     */
    private static boolean initSafe() {
        //加载safe服务
        safeServerDao = new SafeServerDaoImpl();
        //登录获取token
        String tokenStr = safeServerDao.LoginSafe();
        if (tokenStr == null || tokenStr.trim().equals("")) {
            System.out.println("登录安全环保系统失败");
            return false;
        }
        token = "Bearer  " + tokenStr;
        return true;
    }

    /**
     * 安环服务数据同步菜单
     */
    private static void menuServer() {
        f:
        while (true) {
            System.out.println("请选择以下操作:1-导出安环系统基础数据 2-导入安环系统业务数据 0-退出");
            String s = scanner.nextLine();
            switch (s) {
                case "1"://导出安环系统基础数据
                    if (safeServerDao.getSafeData(token)) {
                        System.out.println("导出成功,导出目录:" + conf.getPcDir());
                    }
                    break;
                case "2"://导入安环系统业务数据
                    if (safeServerDao.setSafeData(token)) {
                        System.out.println("数据导入安全环保系统成功!");
                    }

                    break;
                case "0"://退出
                    System.out.println("谢谢使用!");
                    break f;
                default:
                    System.out.println("输入错误,请重新输入");
                    break;
            }
        }
    }

    /**
     * PDA操作、安环服务数据同步菜单
     */
    private static void menuAll() {
        f:
        while (true) {
            System.out.println("请选择以下操作: 1-导入PDA数据 2-导出PDA数据  3-导出安环系统基础数据 4-导入安环系统业务数据 0-退出");
            String s = scanner.nextLine();
            switch (s) {
                case "1"://导入PDA数据
                {
                    if (pdaOperateDao.pushFiles()) {
                        System.out.println("导入成功,导入目录:" + properties.getProperty("androidDir"));
                    }
                }
                break;
                case "2"://导出PDA数据
                {
                    if (pdaOperateDao.pullFiles()) {
                        System.out.println("导出成功,导出目录:" + conf.getPcSerDir());
                    }
                }
                case "3"://导出安环系统基础数据
                    if (safeServerDao.getSafeData(token)) {
                        System.out.println("导出成功,导出目录:" + conf.getPcDir());
                    }
                    break;
                case "4"://导入安环系统业务数据
                    if (safeServerDao.setSafeData(token)) {
                        System.out.println("数据导入安全环保系统成功!");
                    }
                    break;
                case "0"://退出
                    System.out.println("谢谢使用!");
                    break f;
                default:
                    System.out.println("输入错误,请重新输入");
                    break;
            }
        }
    }
}

4.2 PDA实现类

package com.jsonliu.service.impl;

import com.jsonliu.config.PropertiesConf;
import com.jsonliu.service.PdaOperateDao;
import com.jsonliu.util.IOUtil;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * pda操作命令
 *
 * @Author JSONLiu
 * @Date:2021-04-20
 */
public class PdaOperateDaoImpl implements PdaOperateDao {
    //运行时环境
    private Runtime rt = Runtime.getRuntime();
    //配置文件信息
    private Properties properties = PropertiesConf.getInstance().getProp();
    private PropertiesConf conf = PropertiesConf.getInstance();

    /**
     * 解压ADB
     *
     * @return
     */
    private boolean getAdb() {
        if (new File(conf.getAdbPath() + "adb.exe").exists()) {//存在就不解压
            return true;
        }
        //不存在
        try {
            Process process = rt.exec("jar -xvf operateAndroid.jar");
            String msg = IOUtil.readProMsg(process);
            if (msg.contains("adb.exe")) return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean connection() {
        if (!getAdb()) {
            return false;
        }
        //执行pda命令
        try {
            Process process = rt.exec(conf.getAdbPath() + "adb devices");
            //获取连接消息
            String msg = IOUtil.readProMsg(process);
            String[] devices = msg.replace("List of devices attached", "").trim().split("device");
            if (devices.length > 0 && !devices[0].equals("")) return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean pullFiles() {
        //获取所有文件
        List<String> fileNames = getAndroidFile();
        if (fileNames == null || fileNames.size() == 0) {
            System.out.println("目录下不存在文件");
            return false;
        }
        //清空业务数据目录下原来的文件
        IOUtil.clearDir(conf.getPcSerDir());
        //拉取所有文件到本地pc
        StringBuffer sb = new StringBuffer();
        for (String fileName : fileNames) {
            sb.append(conf.getAdbPath() + "adb pull " + properties.getProperty("androidDir") + fileName
                    + " " + conf.getPcSerDir() + " && ");
        }
        String cmd = sb.toString();
        if (cmd != "") cmd = cmd.substring(0, cmd.lastIndexOf("&&"));
        //执行pda命令
        try {
            Process process = rt.exec(cmd);
            //获取连接消息
            String msg = IOUtil.readProMsg(process);
            if (msg.contains("pulled")) return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean pushFiles() {
        //获取本地所有文件
        List<String> fileNames = getPcFile();
        if (fileNames == null || fileNames.size() == 0) {
            System.out.println("目录下不存在文件");
            return false;
        }
        //推送本地所有文件到android设备
        StringBuffer sb = new StringBuffer();
        for (String fileName : fileNames) {
            sb.append(conf.getAdbPath() + "adb push " + fileName + " " + properties.getProperty("androidDir") + " && ");
        }
        String cmd = sb.toString();
        if (cmd != "") cmd = cmd.substring(0, cmd.lastIndexOf("&&"));
        //执行pda命令
        try {
            Process process = rt.exec(cmd);
            //获取连接消息
            String msg = IOUtil.readProMsg(process);
            if (msg.contains("pushed")) return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }


    /**
     * 获取pc基础数据文件夹文件
     *
     * @return
     */
    private List<String> getPcFile() {
        List<String> list = new ArrayList<>();
        File file = new File(conf.getPcDir());
        if (!file.exists()) {
            System.out.println("路径错误");
            return null;
        }
        File[] files = file.listFiles();
        for (File file1 : files) {
            if (file1.isDirectory()) continue;
            list.add(file1.getAbsolutePath());
        }
        return list;
    }

    /**
     * 获取android文件夹文件
     *
     * @return
     */
    private List<String> getAndroidFile() {
        //执行pda命令
        try {
            Process process = rt.exec(conf.getAdbPath() + "adb shell \"cd "
                    + properties.getProperty("androidDir") + " && ls\"");
            //获取连接消息
            return IOUtil.readLineProMsg(process);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}

4.3 业务系统交互实现类

package com.jsonliu.service.impl;

import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;
import com.google.gson.reflect.TypeToken;
import com.jsonliu.bean.BaseAttachment;
import com.jsonliu.bean.CheckLogVO;
import com.jsonliu.bean.Result;
import com.jsonliu.config.PropertiesConf;
import com.jsonliu.service.SafeServerDao;
import com.jsonliu.util.HttpUtil;
import com.jsonliu.util.IOUtil;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;

public class SafeServerDaoImpl implements SafeServerDao {
    //配置文件信息
    private Properties properties = PropertiesConf.getInstance().getProp();
    private PropertiesConf conf = PropertiesConf.getInstance();
    @Override
    public String LoginSafe() {
        //获取用户名
        String username = properties.getProperty("safeUser");
        try {
            username = URLEncoder.encode(username, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        //获取密码
        String pwd = Base64.getEncoder().encodeToString(properties.getProperty("safePwd").getBytes());
        pwd = pwd.replace("=", "%3D");
        //登录地址
        String linkUrl = properties.getProperty("safeUrl") + "/authorization-server/oauth/token";
        //参数
        linkUrl = linkUrl + "?grant_type=password&scope=read&password=" + pwd + "&username=" + username;
        //请求登录
        Result result = HttpUtil.doPost(linkUrl, null, properties.getProperty("safeAuth"));
        if (result != null && result.getData() != null) {
            HashMap hashMap = new Gson().fromJson(String.valueOf(result.getData()), HashMap.class);
            return hashMap.get("access_token").toString();
        }
        return null;
    }

    @Override
    public boolean getSafeData(String token) {
        //清空基础数据目录下原来的文件
        IOUtil.clearDir(conf.getPcDir());
        try {
            //1、危险点台账 /safe/api/proRisk/getList
            writeJsonFile("/safe/api/proRisk/getList", "{}", token, properties.getProperty("proRiskName"));

            //2、特种设备 /equipment/api/specialEqu/getList
            writeJsonFile("/equipment/api/specialEqu/getList", "{}", token, properties.getProperty("specialEquName"));

            //3、非标设备 /safe/api/proNonstandard/getList
            writeJsonFile("/safe/api/proNonstandard/getList", "{}", token, properties.getProperty("proNonstandardName"));

            //4、环境风险点 /envpro/api/envRiskPoint/getList
            writeJsonFile("/envpro/api/envRiskPoint/getList", "{}", token, properties.getProperty("envRiskPointName"));

            //5、环保治理设施 /envpro/api/envEqu/getList
            writeJsonFile("/envpro/api/envEqu/getList", "{}", token, properties.getProperty("envEquName"));

            //6、职业危害设施 /safe/api/heaHarmequ/getList
            writeJsonFile("/safe/api/heaHarmequ/getList", "{}", token, properties.getProperty("heaHarmequName"));

            //7、高能耗设备 /equipment/api/highEqu/getList
            writeJsonFile("/equipment/api/highEqu/getList", "{}", token, properties.getProperty("highEquName"));

            //8、供能设备 /equipment/api/supplyEqu/getList
            writeJsonFile("/equipment/api/supplyEqu/getList", "{}", token, properties.getProperty("supplyEquName"));

            //9、消防重点部位 /safe/api/firePosition/getList
            writeJsonFile("/safe/api/firePosition/getList", "{}", token, properties.getProperty("firePositionName"));

            //10、消防设备 /equipment/api/fireEqu/getList
            writeJsonFile("/equipment/api/fireEqu/getList", "{}", token, properties.getProperty("fireEquName"));

            //11、应急物资管理 /safe/api/emeMaterials/getList
            writeJsonFile("/safe/api/emeMaterials/getList", "{}", token, properties.getProperty("emeMaterialsName"));

        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    @Override
    public boolean setSafeData(String token) {
        String jsonStr = null;
        //读取文件内容
        try {
            jsonStr = IOUtil.readFile(conf.getPcSerDir() + properties.getProperty("checkName"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (jsonStr == null || jsonStr.equals("")) {
            System.out.println("检查记录文件内容为空");
            return false;
        }
        //将json字符串转为集合对象
        List<CheckLogVO> list = new Gson().fromJson(jsonStr, new TypeToken<List<CheckLogVO>>() {
        }.getType());
        if (list == null || list.size() == 0) {
            System.out.println("检查记录文件内容为空");
            return false;
        }
        //上传文件至服务器,更新集合文件路径
        //如果此处文件较多,1000+ 如何处理??
        try {
            upLoadFiles(list, token);
        } catch (FileNotFoundException e) {
            System.out.println(e.getMessage());
            return false;
        }
        //批量保存检查记录 batchInsert
        String apiUrl="/organization/api/baseCheckLog/batchAdd";
        Result result = HttpUtil.doPost(properties.getProperty("safeUrl") + apiUrl,new Gson().toJson(list), token);
        Object obj = getResultData(apiUrl, result);
        if (obj instanceof String && obj.equals("")) {
            return false;
        }
        return true;
    }

    /**
     * 调取远程API,获得基础数据,写出json数据至文件中
     *
     * @param apiUrl   api路径
     * @param params   条件参数
     * @param token    登录获取的token
     * @param fileName 写出文件名称
     * @return
     * @throws IOException
     */
    private boolean writeJsonFile(String apiUrl, String params, String token, String fileName) throws IOException {
        //调用远程方法,获取数据
        Result result = HttpUtil.doPost(properties.getProperty("safeUrl") + apiUrl, params, token);
        Object obj = getResultData(apiUrl, result);
        if (obj instanceof String && obj.equals("")) {
            return false;
        }
        //将数据写入文件
        IOUtil.writeFile(obj.toString(), conf.getPcDir() + fileName);
        return true;
    }

    /**
     * 上传检查附件,并更新检查记录
     *
     * @param checkLogList
     * @param token
     * @return
     */
    private boolean upLoadFiles(List<CheckLogVO> checkLogList, String token) throws FileNotFoundException {
        System.out.println("开始文件上传,请等待...");
        String apiUrl = "/xfile/api/minio/upload";
        for (CheckLogVO vo : checkLogList) {
            if (vo.getAttachmentList() == null) {
                continue;
            }
            for (BaseAttachment attachment : vo.getAttachmentList()) {
                Result result = HttpUtil.doPostFile(properties.getProperty("safeUrl") + apiUrl, token,
                        conf.getPcSerDir() + attachment.getSfPath());
                Object obj = getResultData(apiUrl, result);
                if (obj instanceof String && obj.equals("")) {
                    continue;
                }
                LinkedTreeMap treeMap = (LinkedTreeMap) obj;
                attachment.setSfPath(String.valueOf(treeMap.get("url")));
            }
        }
        System.out.println("文件上传结束...");
        return true;
    }

    /**
     * 获取result返回data数据
     *
     * @param apiUrl api路径
     * @param result result结果
     * @return data字符串
     */
    private Object getResultData(String apiUrl, Result result) {
        if (result == null) return "";
        if (result != null && result.getCode() != 200) {
            System.out.println("接口:" + apiUrl + "-->>" + result.getMessage());
            return "";
        }
        //解析result.getData()
        HashMap json = new Gson().fromJson(String.valueOf(result.getData()), HashMap.class);
        if (json.get("data") == null) {
            System.out.println("接口:" + apiUrl + "-->>" + json.get("mesg"));
            return "";
        }
        return json.get("data");
    }
}

4.4 配置文件读取类

package com.jsonliu.config;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * @Author: JSONLiu
 * @Description: 获取配置类
 * @Date Created in 2021-04-21 22:54
 * @Modified By:
 */
public class PropertiesConf {
    //Properties参数
    private Properties prop = null;
    //adb相关资源解压路径
    private String adbPath = System.getProperty("user.dir") + "\\adb\\";
    //PC基础数据目录
    private String pcDir = System.getProperty("user.dir") + "\\baseDir\\";
    //PC业务数据目录
    private String pcSerDir = System.getProperty("user.dir") + "\\serviceDir\\";

    private PropertiesConf() {
        try {
            //读取配置
            InputStream stream = this.getClass().getClassLoader()
                    .getResourceAsStream("app.properties");
            Properties properties = new Properties();
            properties.load(stream);
            prop = properties;
            //创建adb目录
            File file1 = new File(adbPath);
            if (!file1.exists()) {
                file1.mkdirs();
            }
            //创建PC基础数据目录
            File file2 = new File(pcDir);
            if (!file2.exists()) {
                file2.mkdirs();
            }
            //创建PC基础数据目录
            File file3 = new File(pcSerDir);
            if (!file3.exists()) {
                file3.mkdirs();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static PropertiesConf propertiesConf = new PropertiesConf();

    public static PropertiesConf getInstance() {
        return propertiesConf;
    }

    public Properties getProp() {
        return prop;
    }

    public String getAdbPath() {
        return adbPath;
    }

    public String getPcDir() {
        return pcDir;
    }

    public String getPcSerDir() {
        return pcSerDir;
    }

}

4.5 其他工具实现类参考:

HttpUtil 
IOUtil

源码下载地址:

https://download.csdn.net/download/lj15559275886/18561452

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笑谈子云亭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值