pwxmax 4 лет назад
Родитель
Сommit
c7ae2d2e68

+ 1 - 0
app/build.gradle

@@ -30,6 +30,7 @@ android {
 }
 
 dependencies {
+    implementation fileTree(dir: "libs", include: ["*.jar"])
     implementation project(':VideoCall')
     implementation 'androidx.appcompat:appcompat:1.2.0'
     implementation 'com.google.android.material:material:1.3.0'

BIN
app/libs/printersdkv1.jar


+ 3 - 1
app/src/main/AndroidManifest.xml

@@ -2,6 +2,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.rdgk.cemetery">
 
+    <uses-permission android:name="android.permission.BLUETOOTH" />
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
@@ -11,10 +13,10 @@
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
-    <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.NFC" />
     <uses-permission android:name="android.permission.NFC_TRANSACTION_EVENT" />
+
     <uses-feature
         android:name="android.hardware.nfc"
         android:required="true" />

+ 9 - 37
app/src/main/java/com/rdgk/cemetery/activity/MainActivity.java

@@ -35,7 +35,7 @@ import com.rdgk.cemetery.data.Url;
 import com.rdgk.cemetery.utils.CompressUtil;
 import com.rdgk.cemetery.utils.SharedPreferenceUtil;
 import com.rdgk.cemetery.utils.ToastUtil;
-import com.rdgk.cemetery.view.VersionCheckingUtil;
+import com.rdgk.cemetery.utils.VersionCheckingUtil;
 import com.rdgk.cemetery.weiview.WebViewActivity;
 
 import java.io.File;
@@ -58,6 +58,7 @@ public class MainActivity extends AppCompatActivity {
         start = findViewById(R.id.start);
         editText = findViewById(R.id.ed_text);
         initPermission();
+        getVM();
         start.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
@@ -167,51 +168,22 @@ public class MainActivity extends AppCompatActivity {
     }
 
     private void getVM() {
-        File versionFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/fshome/fsmobile/version");
-        FetchUpBean fetchUpBean = new FetchUpBean();
-        ArrayList<FetchUpBean.QuerysBean> querysBeans = new ArrayList<>();
-        FetchUpBean.QuerysBean querysBean = new FetchUpBean.QuerysBean();
-        FetchUpBean.QuerysBean.OrderbyBean orderbyBean = new FetchUpBean.QuerysBean.OrderbyBean();
-        ArrayList<String> strings = new ArrayList<>();
-        strings.add("createTime");
-        orderbyBean.setColumns(strings);
-        orderbyBean.setSeq("DESC");
-        querysBean.setOrderby(orderbyBean);
-        FetchUpBean.QuerysBean.LimitBean limitBean = new FetchUpBean.QuerysBean.LimitBean();
-        limitBean.setStart(0);
-        limitBean.setLength(1);
-        querysBean.setLimit(limitBean);
-        querysBean.setOrderby(orderbyBean);
-        querysBeans.add(querysBean);
-        fetchUpBean.setQuerys(querysBeans);
-        OkGo.<ItemCommonList<appVMBean, ExpandsBean>>post(Url.URL_VERSION)
-                .upJson(new Gson().toJson(fetchUpBean))
-                .execute(new JsonCallBack<ItemCommonList<appVMBean, ExpandsBean>>() {
+        OkGo.<appVMBean>post(Url.URL_VERSION)
+                .execute(new JsonCallBack<appVMBean>() {
                     @Override
-                    public void onSuccess(Response<ItemCommonList<appVMBean, ExpandsBean>> response) {
+                    public void onSuccess(Response<appVMBean> response) {
                         super.onSuccess(response);
-                        ItemCommonList<appVMBean, ExpandsBean> body = response.body();
+                        appVMBean body = response.body();
                         if (body.getCode() == ConstantData.CODE_RESULT_SUCCESS) {
-                            if (body.getData() != null && body.getData().size() > 0) {
-                                if (body.getData().get(0).getUpdateType() == 2) {
-                                    new VersionCheckingUtil().isChecking(MainActivity.this, body.getData().get(0), 0);
-                                } else if (body.getData().get(0).getUpdateType() == 1) {
-                                    if (versionFile.exists()) {
-                                        if (!readFileContent(versionFile).equals(body.getData().get(0).getWebVersion())) {
-                                            initApp(body.getData().get(0).getAppWebUrl(), 1);
-                                        }
-                                    } else {
-                                        initApp(body.getData().get(0).getAppWebUrl(), 1);
-                                    }
-                                }
-                            }
+                            VersionCheckingUtil versionCheckingUtil = new VersionCheckingUtil();
+                            versionCheckingUtil.isChecking(MainActivity.this, body, 1);
                         } else {
                             ToastUtil.showToast("加载失败");
                         }
                     }
 
                     @Override
-                    public void onError(Response<ItemCommonList<appVMBean, ExpandsBean>> response) {
+                    public void onError(Response<appVMBean> response) {
                         super.onError(response);
                     }
                 });

+ 406 - 0
app/src/main/java/com/rdgk/cemetery/activity/PrintActivity.java

@@ -0,0 +1,406 @@
+package com.rdgk.cemetery.activity;
+
+import android.Manifest;
+import android.annotation.SuppressLint;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
+
+import com.lzy.okgo.OkGo;
+import com.printer.command.EscCommand;
+import com.rdgk.cemetery.R;
+import com.rdgk.cemetery.printer.BluetoothListActivity;
+import com.rdgk.cemetery.printer.DeviceConnFactoryManager;
+import com.rdgk.cemetery.printer.PrinterCommand;
+import com.rdgk.cemetery.printer.ThreadPool;
+import com.rdgk.cemetery.utils.SharedPreferenceUtil;
+import com.rdgk.cemetery.utils.ToastUtil;
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+import static android.hardware.usb.UsbManager.ACTION_USB_DEVICE_DETACHED;
+import static com.rdgk.cemetery.printer.DeviceConnFactoryManager.ACTION_QUERY_PRINTER_STATE;
+
+public class PrintActivity extends AppCompatActivity {
+
+    private TextView mTvState;
+
+    /**
+     * 权限请求码
+     */
+    private static final int REQUEST_CODE = 0x001;
+
+    /**
+     * 蓝牙所需权限
+     */
+    private String[] permissions = {
+            Manifest.permission.ACCESS_FINE_LOCATION,
+            Manifest.permission.ACCESS_COARSE_LOCATION,
+            Manifest.permission.BLUETOOTH
+    };
+
+    /**
+     * 未授予的权限
+     */
+    private ArrayList<String> per = new ArrayList<>();
+
+    /**
+     * 蓝牙请求码
+     */
+    public static final int BLUETOOTH_REQUEST_CODE = 0x002;
+
+    private ThreadPool threadPool;//线程
+
+    /**
+     * 判断打印机所使用指令是否是ESC指令
+     */
+    private int id = 0;
+
+    /**
+     * 打印机是否连接
+     */
+    private static final int CONN_PRINTER = 0x003;
+
+    /**
+     * 使用打印机指令错误
+     */
+    private static final int PRINTER_COMMAND_ERROR = 0x004;
+
+    /**
+     * 连接状态断开
+     */
+    private static final int CONN_STATE_DISCONN = 0x005;
+    private String data;
+
+
+    public static void launch(Context context, String json) {
+        Intent intent = new Intent(context, PrintActivity.class);
+        intent.putExtra("json", json);
+        context.startActivity(intent);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_test);
+        Bundle bundle = getIntent().getExtras();
+        if (bundle != null) {
+            data = bundle.getString("json", "");
+        }
+        mTvState = findViewById(R.id.tv_state);
+        checkPermission();
+        requestPermission();
+        String mac = (String) SharedPreferenceUtil.get(this, "mac", "");
+        if (!TextUtils.isEmpty(mac)) {
+            ToastUtil.showToast("正在连接蓝牙");
+            connectBluetooth(mac);
+        }
+
+    }
+
+    private void checkPermission() {
+        for (String permission : permissions) {
+            if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this, permission)) {
+                per.add(permission);
+            }
+        }
+    }
+
+    private void requestPermission() {
+        if (per.size() > 0) {
+            String[] p = new String[per.size()];
+            ActivityCompat.requestPermissions(this, per.toArray(p), REQUEST_CODE);
+        }
+    }
+
+    public void btnConnect(View view) {
+        startActivityForResult(new Intent(PrintActivity.this, BluetoothListActivity.class), BLUETOOTH_REQUEST_CODE);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if (resultCode == RESULT_OK) {
+            //蓝牙连接
+            if (requestCode == BLUETOOTH_REQUEST_CODE) {
+                String macAddress = data.getStringExtra(BluetoothListActivity.EXTRA_DEVICE_ADDRESS);
+                connectBluetooth(macAddress);
+            }
+        }
+    }
+
+    private void connectBluetooth(String macAddress) {
+        closePort();
+        //获取蓝牙mac地址
+
+        //初始化DeviceConnFactoryManager 并设置信息
+        new DeviceConnFactoryManager.Build()
+                //设置标识符
+                .setId(id)
+                //设置连接方式
+                .setConnMethod(DeviceConnFactoryManager.CONN_METHOD.BLUETOOTH)
+                //设置连接的蓝牙mac地址
+                .setMacAddress(macAddress)
+                .build();
+        //配置完信息,就可以打开端口连接了
+        Log.i("TAG", "onActivityResult: 连接蓝牙" + id);
+        threadPool = ThreadPool.getInstantiation();
+        threadPool.addTask(new Runnable() {
+            @Override
+            public void run() {
+                DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].openPort();
+            }
+        });
+    }
+
+    /**
+     * 重新连接回收上次连接的对象,避免内存泄漏
+     */
+    private void closePort() {
+        if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] != null && DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].mPort != null) {
+            DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].reader.cancel();
+            DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].mPort.closePort();
+            DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].mPort = null;
+        }
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        /*
+         * 注册接收连接状态的广播
+         */
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_QUERY_PRINTER_STATE);
+        filter.addAction(DeviceConnFactoryManager.ACTION_CONN_STATE);
+        registerReceiver(receiver, filter);
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        unregisterReceiver(receiver);
+    }
+
+    /**
+     * 连接状态的广播
+     */
+    private BroadcastReceiver receiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (DeviceConnFactoryManager.ACTION_CONN_STATE.equals(action)) {
+                int state = intent.getIntExtra(DeviceConnFactoryManager.STATE, -1);
+                int deviceId = intent.getIntExtra(DeviceConnFactoryManager.DEVICE_ID, -1);
+                switch (state) {
+                    case DeviceConnFactoryManager.CONN_STATE_DISCONNECT:
+                        if (id == deviceId) mTvState.setText("未连接");
+                        break;
+                    case DeviceConnFactoryManager.CONN_STATE_CONNECTING:
+                        mTvState.setText("连接中");
+                        break;
+                    case DeviceConnFactoryManager.CONN_STATE_CONNECTED:
+                        mTvState.setText("已连接");
+                        SharedPreferenceUtil.put(PrintActivity.this, "mac", DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getMacAddress());
+                        Toast.makeText(PrintActivity.this, "已连接", Toast.LENGTH_SHORT).show();
+                        //TODO !!!此处代码为连接完成打印
+                        Log.i("TAG", "准备打印");
+                        threadPool = ThreadPool.getInstantiation();
+                        threadPool.addTask(new Runnable() {
+                            @Override
+                            public void run() {
+                                //先判断打印机是否连接
+                                if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] == null ||
+                                        !DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getConnState()) {
+                                    mHandler.obtainMessage(CONN_PRINTER).sendToTarget();
+                                    return;
+                                }
+                                if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getCurrentPrinterCommand() == PrinterCommand.ESC) {
+                                    Log.i("TAG", "开始打印");
+                                    sendLabel(data);
+                                } else {
+                                    mHandler.obtainMessage(PRINTER_COMMAND_ERROR).sendToTarget();
+                                }
+                            }
+                        });
+                        break;
+//                    case CONN_STATE_FAILED:
+//                        mTvState.setText("未连接");
+//                        Toast.makeText(MainActivity.this, "连接失败!重试或重启打印机试试", Toast.LENGTH_SHORT).show();
+//                        break;
+                }
+                /* Usb连接断开、蓝牙连接断开广播 */
+            } else if (ACTION_USB_DEVICE_DETACHED.equals(action)) {
+                mHandler.obtainMessage(CONN_STATE_DISCONN).sendToTarget();
+            }
+        }
+    };
+
+    @SuppressLint("HandlerLeak")
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case CONN_STATE_DISCONN:
+                    if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] != null || !DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getConnState()) {
+                        DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].closePort(id);
+                        Toast.makeText(PrintActivity.this, "成功断开连接", Toast.LENGTH_SHORT).show();
+                    }
+                    break;
+                case PRINTER_COMMAND_ERROR:
+                    Toast.makeText(PrintActivity.this, "请选择正确的打印机指令", Toast.LENGTH_SHORT).show();
+                    break;
+                case CONN_PRINTER:
+                    Toast.makeText(PrintActivity.this, "请先连接打印机", Toast.LENGTH_SHORT).show();
+                    break;
+            }
+        }
+    };
+
+
+    public void printLabel() {
+
+    }
+
+    private void sendLabel(String printBean) {
+        EscCommand esc = new EscCommand();
+        esc.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);
+        esc.addSetCharcterSize(EscCommand.WIDTH_ZOOM.MUL_2, EscCommand.HEIGHT_ZOOM.MUL_2);
+        esc.addTurnEmphasizedModeOnOrOff(EscCommand.ENABLE.ON);
+//        String orderSt = "";
+//        String orderTy = "";
+//        if (orderType == 1) {
+//            orderSt = "服务小票";
+//            orderTy = "*  福山居家服务  *";
+//        } else if (orderType == 2) {
+//            orderSt = "餐饮小票";
+//            orderTy = "*  福山居家送餐  *";
+//        } else {
+//            orderSt = "医疗小票";
+//            orderTy = "*  福山居家医疗  *";
+//        }
+//        esc.addText(orderSt);
+//        esc.addTurnEmphasizedModeOnOrOff(EscCommand.ENABLE.OFF);
+//        esc.addPrintAndLineFeed();
+//        esc.addSetCharcterSize(EscCommand.WIDTH_ZOOM.MUL_1, EscCommand.HEIGHT_ZOOM.MUL_1);
+//        esc.addText("————————————————————————");
+//        esc.addPrintAndLineFeed();
+//
+////        esc.addText(orderTy);
+////        esc.addPrintAndLineFeed();
+//        esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
+//        esc.addText("服务机构:" + printBean.getServiceCenter());
+//        esc.addPrintAndLineFeed();
+//        esc.addText("客户姓名:" + printBean.getReceive());
+//        esc.addPrintAndLineFeed();
+//        esc.addText("客户地址:" + printBean.getAddress());
+//        esc.addPrintAndLineFeed();
+//        esc.addText("客户电话:" + printBean.getPhone());
+//        esc.addPrintAndLineFeed();
+//        esc.addText("服务完成时间: " + printBean.getResidentialServicesWorkVO().getOverTimeX());
+//        esc.addPrintAndLineFeed();
+//        esc.addText("————————————————————————");
+//        esc.addPrintAndLineFeed();
+//        esc.addTurnEmphasizedModeOnOrOff(EscCommand.ENABLE.ON);
+//        StringBuffer stringBuffer = new StringBuffer();
+//        char c = " ".toCharArray()[0];
+//        stringBuffer.append("服务项目");
+//        for (int i = 0; i < 15; i++) {
+//            stringBuffer.append(c);
+//        }
+//        stringBuffer.append("数量");
+//        for (int i = 0; i < 10; i++) {
+//            stringBuffer.append(c);
+//        }
+//        stringBuffer.append("金额");
+//        esc.addText(stringBuffer.toString());
+//        esc.addPrintAndLineFeed();
+//        esc.addPrintAndLineFeed();
+//        esc.addTurnEmphasizedModeOnOrOff(EscCommand.ENABLE.OFF);
+//        List<com.example.homeservicelive.bean.printBean.ItemsBean> list = printBean.getItems();
+//        for (int i = 0; i < list.size(); i++) {
+//            com.example.homeservicelive.bean.printBean.ItemsBean itemsBean = list.get(i);
+//            esc.addText(itemsBean.getGoodsName());
+//            esc.addText(StringUtil.getNameToSpace(itemsBean.getGoodsName(), "服务项目".toCharArray().length));
+//            esc.addText(itemsBean.getGoodsCount().toString());
+//            esc.addText(StringUtil.getNameToSpaceTwo(itemsBean.getGoodsCount(), "服务".toCharArray().length));
+//            esc.addText(itemsBean.getGoodsPrice().toString());
+//            esc.addPrintAndLineFeed();
+//            if (itemsBean.getList() != null && itemsBean.getList().size() > 0) {
+//                StringBuffer sb = new StringBuffer();
+//                sb.append("套餐内容:");
+//                for (int j = 0; j < itemsBean.getList().size(); j++) {
+//                    sb.append(itemsBean.getList().get(j).getGoodsName());
+//                    sb.append("   X");
+//                    sb.append(itemsBean.getList().get(j).getGoodsCount());
+//                    sb.append(",");
+//                }
+//                esc.addText(sb.toString().substring(0, sb.toString().length() - 1));
+//                esc.addPrintAndLineFeed();
+//            }
+//        }
+//        esc.addPrintAndLineFeed();
+//        esc.addText("————————————————————————");
+//        esc.addPrintAndLineFeed();
+//        esc.addPrintAndLineFeed();
+//        esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
+//        if (!TextUtils.isEmpty(printBean.getPreferential()) && !printBean.getPreferential().equals("null") && !printBean.getPreferential().equals("0.00")) {
+//            esc.addText("减免:-¥" + printBean.getPreferential() + "元");
+//            esc.addPrintAndLineFeed();
+//        }
+//        esc.addTurnEmphasizedModeOnOrOff(EscCommand.ENABLE.ON);
+//        esc.addText("实付:    ¥" + printBean.getUsersPay() + "元");
+//        esc.addPrintAndLineFeed();
+//        esc.addText("余额:    ¥" + printBean.getTheBalanceOf() + "元");
+//        esc.addPrintAndLineFeed();
+//        esc.addText("付款方式:" + printBean.getWay());
+        esc.addPrintAndLineFeed();
+        esc.addTurnEmphasizedModeOnOrOff(EscCommand.ENABLE.OFF);
+        esc.addPrintAndLineFeed();
+        esc.addText("————————————————————————");
+        esc.addPrintAndLineFeed();
+        esc.addPrintAndLineFeed();
+        esc.addPrintAndLineFeed();
+        esc.addPrintAndLineFeed();
+        /* 发送数据 */
+        Vector<Byte> data = esc.getCommand();
+        if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] == null) {
+            Log.i("TAG", "sendLabel: 打印机为空");
+            return;
+        }
+        DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].sendDataImmediately(data);
+
+        finish();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        Log.i("TAG", "onDestroy");
+        DeviceConnFactoryManager.closeAllPort();
+        if (threadPool != null) {
+            threadPool.stopThreadPool();
+            threadPool = null;
+        }
+    }
+
+    public void BtnClose(View view) {
+        finish();
+    }
+}

+ 107 - 64
app/src/main/java/com/rdgk/cemetery/bean/appVMBean.java

@@ -2,94 +2,137 @@ package com.rdgk.cemetery.bean;
 
 public class appVMBean {
 
-    private String appApkUrl;
-    private String appWebUrl;
-    private String createTime;
-    private String id;
-    private Integer updateLevel;
-    private String updateTime;
-    private Integer updateType;
-    private String version;
-    private String versionDoc;
-    private String webVersion;
-
-    public String getWebVersion() {
-        return webVersion;
-    }
 
-    public void setWebVersion(String webVersion) {
-        this.webVersion = webVersion;
-    }
+    private String msg;
+    private int code;
+    private DataBean data;
 
-    public String getAppApkUrl() {
-        return appApkUrl;
+    public String getMsg() {
+        return msg;
     }
 
-    public void setAppApkUrl(String appApkUrl) {
-        this.appApkUrl = appApkUrl;
+    public void setMsg(String msg) {
+        this.msg = msg;
     }
 
-    public String getAppWebUrl() {
-        return appWebUrl;
+    public int getCode() {
+        return code;
     }
 
-    public void setAppWebUrl(String appWebUrl) {
-        this.appWebUrl = appWebUrl;
+    public void setCode(int code) {
+        this.code = code;
     }
 
-    public String getCreateTime() {
-        return createTime;
+    public DataBean getData() {
+        return data;
     }
 
-    public void setCreateTime(String createTime) {
-        this.createTime = createTime;
+    public void setData(DataBean data) {
+        this.data = data;
     }
 
-    public String getId() {
-        return id;
-    }
+    public static class DataBean {
+        private Object searchValue;
+        private String createBy;
+        private Object createTime;
+        private String updateBy;
+        private Object updateTime;
+        private Object remark;
+        private ParamsBean params;
+        private int id;
+        private String version;
+        private String url;
+        private String delFlag;
 
-    public void setId(String id) {
-        this.id = id;
-    }
+        public Object getSearchValue() {
+            return searchValue;
+        }
 
-    public Integer getUpdateLevel() {
-        return updateLevel;
-    }
+        public void setSearchValue(Object searchValue) {
+            this.searchValue = searchValue;
+        }
 
-    public void setUpdateLevel(Integer updateLevel) {
-        this.updateLevel = updateLevel;
-    }
+        public String getCreateBy() {
+            return createBy;
+        }
 
-    public String getUpdateTime() {
-        return updateTime;
-    }
+        public void setCreateBy(String createBy) {
+            this.createBy = createBy;
+        }
 
-    public void setUpdateTime(String updateTime) {
-        this.updateTime = updateTime;
-    }
+        public Object getCreateTime() {
+            return createTime;
+        }
 
-    public Integer getUpdateType() {
-        return updateType;
-    }
+        public void setCreateTime(Object createTime) {
+            this.createTime = createTime;
+        }
 
-    public void setUpdateType(Integer updateType) {
-        this.updateType = updateType;
-    }
+        public String getUpdateBy() {
+            return updateBy;
+        }
 
-    public String getVersion() {
-        return version;
-    }
+        public void setUpdateBy(String updateBy) {
+            this.updateBy = updateBy;
+        }
 
-    public void setVersion(String version) {
-        this.version = version;
-    }
+        public Object getUpdateTime() {
+            return updateTime;
+        }
 
-    public String getVersionDoc() {
-        return versionDoc;
-    }
+        public void setUpdateTime(Object updateTime) {
+            this.updateTime = updateTime;
+        }
+
+        public Object getRemark() {
+            return remark;
+        }
+
+        public void setRemark(Object remark) {
+            this.remark = remark;
+        }
+
+        public ParamsBean getParams() {
+            return params;
+        }
+
+        public void setParams(ParamsBean params) {
+            this.params = params;
+        }
+
+        public int getId() {
+            return id;
+        }
+
+        public void setId(int id) {
+            this.id = id;
+        }
+
+        public String getVersion() {
+            return version;
+        }
+
+        public void setVersion(String version) {
+            this.version = version;
+        }
+
+        public String getUrl() {
+            return url;
+        }
+
+        public void setUrl(String url) {
+            this.url = url;
+        }
 
-    public void setVersionDoc(String versionDoc) {
-        this.versionDoc = versionDoc;
+        public String getDelFlag() {
+            return delFlag;
+        }
+
+        public void setDelFlag(String delFlag) {
+            this.delFlag = delFlag;
+        }
+
+        public static class ParamsBean {
+        }
     }
 }

+ 1 - 1
app/src/main/java/com/rdgk/cemetery/data/Url.java

@@ -28,7 +28,7 @@ public class Url {
 
     //========= app版本接口类 Version Controller =========//
 
-    public static final String URL_VERSION = baseUrl + "appvm/fetch";
+    public static final String URL_VERSION = "http://118.190.148.113:10090/business/appVersion/getNewAppVersion";
 
     //========= Circle Async Controller =========//
 

+ 203 - 0
app/src/main/java/com/rdgk/cemetery/printer/BluetoothListActivity.java

@@ -0,0 +1,203 @@
+package com.rdgk.cemetery.printer;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+
+import com.rdgk.cemetery.R;
+
+import java.util.Set;
+
+/**
+ * 主要负责打开、搜索、显示蓝牙
+ */
+public class BluetoothListActivity extends Activity {
+
+    private ListView lvPairedDevice;
+    private BluetoothAdapter mBluetoothAdapter;
+    private ArrayAdapter<String> mDevicesArrayAdapter;
+    public static final String EXTRA_DEVICE_ADDRESS = "address";
+    public static final int REQUEST_ENABLE_BT = 2;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+        setContentView(R.layout.dialog_bluetooth_list);
+
+        lvPairedDevice = findViewById(R.id.lvPairedDevices);
+        findViewById(R.id.btBluetoothScan).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                view.setVisibility(View.GONE);
+                discoveryDevice();
+            }
+        });
+
+        // 设置广播信息过滤 并注册
+        // Register for broadcasts when a device is discovered
+        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
+        this.registerReceiver(mFindBlueToothReceiver, filter);
+        // Register for broadcasts when discovery has finished
+        filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
+        this.registerReceiver(mFindBlueToothReceiver, filter);
+
+        initBluetooth();
+    }
+
+    /**
+     * 初始化蓝牙
+     */
+    private void initBluetooth() {
+        // 获取蓝牙适配器
+        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+        // 检查蓝牙是否可用
+        if (mBluetoothAdapter == null) {
+            Toast.makeText(this, "当前设备不支持蓝牙", Toast.LENGTH_SHORT).show();
+        } else {
+            // 检查蓝牙是否打开
+            if (!mBluetoothAdapter.isEnabled()) {
+                Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+                startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
+            } else {
+                getDeviceList();
+            }
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if (requestCode == REQUEST_ENABLE_BT) {
+            if (resultCode == Activity.RESULT_OK) {
+                // bluetooth is opened
+                getDeviceList();
+            } else {
+                // bluetooth is not open
+                Toast.makeText(this, "蓝牙没有开启", Toast.LENGTH_SHORT).show();
+            }
+        }
+    }
+
+    /**
+     * 蓝牙设备列表
+     */
+    protected void getDeviceList() {
+        // 初始化一个数组适配器,用来显示已匹对和未匹对的设备
+        mDevicesArrayAdapter = new ArrayAdapter<>(this, R.layout.bluetooth_device_name_item);
+        lvPairedDevice.setAdapter(mDevicesArrayAdapter);
+        lvPairedDevice.setOnItemClickListener(mDeviceClickListener);
+        // 已匹对数据
+        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
+        // 添加一个item显示信息
+        mDevicesArrayAdapter.add("已配对:");
+        if (pairedDevices.size() > 0) {
+            //遍历填充数据
+            for (BluetoothDevice device : pairedDevices) {
+                mDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
+            }
+        } else {
+            mDevicesArrayAdapter.add("没有已配对设备");
+        }
+    }
+
+    /**
+     * 接收扫描设备的广播
+     * changes the title when discovery is finished
+     */
+    private final BroadcastReceiver mFindBlueToothReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            // 每当发现一个蓝牙设备时
+            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
+                // Get the BluetoothDevice object from the Intent
+                //获取设备
+                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+                // If it's already paired, skip it, because it's been listed
+                // 未匹对的情况下添加显示
+                if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
+                    mDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
+                }
+                // 扫描结束
+            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
+                setProgressBarIndeterminateVisibility(false);
+                setTitle("选择蓝牙设备");
+                //此处-2是减去我们手动添加的两个区分显示的item
+                Log.i("tag", "finish discovery" + (mDevicesArrayAdapter.getCount() - 2));
+                if (mDevicesArrayAdapter.getCount() == 0) {
+                    mDevicesArrayAdapter.add("没有找到蓝牙设备");
+                }
+            }
+        }
+    };
+
+    /**
+     * 扫描设备
+     */
+    private void discoveryDevice() {
+        setProgressBarIndeterminateVisibility(true);
+        setTitle("扫描中");
+        // 添加一个item区分显示信息
+        mDevicesArrayAdapter.add("未配对:");
+        // If we're already discovering, stop it
+        if (mBluetoothAdapter.isDiscovering()) {
+            mBluetoothAdapter.cancelDiscovery();
+        }
+        // 开始扫描,每扫描到一个设备,都会发送一个广播
+        mBluetoothAdapter.startDiscovery();
+    }
+
+    /**
+     * The on-click listener for all devices in the ListViews
+     */
+    private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {
+        @Override
+        public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
+            // Cancel discovery because it's costly and we're about to connect
+            // Get the device MAC address, which is the last 17 chars in the View
+            String info = ((TextView) v).getText().toString();
+            String noDevices = "没有已配对设备";
+            String noNewDevice = "没有找到蓝牙设备";
+            Log.i("TAG", info);
+            // info 不是我们手动添加的信息 即表示为真实蓝牙设备信息
+            if (!info.equals(noDevices) && !info.equals(noNewDevice) && !info.equals("未配对") && !info.equals("已配对")) {
+                mBluetoothAdapter.cancelDiscovery();
+                //mac 地址
+                String address = info.substring(info.length() - 17);
+                // 设置信息并返回
+                // Set result and finish this Activity
+                Intent intent = new Intent();
+                intent.putExtra(EXTRA_DEVICE_ADDRESS, address);
+                setResult(Activity.RESULT_OK, intent);
+                finish();
+            }
+        }
+    };
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        // Make sure we're not doing discovery anymore
+        if (mBluetoothAdapter != null) {
+            mBluetoothAdapter.cancelDiscovery();
+        }
+        // Unregister broadcast listeners
+        unregisterReceiver(mFindBlueToothReceiver);
+    }
+}

+ 649 - 0
app/src/main/java/com/rdgk/cemetery/printer/DeviceConnFactoryManager.java

@@ -0,0 +1,649 @@
+package com.rdgk.cemetery.printer;
+
+import android.annotation.SuppressLint;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.usb.UsbDevice;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.widget.Toast;
+
+
+import java.io.IOException;
+import java.util.Vector;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import static android.hardware.usb.UsbManager.ACTION_USB_DEVICE_DETACHED;
+
+import com.printer.io.BluetoothPort;
+import com.printer.io.EthernetPort;
+import com.printer.io.PortManager;
+import com.printer.io.SerialPort;
+import com.printer.io.UsbPort;
+import com.rdgk.cemetery.component.App;
+
+/**
+ * Time 2017/8/2
+ */
+public class DeviceConnFactoryManager {
+
+    public static final byte FLAG = 0x10;
+    public static final String ACTION_CONN_STATE = "action_connect_state";
+    public static final String ACTION_QUERY_PRINTER_STATE = "action_query_printer_state";
+    public static final String STATE = "state";
+    public static final String DEVICE_ID = "id";
+    public static final int CONN_STATE_DISCONNECT = 0x90;
+    public static final int CONN_STATE_CONNECTING = CONN_STATE_DISCONNECT << 1;
+    public static final int CONN_STATE_FAILED = CONN_STATE_DISCONNECT << 2;
+    public static final int CONN_STATE_CONNECTED = CONN_STATE_DISCONNECT << 3;
+    private static final String TAG = DeviceConnFactoryManager.class.getSimpleName();
+    /**
+     * ESC查询打印机实时状态 缺纸状态
+     */
+    private static final int ESC_STATE_PAPER_ERR = 0x20;
+    /**
+     * ESC指令查询打印机实时状态 打印机开盖状态
+     */
+    private static final int ESC_STATE_COVER_OPEN = 0x04;
+    /**
+     * ESC指令查询打印机实时状态 打印机报错状态
+     */
+    private static final int ESC_STATE_ERR_OCCURS = 0x40;
+    /**
+     * ESC低电量
+     */
+    private static final int ESC_LOW_POWER = 0x31;
+    /**
+     * ESC中电量
+     */
+    private static final int ESC_AMID_POWER = 0x32;
+    /**
+     * ESC高电量
+     */
+    private static final int ESC_HIGH_POWER = 0x33;
+    /**
+     * ESC正在充电
+     */
+    private static final int ESC_CHARGING = 0x35;
+    /**
+     * TSC指令查询打印机实时状态 打印机缺纸状态
+     */
+    private static final int TSC_STATE_PAPER_ERR = 0x04;
+    /**
+     * TSC指令查询打印机实时状态 打印机开盖状态
+     */
+    private static final int TSC_STATE_COVER_OPEN = 0x01;
+    /**
+     * TSC指令查询打印机实时状态 打印机出错状态
+     */
+    private static final int TSC_STATE_ERR_OCCURS = 0x80;
+    /**
+     * CPCL指令查询打印机实时状态 打印机缺纸状态
+     */
+    private static final int CPCL_STATE_PAPER_ERR = 0x01;
+    /**
+     * CPCL指令查询打印机实时状态 打印机开盖状态
+     */
+    private static final int CPCL_STATE_COVER_OPEN = 0x02;
+    private static final int READ_DATA = 10000;
+    private static final String READ_DATA_CNT = "read_data_cnt";
+    private static final String READ_BUFFER_ARRAY = "read_buffer_array";
+    public static boolean whichFlag = true;
+    private static DeviceConnFactoryManager[] deviceConnFactoryManagers = new DeviceConnFactoryManager[4];
+    public PortManager mPort;
+    public CONN_METHOD connMethod;
+    public PrinterReader reader;
+    private String ip;
+    private int port;
+    private String macAddress;
+    private UsbDevice mUsbDevice;
+    private Context mContext;
+    private String serialPortPath;
+    private int baudrate;
+    private int id;
+
+    BroadcastReceiver usbStateReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (ACTION_USB_DEVICE_DETACHED.equals(action)) {
+                sendStateBroadcast(CONN_STATE_DISCONNECT);
+            }
+        }
+    };
+
+    private boolean isOpenPort;
+    /**
+     * ESC查询打印机实时状态指令
+     */
+    private byte[] esc = {0x10, 0x04, 0x02};
+    /**
+     * TSC查询打印机状态指令
+     */
+    private byte[] tsc = {0x1b, '!', '?'};
+    private byte[] cpcl = {0x1b, 0x68};
+    private byte[] sendCommand;
+    /**
+     * 判断打印机所使用指令是否是ESC指令
+     */
+    private PrinterCommand currentPrinterCommand;
+
+    @SuppressLint("HandlerLeak")
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case READ_DATA:
+                    int cnt = msg.getData().getInt(READ_DATA_CNT); //数据长度 >0;
+                    byte[] buffer = msg.getData().getByteArray(READ_BUFFER_ARRAY);  //数据
+                    //这里只对查询状态返回值做处理,其它返回值可参考编程手册来解析
+                    if (buffer == null) {
+                        return;
+                    }
+                    int result = judgeResponseType(buffer[0]); //数据右移
+                    String status = "打印机连接正常";
+                    if (sendCommand == esc) {
+                        //设置当前打印机模式为ESC模式
+                        if (currentPrinterCommand == null) {
+                            currentPrinterCommand = PrinterCommand.ESC;
+                            sendStateBroadcast(CONN_STATE_CONNECTED);
+                        } else {//查询打印机状态
+                            if (result == 0) {//打印机状态查询
+                                Intent intent = new Intent(ACTION_QUERY_PRINTER_STATE);
+                                intent.putExtra(DEVICE_ID, id);
+                                App.getInstance().sendBroadcast(intent);
+                            } else if (result == 1) {//查询打印机实时状态
+                                if (whichFlag) {
+                                    if ((buffer[0] & ESC_STATE_PAPER_ERR) > 0) {
+                                        status += "打印机缺纸";
+                                    }
+                                    if ((buffer[0] & ESC_STATE_COVER_OPEN) > 0) {
+                                        status += "打印机开盖";
+                                    }
+                                    if ((buffer[0] & ESC_STATE_ERR_OCCURS) > 0) {
+                                        status += "打印机出错";
+                                    }
+                                } else {
+                                    if ((buffer[0] == ESC_LOW_POWER)) {
+                                        status = "电量:低电量";
+                                    } else if ((buffer[0] == ESC_AMID_POWER)) {
+                                        status = "电量:中电量";
+                                    } else if ((buffer[0] == ESC_HIGH_POWER)) {
+                                        status = "电量:高电量";
+                                    } else if ((buffer[0] == ESC_CHARGING)) {
+                                        status = "正在充电";
+                                    }
+                                }
+                                Log.i("TAG", "状态:" + status);
+                                String mode = "打印模式:ESC";
+//                                Toast.makeText(MyApp.getInstance(), mode + " " + status, Toast.LENGTH_SHORT).show();
+                            }
+                        }
+                    } else if (sendCommand == tsc) {
+                        //设置当前打印机模式为TSC模式
+                        if (currentPrinterCommand == null) {
+                            currentPrinterCommand = PrinterCommand.TSC;
+                            sendStateBroadcast(CONN_STATE_CONNECTED);
+                        } else {
+                            if (cnt == 1) {//查询打印机实时状态
+                                if ((buffer[0] & ESC_STATE_PAPER_ERR) > 0) {
+                                    status += "打印机缺纸";
+                                }
+                                if ((buffer[0] & ESC_STATE_COVER_OPEN) > 0) {
+                                    status += "打印机开盖";
+                                }
+                                if ((buffer[0] & ESC_STATE_ERR_OCCURS) > 0) {
+                                    status += "打印机出错";
+                                }
+                                Log.i("TAG", "状态:" + status);
+                                String mode = "打印模式:TSC";
+                                Toast.makeText(App.getInstance(), mode + " " + status, Toast.LENGTH_SHORT).show();
+                            } else {//打印机状态查询
+                                Intent intent = new Intent(ACTION_QUERY_PRINTER_STATE);
+                                intent.putExtra(DEVICE_ID, id);
+                                App.getInstance().sendBroadcast(intent);
+                            }
+                        }
+                    } else if (sendCommand == cpcl) {
+                        if (currentPrinterCommand == null) {
+                            currentPrinterCommand = PrinterCommand.CPCL;
+                            sendStateBroadcast(CONN_STATE_CONNECTED);
+                        } else {
+                            if (cnt == 1) {
+                                if ((buffer[0] & ESC_STATE_PAPER_ERR) > 0) {
+                                    status += "打印机缺纸";
+                                }
+                                if ((buffer[0] & ESC_STATE_COVER_OPEN) > 0) {
+                                    status += "打印机开盖";
+                                }
+                                Log.i("TAG", "状态:" + status);
+                                String mode = "打印模式:CPCL";
+                                Toast.makeText(App.getInstance(), mode + " " + status, Toast.LENGTH_SHORT).show();
+                            } else {//打印机状态查询
+                                Intent intent = new Intent(ACTION_QUERY_PRINTER_STATE);
+                                intent.putExtra(DEVICE_ID, id);
+                                App.getInstance().sendBroadcast(intent);
+                            }
+                        }
+                    }
+                    break;
+                default:
+                    break;
+            }
+        }
+    };
+
+    private DeviceConnFactoryManager(Build build) {
+        this.connMethod = build.connMethod;
+        this.macAddress = build.macAddress;
+        this.port = build.port;
+        this.ip = build.ip;
+        this.mUsbDevice = build.usbDevice;
+        this.mContext = build.context;
+        this.serialPortPath = build.serialPortPath;
+        this.baudrate = build.baudrate;
+        this.id = build.id;
+        deviceConnFactoryManagers[id] = this;
+    }
+
+    public static DeviceConnFactoryManager[] getDeviceConnFactoryManagers() {
+        return deviceConnFactoryManagers;
+    }
+
+    public static void closeAllPort() {
+        for (DeviceConnFactoryManager deviceConnFactoryManager : deviceConnFactoryManagers) {
+            if (deviceConnFactoryManager != null) {
+                Log.e(TAG, "cloaseAllPort() id -> " + deviceConnFactoryManager.id);
+                deviceConnFactoryManager.closePort(deviceConnFactoryManager.id);
+                deviceConnFactoryManagers[deviceConnFactoryManager.id] = null;
+            }
+        }
+    }
+
+    /**
+     * 关闭端口(断开连接)
+     */
+    public void closePort(int id) {
+        if (this.mPort != null) {
+            System.out.println("id -> " + id);
+            if (reader != null) {
+                reader.cancel();
+            }
+            boolean b = this.mPort.closePort();
+            if (b) {
+                this.mPort = null;
+                isOpenPort = false;
+                currentPrinterCommand = null;
+            }
+        }
+        sendStateBroadcast(CONN_STATE_DISCONNECT);
+    }
+
+    /**
+     * 打开端口(开始连接)
+     */
+    public void openPort() {
+        deviceConnFactoryManagers[id].isOpenPort = false;
+        sendStateBroadcast(CONN_STATE_CONNECTING);
+        switch (deviceConnFactoryManagers[id].connMethod) {
+            case BLUETOOTH:
+                System.out.println("id -> " + id);
+                mPort = new BluetoothPort(macAddress);
+                isOpenPort = deviceConnFactoryManagers[id].mPort.openPort();
+                break;
+            case USB:
+                mPort = new UsbPort(mContext, mUsbDevice);
+                isOpenPort = mPort.openPort();
+                if (isOpenPort) {
+                    IntentFilter filter = new IntentFilter(ACTION_USB_DEVICE_DETACHED);
+                    mContext.registerReceiver(usbStateReceiver, filter);
+                }
+                break;
+            case WIFI:
+                mPort = new EthernetPort(ip, port);
+                isOpenPort = mPort.openPort();
+                break;
+            case SERIAL_PORT:
+                mPort = new SerialPort(serialPortPath, baudrate, 0);
+                isOpenPort = mPort.openPort();
+                break;
+            default:
+                break;
+        }
+
+        //端口打开成功后,检查连接打印机所使用的打印机指令ESC、TSC
+        if (isOpenPort) {
+            queryCommand();
+        } else {
+            if (this.mPort != null) {
+                this.mPort = null;
+            }
+            sendStateBroadcast(CONN_STATE_FAILED);
+        }
+    }
+
+    private void sendStateBroadcast(int state) {
+        Intent intent = new Intent(ACTION_CONN_STATE);
+        intent.putExtra(STATE, state);
+        intent.putExtra(DEVICE_ID, id);
+        App.getInstance().sendBroadcast(intent);
+    }
+
+    /**
+     * 查询当前连接打印机所使用打印机指令(ESC(EscCommand.java)、TSC(LabelCommand.java))
+     */
+    private void queryCommand() {
+        //开启读取打印机返回数据线程
+        reader = new PrinterReader();
+        reader.start(); //读取数据线程
+        //查询打印机所使用指令
+        queryPrinterCommand(); //
+    }
+
+    /**
+     * 查询打印机当前使用的指令(TSC、ESC)
+     */
+    private void queryPrinterCommand() {
+        //线程池添加任务
+        ThreadPool.getInstantiation().addTask(new Runnable() {
+            @Override
+            public void run() {
+                //发送ESC查询打印机状态指令
+                sendCommand = esc;
+                Vector<Byte> data = new Vector<>(esc.length);
+                for (int i = 0; i < esc.length; i++) {
+                    data.add(esc[i]);
+                }
+                sendDataImmediately(data); //发送esc数据
+                //开启计时器,隔2000毫秒没有没返回值时发送TSC查询打印机状态指令
+                final ThreadFactoryBuilder threadFactoryBuilder = new ThreadFactoryBuilder("Timer");
+                final ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1, threadFactoryBuilder);
+                scheduledExecutorService.schedule(threadFactoryBuilder.newThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (currentPrinterCommand == null || currentPrinterCommand != PrinterCommand.ESC) {
+                            Log.e(TAG, Thread.currentThread().getName());
+                            //发送TSC查询打印机状态指令
+                            sendCommand = tsc;
+                            Vector<Byte> data = new Vector<>(tsc.length);
+                            for (int i = 0; i < tsc.length; i++) {
+                                data.add(tsc[i]);
+                            }
+                            sendDataImmediately(data);
+                            //开启计时器,隔2000毫秒没有没返回值时发送CPCL查询打印机状态指令
+                            scheduledExecutorService.schedule(threadFactoryBuilder.newThread(new Runnable() {
+                                @Override
+                                public void run() {
+                                    if (currentPrinterCommand == null || (currentPrinterCommand != PrinterCommand.ESC && currentPrinterCommand != PrinterCommand.TSC)) {
+                                        Log.e(TAG, Thread.currentThread().getName());
+                                        //发送CPCL查询打印机状态指令
+                                        sendCommand = cpcl;
+                                        Vector<Byte> data = new Vector<Byte>(cpcl.length);
+                                        for (int i = 0; i < cpcl.length; i++) {
+                                            data.add(cpcl[i]);
+                                        }
+                                        sendDataImmediately(data);
+                                        //开启计时器,隔2000毫秒打印机没有响应者停止读取打印机数据线程并且关闭端口
+                                        scheduledExecutorService.schedule(threadFactoryBuilder.newThread(new Runnable() {
+                                            @Override
+                                            public void run() {
+                                                if (currentPrinterCommand == null) {
+                                                    if (reader != null) {
+                                                        reader.cancel();
+                                                        mPort.closePort();
+                                                        isOpenPort = false;
+                                                        mPort = null;
+                                                        sendStateBroadcast(CONN_STATE_FAILED);
+                                                    }
+                                                }
+                                            }
+                                        }), 2000, TimeUnit.MILLISECONDS);
+                                    }
+                                }
+                            }), 2000, TimeUnit.MILLISECONDS);
+                        }
+                    }
+                }), 2000, TimeUnit.MILLISECONDS);
+            }
+        });
+    }
+
+    public void sendDataImmediately(final Vector<Byte> data) {
+        if (this.mPort == null) {
+            return;
+        }
+        try {
+            this.mPort.writeDataImmediately(data, 0, data.size());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 获取端口连接方式
+     *
+     * @return
+     */
+    public CONN_METHOD getConnMethod() {
+        return connMethod;
+    }
+
+    /**
+     * 获取端口打开状态(true 打开,false 未打开)
+     *
+     * @return
+     */
+    public boolean getConnState() {
+        return isOpenPort;
+    }
+
+    /**
+     * 获取连接蓝牙的物理地址
+     *
+     * @return
+     */
+    public String getMacAddress() {
+        return macAddress;
+    }
+
+    /**
+     * 获取连接网口端口号
+     *
+     * @return
+     */
+    public int getPort() {
+        return port;
+    }
+
+    /**
+     * 获取连接网口的IP
+     *
+     * @return
+     */
+    public String getIp() {
+        return ip;
+    }
+
+    /**
+     * 获取连接的USB设备信息
+     *
+     * @return
+     */
+    public UsbDevice usbDevice() {
+        return mUsbDevice;
+    }
+
+    /**
+     * 获取串口号
+     *
+     * @return
+     */
+    public String getSerialPortPath() {
+        return serialPortPath;
+    }
+
+    /**
+     * 获取波特率
+     *
+     * @return
+     */
+    public int getBaudrate() {
+        return baudrate;
+    }
+
+    /**
+     * 获取当前打印机指令
+     *
+     * @return PrinterCommand
+     */
+    public PrinterCommand getCurrentPrinterCommand() {
+        return deviceConnFactoryManagers[id].currentPrinterCommand;
+    }
+
+    public int readDataImmediately(byte[] buffer) throws IOException {
+        return this.mPort.readData(buffer);
+    }
+
+    /**
+     * 判断是实时状态(10 04 02)还是查询状态(1D 72 01)
+     */
+    private int judgeResponseType(byte r) {
+        return (byte) ((r & FLAG) >> 4);
+    }
+
+    /**
+     * 几种连接方式
+     */
+    public enum CONN_METHOD {
+        //蓝牙连接
+        BLUETOOTH("BLUETOOTH"),
+        //USB连接
+        USB("USB"),
+        //wifi连接
+        WIFI("WIFI"),
+        //串口连接
+        SERIAL_PORT("SERIAL_PORT");
+
+        private String name;
+
+        private CONN_METHOD(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public String toString() {
+            return this.name;
+        }
+    }
+
+    /**
+     * 使用构建者模式传入数据,清晰 解耦
+     */
+    public static final class Build {
+        private String ip;
+        private String macAddress;
+        private UsbDevice usbDevice;
+        private int port;
+        private CONN_METHOD connMethod;
+        private Context context;
+        private String serialPortPath;
+        private int baudrate;
+        private int id;//设置标识符
+
+        public Build setIp(String ip) {
+            this.ip = ip;
+            return this;
+        }
+
+        public Build setMacAddress(String macAddress) {
+            this.macAddress = macAddress;
+            return this;
+        }
+
+        public Build setUsbDevice(UsbDevice usbDevice) {
+            this.usbDevice = usbDevice;
+            return this;
+        }
+
+        public Build setPort(int port) {
+            this.port = port;
+            return this;
+        }
+
+        public Build setConnMethod(CONN_METHOD connMethod) {
+            this.connMethod = connMethod;
+            return this;
+        }
+
+        public Build setContext(Context context) {
+            this.context = context;
+            return this;
+        }
+
+        public Build setId(int id) {
+            this.id = id;
+            return this;
+        }
+
+        public Build setSerialPort(String serialPortPath) {
+            this.serialPortPath = serialPortPath;
+            return this;
+        }
+
+        public Build setBaudrate(int baudrate) {
+            this.baudrate = baudrate;
+            return this;
+        }
+
+        public DeviceConnFactoryManager build() {
+            return new DeviceConnFactoryManager(this);
+        }
+    }
+
+    /**
+     * 开线程读取数据
+     */
+    public class PrinterReader extends Thread {
+        private boolean isRun = false;
+
+        private byte[] buffer = new byte[100];
+
+        public PrinterReader() {
+            isRun = true;
+        }
+
+        @Override
+        public void run() {
+            try {
+                while (isRun) {
+                    //读取打印机返回信息
+                    int len = readDataImmediately(buffer);
+                    if (len > 0) {
+                        Message message = Message.obtain();
+                        message.what = READ_DATA;
+                        Bundle bundle = new Bundle();
+                        bundle.putInt(READ_DATA_CNT, len); //数据长度
+                        bundle.putByteArray(READ_BUFFER_ARRAY, buffer); //数据
+                        message.setData(bundle);
+                        mHandler.sendMessage(message);
+                    }
+                }
+            } catch (Exception e) {
+                if (deviceConnFactoryManagers[id] != null) {
+                    closePort(id);
+                }
+            }
+        }
+
+        public void cancel() {
+            isRun = false;
+        }
+    }
+
+}

+ 19 - 0
app/src/main/java/com/rdgk/cemetery/printer/PrinterCommand.java

@@ -0,0 +1,19 @@
+package com.rdgk.cemetery.printer;
+
+/**
+ * Created by Administrator
+ */
+public enum PrinterCommand {
+    /**
+     * ESC指令
+     */
+    ESC,
+    /**
+     * TSC指令
+     */
+    TSC,
+    /**
+     * CPCL指令
+     */
+    CPCL
+}

+ 27 - 0
app/src/main/java/com/rdgk/cemetery/printer/ThreadFactoryBuilder.java

@@ -0,0 +1,27 @@
+package com.rdgk.cemetery.printer;
+
+
+import androidx.annotation.NonNull;
+
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * Created by Administrator
+ */
+public class ThreadFactoryBuilder implements ThreadFactory {
+
+    private String name;
+    private int counter;
+
+    public ThreadFactoryBuilder(String name) {
+        this.name = name;
+        counter = 1;
+    }
+
+    @Override
+    public Thread newThread(@NonNull Runnable runnable) {
+        Thread thread = new Thread(runnable, name);
+        thread.setName("ThreadFactoryBuilder_" + name + "_" + counter);
+        return thread;
+    }
+}

+ 76 - 0
app/src/main/java/com/rdgk/cemetery/printer/ThreadPool.java

@@ -0,0 +1,76 @@
+package com.rdgk.cemetery.printer;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Created by Administrator
+ */
+public class ThreadPool {
+
+    private static ThreadPool threadPool;
+    /**
+     * java线程池
+     */
+    private ThreadPoolExecutor threadPoolExecutor;
+
+    /**
+     * 最大线程数
+     */
+    private final static int MAX_POOL_COUNTS = 20;
+
+    /**
+     * 线程存活时间
+     */
+    private final static long ALIVETIME = 200L;
+
+    /**
+     * 核心线程数
+     */
+    private final static int CORE_POOL_SIZE = 20;
+
+    /**
+     * 线程池缓存队列
+     */
+    private BlockingQueue<Runnable> mWorkQueue = new ArrayBlockingQueue<>(CORE_POOL_SIZE);
+
+    /**
+     * 为线程池提供创建新线程的功能
+     */
+    private ThreadFactory threadFactory = new ThreadFactoryBuilder("ThreadPool");
+
+    private ThreadPool() {
+        //初始化线程池 核心线程数为20,最大线程数30,线程存活200L,线程队列mWorkQueue,
+        threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_COUNTS, ALIVETIME, TimeUnit.SECONDS, mWorkQueue, threadFactory);
+    }
+
+    public static ThreadPool getInstantiation() {
+        if (threadPool == null) {
+            threadPool = new ThreadPool();
+        }
+        return threadPool;
+    }
+
+    /**
+     * 为线程池添加任务
+     */
+    public void addTask(Runnable runnable) {
+        if (runnable == null) {
+            throw new NullPointerException("addTask(Runnable runnable)传入参数为空");
+        }
+        if (threadPoolExecutor != null && threadPoolExecutor.getActiveCount() < MAX_POOL_COUNTS) {
+            threadPoolExecutor.execute(runnable);
+        }
+    }
+
+    public void stopThreadPool() {
+        if (threadPoolExecutor != null) {
+            threadPoolExecutor.shutdown();
+            threadPoolExecutor = null;
+            threadPool = null;
+        }
+    }
+}

+ 26 - 25
app/src/main/java/com/rdgk/cemetery/view/VersionCheckingUtil.java → app/src/main/java/com/rdgk/cemetery/utils/VersionCheckingUtil.java

@@ -1,8 +1,5 @@
-package com.rdgk.cemetery.view;
+package com.rdgk.cemetery.utils;
 
-import static android.os.Build.VERSION_CODES.Q;
-
-import android.annotation.SuppressLint;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
@@ -16,8 +13,10 @@ import android.util.Log;
 import android.widget.RemoteViews;
 
 import androidx.core.app.NotificationCompat;
+import androidx.core.content.ContextCompat;
 import androidx.core.content.FileProvider;
 
+
 import com.lzy.okgo.OkGo;
 import com.lzy.okgo.model.Progress;
 import com.lzy.okgo.request.GetRequest;
@@ -32,17 +31,20 @@ import com.rdgk.cemetery.downloadmanager.DefaultRetryPolicy;
 import com.rdgk.cemetery.downloadmanager.DownloadRequest;
 import com.rdgk.cemetery.downloadmanager.DownloadStatusListener;
 import com.rdgk.cemetery.downloadmanager.ThinDownloadManager;
+import com.rdgk.cemetery.view.DownloadDialog;
 import com.tencent.trtc.videocall.DeviceUtil;
-import com.rdgk.cemetery.utils.ToastUtil;
+
 
 import java.io.File;
 
+import static android.os.Build.VERSION_CODES.Q;
+
 /**
  * apk版本升级检测类
  */
 public class VersionCheckingUtil {
     private Context mContext;
-    private appVMBean appVMBean;
+    private appVMBean mAppUpDataItem;
     private DownloadDialog downloadDialog;
     private long mkeyTime;
     private int mType;
@@ -55,21 +57,21 @@ public class VersionCheckingUtil {
 
     /**
      * @param context
-     * @param appVMBean
+     * @param appUpDataItem
      * @param type          判断哪个类唤起的
      */
-    public void isChecking(Context context, appVMBean appVMBean, int type) {
+    public void isChecking(Context context, appVMBean appUpDataItem, int type) {
         mContext = context;
-        this.appVMBean = appVMBean;
+        mAppUpDataItem = appUpDataItem;
         mType = type;
 
         //getUpdatelevel 是否强制更新
-        if (!DeviceUtil.getVersionName(mContext).equals(appVMBean.getVersion())) {
-            if (1 == appVMBean.getUpdateLevel()) {
-                myShowDialog(false);
-            } else {
-                myShowDialog(true);
-            }
+        if (!DeviceUtil.getVersionName(mContext).equals(appUpDataItem.getData().getVersion())) {
+//            if (1 == appUpDataItem.getUpdateLevel()) {
+            myShowDialog(false);
+//            } else {
+//                myShowDialog(true);
+//            }
         } else {
             if (mType == 2) {
                 ToastUtil.showToast("已是最新版本!");
@@ -83,9 +85,9 @@ public class VersionCheckingUtil {
     private void myShowDialog(final boolean b) {
         if (downloadDialog == null) {
             downloadDialog = new DownloadDialog(mContext);
-            downloadDialog.setTitle("测到新版本,是否安装?");
+            downloadDialog.setTitle("测到新版本,是否安装?");
             downloadDialog.setIsDismiss(b);
-            downloadDialog.setMessage(appVMBean.getVersionDoc());
+            downloadDialog.setMessage(mAppUpDataItem.getData().getRemark() + "");
             downloadDialog.setOnClickBottomListener(new DownloadDialog.OnClickBottomListener() {
                 @Override
                 public void onPositiveClick() {
@@ -112,14 +114,13 @@ public class VersionCheckingUtil {
         }
     }
 
-    @SuppressLint("NewApi")
     private void downLoadApkNew() {
         String filepath = mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) + "/updateApk/";
-        String filename = "homelifemini.apk";
+        String filename = "homeservicelive.apk";
         //这一步,系统会自动为你在沙盒中创建文件夹
         apkFile = new File(filepath, filename);
         thinDownloadManager = new ThinDownloadManager(DOWNLOAD_THREAD_POOL_SIZE);
-        Uri downloadUri = Uri.parse(appVMBean.getAppApkUrl());
+        Uri downloadUri = Uri.parse(mAppUpDataItem.getData().getUrl());
         Uri destinationUri = Uri.fromFile(apkFile);
         DownloadRequest downloadRequest = new DownloadRequest(downloadUri)
                 .setRetryPolicy(new DefaultRetryPolicy())
@@ -140,7 +141,7 @@ public class VersionCheckingUtil {
 
                     @Override
                     public void onProgress(int id, long totalBytes, long downloadedBytes, int progress) {
-                        Log.e("pwx", "id = " + id + " ;  total = " + totalBytes + " ;  downloaded = " + downloadedBytes + " ; progress = " + progress);
+                        Log.d("llm", "id = " + id + " ;  total = " + totalBytes + " ;  downloaded = " + downloadedBytes + " ; progress = " + progress);
                         downloadDialog.setProgress(progress);
                         RemoteViews remoteViews = new RemoteViews(mContext.getPackageName(), R.layout.notification);
                         //使用notification.xml文件作VIEW
@@ -158,8 +159,8 @@ public class VersionCheckingUtil {
 
     //下载方法
     private void downloadApk() {
-        GetRequest<File> request = OkGo.get(appVMBean.getAppApkUrl());
-        DownloadTask task = OkDownload.request(appVMBean.getVersion(), request).save().register(new DownloadListener(appVMBean.getVersion()) {
+        GetRequest<File> request = OkGo.get(mAppUpDataItem.getData().getUrl());
+        DownloadTask task = OkDownload.request(mAppUpDataItem.getData().getVersion(), request).save().register(new DownloadListener(mAppUpDataItem.getData().getVersion()) {
             @Override
             public void onStart(Progress progress) {
 
@@ -207,7 +208,7 @@ public class VersionCheckingUtil {
         //判读版本是否在7.0以上
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
             //参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致   参数3  共享的文件
-            Uri apkUri = FileProvider.getUriForFile(context, "com.rdgk.cemetery.fileprovider", file);
+            Uri apkUri = FileProvider.getUriForFile(context, "com.example.homeservicelive.fileprovider", file);
             //添加这一句表示对目标应用临时授权该Uri所代表的文件
             intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
             intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
@@ -224,7 +225,7 @@ public class VersionCheckingUtil {
 //            mkeyTime = System.currentTimeMillis();
 //            ToastUtils.show("再按一次退出程序");
 //        } else {
-//            Intent intent = new Intent("com.rdgk.cemetery.mvp.base.BaseMvpActivity");
+//            Intent intent = new Intent("com.sharedtalent.openhr.mvp.base.BaseMvpActivity");
 //            intent.putExtra("closeAll", 1);
 //            mContext.sendBroadcast(intent);//发送广播
 //            Activity activity = null;

+ 11 - 0
app/src/main/java/com/rdgk/cemetery/weiview/AndroidInterface.java

@@ -7,6 +7,7 @@ import android.os.Looper;
 import android.webkit.JavascriptInterface;
 
 import com.just.agentweb.AgentWeb;
+import com.rdgk.cemetery.activity.PrintActivity;
 import com.rdgk.cemetery.event.EventData;
 import com.rdgk.cemetery.event.EventMp3;
 import com.rdgk.cemetery.utils.SharedPreferenceUtil;
@@ -167,4 +168,14 @@ public class AndroidInterface {
             }
         });
     }
+
+    @JavascriptInterface
+    public void Print(String json) {
+        deliver.post(new Runnable() {
+            @Override
+            public void run() {
+                PrintActivity.launch(activity, json);
+            }
+        });
+    }
 }

+ 11 - 0
app/src/main/res/drawable-v24/bg_1.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+	<!-- 实心 -->
+	<solid android:color="@color/white"/>
+	<!-- 圆角 -->
+	<corners android:radius="10dp"/>
+	<stroke
+		android:width="1dp"
+		android:color="#999999" />
+
+</shape>

+ 47 - 0
app/src/main/res/layout/activity_test.xml

@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center"
+    android:orientation="vertical">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/dp_300"
+        android:layout_margin="@dimen/dp_30"
+        android:background="@drawable/bg_1"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/tv_state"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/dp_100"
+            android:gravity="center"
+            android:text="未连接"
+            android:textColor="#000000"
+            android:textSize="20sp" />
+
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="@dimen/dp_150"
+            android:onClick="btnConnect"
+            android:text="连接蓝牙"
+            android:textSize="18sp" />
+
+        <ImageView
+            android:layout_width="@dimen/dp_40"
+            android:layout_height="@dimen/dp_40"
+            android:layout_alignParentEnd="true"
+            android:layout_alignParentRight="true"
+            android:layout_marginTop="@dimen/dp_5"
+            android:layout_marginRight="@dimen/dp_5"
+            android:onClick="BtnClose"
+            android:src="@mipmap/icon_no" />
+    </RelativeLayout>
+
+
+</LinearLayout>

+ 7 - 0
app/src/main/res/layout/bluetooth_device_name_item.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:padding="5dp"
+    android:textColor="@color/white"
+    android:textSize="18sp" />

+ 26 - 0
app/src/main/res/layout/dialog_bluetooth_list.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical">
+
+    <ListView
+        android:id="@+id/lvPairedDevices"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="5dp"
+        android:layout_weight="1"
+        android:stackFromBottom="true" />
+
+    <Button
+        android:id="@+id/btBluetoothScan"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="5dp"
+        android:background="#6200EE"
+        android:padding="15dp"
+        android:text="扫描"
+        android:textColor="@color/white"
+        android:textSize="16sp" />
+
+</LinearLayout>

BIN
app/src/main/res/mipmap-xhdpi/icon_no.png