Browse Source

feat:东信社保读卡器逻辑

xwh 6 months ago
parent
commit
8c28ed5ef0
29 changed files with 1069 additions and 16 deletions
  1. 2 0
      app/build.gradle
  2. 11 0
      app/src/main/java/com/hh/arome/MyApplication.java
  3. 63 0
      app/src/main/java/com/hh/arome/bean/ampe/AmpeAppletResultBean.java
  4. 10 2
      app/src/main/java/com/hh/arome/common/Constants.java
  5. 128 14
      app/src/main/java/com/hh/arome/ui/MainActivity.java
  6. 115 0
      app/src/main/java/com/hh/arome/utlis/log/AppNetLogUtils.java
  7. 1 0
      lib_basecard/.gitignore
  8. 27 0
      lib_basecard/build.gradle
  9. 0 0
      lib_basecard/consumer-rules.pro
  10. 21 0
      lib_basecard/proguard-rules.pro
  11. 26 0
      lib_basecard/src/androidTest/java/com/hh/arome/basecard/ExampleInstrumentedTest.java
  12. 6 0
      lib_basecard/src/main/AndroidManifest.xml
  13. 135 0
      lib_basecard/src/main/java/com/hh/arome/basecard/BaseSocialSecurityCardBean.java
  14. 58 0
      lib_basecard/src/main/java/com/hh/arome/basecard/BaseSocialSecurityCardReader.java
  15. 49 0
      lib_basecard/src/main/java/com/hh/arome/basecard/SocialSecurityCardConfig.java
  16. 20 0
      lib_basecard/src/main/java/com/hh/arome/basecard/listener/SimpleSocialSecurityCardResaultListener.java
  17. 20 0
      lib_basecard/src/main/java/com/hh/arome/basecard/listener/SocialSecurityCardResaultListener.java
  18. 17 0
      lib_basecard/src/test/java/com/hh/arome/basecard/ExampleUnitTest.java
  19. 1 0
      lib_sscard/.gitignore
  20. 27 0
      lib_sscard/build.gradle
  21. 0 0
      lib_sscard/consumer-rules.pro
  22. BIN
      lib_sscard/libs/DonseeDevice.aar
  23. BIN
      lib_sscard/libs/jar_4_2_8.jar
  24. 21 0
      lib_sscard/proguard-rules.pro
  25. 26 0
      lib_sscard/src/androidTest/java/com/hh/arome/lib_sscard/ExampleInstrumentedTest.java
  26. 5 0
      lib_sscard/src/main/AndroidManifest.xml
  27. 261 0
      lib_sscard/src/main/java/com/hh/arome/lib_sscard/DX_SSCardReader.java
  28. 17 0
      lib_sscard/src/test/java/com/hh/arome/lib_sscard/ExampleUnitTest.java
  29. 2 0
      settings.gradle

+ 2 - 0
app/build.gradle

@@ -288,6 +288,8 @@ dependencies {
 
     //副屏库
     implementation project(':secondaryscreen')
+    implementation project(':lib_basecard')
+    implementation project(':lib_sscard')
 }
 repositories {
     mavenCentral()

+ 11 - 0
app/src/main/java/com/hh/arome/MyApplication.java

@@ -1,11 +1,14 @@
 package com.hh.arome;
 
+import android.content.Context;
+
 import com.alipay.arome.aromecli.AromeInit;
 import com.common.lib_base.CommonApplication;
 import com.common.lib_base.aop.annotation.Time;
 import com.elvishew.xlog.LogLevel;
 import com.elvishew.xlog.XLog;
 import com.hh.arome.common.Constants;
+import com.hh.arome.lib_sscard.DX_SSCardReader;
 import com.hh.arome.utlis.log.AppLogUtils;
 import com.hh.arome.utlis.log.CrashLogManager;
 import com.tencent.bugly.crashreport.CrashReport;
@@ -78,6 +81,14 @@ public class MyApplication extends CommonApplication {
         }
     }
 
+    @Override
+    protected void attachBaseContext(Context base) {
+        super.attachBaseContext(base);
+        //在attachBaseContext方法中调用初始化sdk
+        DX_SSCardReader.initPgyerSDK(this);
+    }
+
+
 
 
 }

+ 63 - 0
app/src/main/java/com/hh/arome/bean/ampe/AmpeAppletResultBean.java

@@ -153,6 +153,21 @@ public class AmpeAppletResultBean {
          */
         Integer getSecondaryScreenState;
 
+        /**
+         *
+         * 社保卡新增字段,有些字段与上方字段复用
+         *
+         */
+        private String cardNumber="";
+        private String idNumber="";
+        private String issueDate="";
+        private String expireDate="";
+        private String fullVersion="";
+        private String cityCode="";
+
+
+
+
         public String getVoiceContent() {
             return voiceContent;
         }
@@ -436,6 +451,54 @@ public class AmpeAppletResultBean {
             this.getSecondaryScreenState = getSecondaryScreenState;
         }
 
+        public String getCardNumber() {
+            return cardNumber;
+        }
+
+        public void setCardNumber(String cardNumber) {
+            this.cardNumber = cardNumber;
+        }
+
+        public String getIdNumber() {
+            return idNumber;
+        }
+
+        public void setIdNumber(String idNumber) {
+            this.idNumber = idNumber;
+        }
+
+        public String getIssueDate() {
+            return issueDate;
+        }
+
+        public void setIssueDate(String issueDate) {
+            this.issueDate = issueDate;
+        }
+
+        public String getExpireDate() {
+            return expireDate;
+        }
+
+        public void setExpireDate(String expireDate) {
+            this.expireDate = expireDate;
+        }
+
+        public String getFullVersion() {
+            return fullVersion;
+        }
+
+        public void setFullVersion(String fullVersion) {
+            this.fullVersion = fullVersion;
+        }
+
+        public String getCityCode() {
+            return cityCode;
+        }
+
+        public void setCityCode(String cityCode) {
+            this.cityCode = cityCode;
+        }
+
         @Override
         public String toString() {
             return "Data{" +

+ 10 - 2
app/src/main/java/com/hh/arome/common/Constants.java

@@ -107,6 +107,7 @@ public class Constants {
 
         public static final String LOG_SECONDARY_SCREEN_PAGE = "副屏---";
 
+        public static final String LOG_SOCIAL_SECURITY_CARD = "社保卡---";
 
         // 对应web的日志类型
         public static final String NET_LOGCAT = "Logcat";
@@ -179,11 +180,18 @@ public class Constants {
 
         //开启副屏
         public static final String ACTION_OPENSECONDARYSCREEN = "openSecondaryScreen";
-
+        //关闭副屏
         public static final String ACTION_CLOSESECONDARYSCREEN = "closeSecondaryScreen";
-
+        //获取副屏显示状态
         public static final String ACTION_SECONDARYSCREENSTATE = "getSecondaryScreenState";
 
+        //社保卡读卡器配置
+        public static final String ACTION_SOCIALSECURITYCARDCONFIG = "socialSecurityCardConfig";
+        //获取社保卡信息
+        public static final String ACTION_SOCIALSECURITYCARDINFO = "getSocialSecurityCardInfo";
+        //社保卡读卡器信息监听
+        public static final String EVENT_SOCIALSECURITYCARD_LISTENER = "socialSecurityCardListener";
+
         public static final String AMPE_EVENT = "";
 
         public static final String AMPE_EVENT_CLOSE = "close";

+ 128 - 14
app/src/main/java/com/hh/arome/ui/MainActivity.java

@@ -1,6 +1,5 @@
 package com.hh.arome.ui;
 
-import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.ServiceConnection;
@@ -31,18 +30,13 @@ import com.alipay.iot.bpaas.api.BPaaSInitCallback;
 import com.alipay.iot.bpaas.api.service.BPaaSCallback;
 import com.alipay.iot.bpaas.api.service.BPaaSResponse;
 import com.blankj.utilcode.util.FileUtils;
-import com.common.face.api.FaceUtil;
 import com.common.lib_base.aop.annotation.NoDoubleClick;
 import com.common.lib_base.common.async.ThreadPoolManager;
 import com.common.lib_base.common.local.AppLocalConfigHandler;
 import com.common.lib_base.utils.GlideUtils;
 import com.common.lib_base.utils.NetworkUtils;
 import com.common.lib_base.utils.StringUtils;
-import com.common.lib_base.utils.TimeUtils;
-import com.common.lib_base.utils.app.AppUtils;
 import com.common.lib_base.utils.ui.ToastUtils;
-import com.common.lib_base.utils.ui.UIUtils;
-import com.common.pos.api.util.ShellUtils;
 
 
 import android.app.Activity;
@@ -75,6 +69,7 @@ import androidx.annotation.NonNull;
 import com.alipay.iot.bpaas.api.InnerApi;
 import com.alipay.iot.bpaas.api.ipc.IpcChannel;
 import com.alipay.iot.bpaas.api.ipc.IpcListener;
+import com.common.lib_base.utils.ui.UIUtils;
 import com.common.print.BasePrinter;
 import com.common.print.IPrinter;
 import com.common.print.callback.PrintInitResultCallback;
@@ -84,6 +79,11 @@ import com.google.gson.JsonObject;
 import com.hh.arome.BuildConfig;
 import com.hh.arome.MyApplication;
 import com.hh.arome.R;
+import com.hh.arome.basecard.BaseSocialSecurityCardBean;
+import com.hh.arome.basecard.BaseSocialSecurityCardReader;
+import com.hh.arome.basecard.SocialSecurityCardConfig;
+import com.hh.arome.basecard.listener.SimpleSocialSecurityCardResaultListener;
+import com.hh.arome.basecard.listener.SocialSecurityCardResaultListener;
 import com.hh.arome.bean.AlipayUserInfoRequestBean;
 import com.hh.arome.bean.AlipayUserInfoResultBean;
 import com.hh.arome.bean.BizContentBean;
@@ -112,9 +112,9 @@ import com.hh.arome.common.scan.idcard.IDCardScan;
 import com.hh.arome.common.scan.idcard.bean.IDCardInfoBean;
 import com.hh.arome.common.scan.idcard.callback.IDCardInitResultCallback;
 import com.hh.arome.common.scan.idcard.callback.IDCardScanResultCallback;
-import com.hh.arome.common.voice.BaiduVoice;
 import com.hh.arome.common.voice.MTTSDemo;
 import com.hh.arome.helper.Serial.SerialPortFinder;
+import com.hh.arome.lib_sscard.DX_SSCardReader;
 import com.hh.arome.mvp.contract.AlipayUserInfoContract;
 import com.hh.arome.mvp.contract.DeviceConfigContract;
 import com.hh.arome.mvp.contract.HeartbeatContract;
@@ -133,8 +133,8 @@ import com.hh.arome.services.keeplive.RemoteService;
 import com.hh.arome.ui.base.BaseHHActivity;
 import com.hh.arome.utlis.DateUtil;
 import com.hh.arome.utlis.IdCardUtils;
+import com.hh.arome.utlis.log.AppNetLogUtils;
 import com.telpo.tps508.PrintContentBean;
-import com.telpo.tps508.PrintUtile;
 import com.hh.arome.utlis.device.DeviceUtils;
 import com.hh.arome.utlis.device.FaceScenicUtile;
 import com.hh.arome.utlis.log.AppLogUtils;
@@ -181,6 +181,8 @@ import static com.hh.arome.common.Constants.Ampe.ACTION_MICROPHONE_STATE;
 import static com.hh.arome.common.Constants.Ampe.ACTION_PRINT;
 import static com.hh.arome.common.Constants.Ampe.ACTION_QR;
 import static com.hh.arome.common.Constants.Ampe.ACTION_SCAN_FACE;
+import static com.hh.arome.common.Constants.Ampe.ACTION_SOCIALSECURITYCARDCONFIG;
+import static com.hh.arome.common.Constants.Ampe.ACTION_SOCIALSECURITYCARDINFO;
 import static com.hh.arome.common.Constants.Ampe.ACTION_SPEECH;
 import static com.hh.arome.common.Constants.Ampe.ACTION_SPEECH_STOP;
 import static com.hh.arome.common.Constants.Ampe.ACTION_START_INFRARED_INDUCTION_LISTENER;
@@ -194,6 +196,7 @@ import static com.hh.arome.common.Constants.Ampe.EVENT_IDCard_LISTENER;
 import static com.hh.arome.common.Constants.Ampe.EVENT_INFRARED_INDUCTION_LISTENER;
 import static com.hh.arome.common.Constants.Ampe.EVENT_MICROPHONE_LISTENER;
 import static com.hh.arome.common.Constants.Ampe.EVENT_QR_LISTENER;
+import static com.hh.arome.common.Constants.Ampe.EVENT_SOCIALSECURITYCARD_LISTENER;
 import static com.hh.arome.common.Constants.LogcatValue.LINE;
 import static com.hh.arome.common.Constants.LogcatValue.LOG_NODE_AIDL;
 import static com.hh.arome.common.Constants.LogcatValue.LOG_NODE_APPLET;
@@ -204,10 +207,10 @@ import static com.hh.arome.common.Constants.LogcatValue.LOG_NODE_INFRARED_INDUCT
 import static com.hh.arome.common.Constants.LogcatValue.LOG_NODE_MICROPHONE;
 import static com.hh.arome.common.Constants.LogcatValue.LOG_NODE_NET;
 import static com.hh.arome.common.Constants.LogcatValue.LOG_NODE_NET_CONFIG_QUERY;
-import static com.hh.arome.common.Constants.LogcatValue.LOG_NODE_NET_HEARTBEAT;
 import static com.hh.arome.common.Constants.LogcatValue.LOG_NODE_QR;
 import static com.hh.arome.common.Constants.LogcatValue.LOG_NODE_SPEECH;
 import static com.hh.arome.common.Constants.LogcatValue.LOG_PRINT;
+import static com.hh.arome.common.Constants.LogcatValue.LOG_SOCIAL_SECURITY_CARD;
 import static com.hh.arome.common.Constants.LogcatValue.LOG_SPEECH;
 import static com.hh.arome.common.Constants.LogcatValue.NET_CRASH;
 import static com.hh.arome.common.Constants.LogcatValue.NET_ERROR;
@@ -225,7 +228,6 @@ import static com.hh.arome.common.Constants.Value.INDUCTION_PEOPLE_YES;
 import static com.hh.arome.common.Constants.Value.TIME_HEARTBEAT;
 import static com.hh.arome.common.Constants.Value.TIME_INDUCTION_INTERVAL;
 import static com.hh.arome.common.Constants.Value.TOKEN;
-import static org.apache.log4j.Layout.LINE_SEP;
 
 
 public class MainActivity extends BaseHHActivity implements DeviceConfigContract.View,
@@ -272,7 +274,7 @@ public class MainActivity extends BaseHHActivity implements DeviceConfigContract
     private TextView tv_idcard_info;
     private TextView tv_scan_result;
     private Button tv_voice;
-
+    BaseSocialSecurityCardReader reader;
     @Override
     public int setLayout() {
         if (Constants.DeviceModel.D2.equals(deviceModel)) {
@@ -2593,6 +2595,28 @@ public class MainActivity extends BaseHHActivity implements DeviceConfigContract
                 }else  if(Constants.Ampe.ACTION_SECONDARYSCREENSTATE.equals(ampeAppletRequestBean.getAction())){
                     //副屏显示状态
                     getSecondaryScreen(ampeAppletRequestBean,bridgeCallback);
+                }else if(ACTION_SOCIALSECURITYCARDINFO.equals(ampeAppletRequestBean.getAction())){
+                    AmpeActionDataBean SocialSecurityCardInfoBean = new AmpeActionDataBean();
+                    SocialSecurityCardInfoBean.setTaskId(ampeAppletRequestBean.getTaskId());
+                    SocialSecurityCardInfoBean.setBridgeCallback(bridgeCallback);
+                    SocialSecurityCardInfoBean.setEvent(ampeAppletRequestBean.getEvent());
+                    ampeActionMap.put(ACTION_SOCIALSECURITYCARDINFO, SocialSecurityCardInfoBean);
+                    //启动社保卡读卡器
+                    startSSCardReader();
+                }else if(ACTION_SOCIALSECURITYCARDCONFIG.equals(ampeAppletRequestBean.getAction())){
+                    //启动社保卡读卡器
+                    startSSCardReader();
+                    AmpeAppletResultBean ssConfigBean = new AmpeAppletResultBean();
+                    ssConfigBean.setAction(ACTION_SOCIALSECURITYCARDCONFIG);
+                    ssConfigBean.setEvent(ampeAppletRequestBean.getEvent());
+                    ssConfigBean.setTaskId(ampeAppletRequestBean.getTaskId());
+                    ssConfigBean.setSuccess(true);
+                    ssConfigBean.setMessage("成功");
+                    JsonObject jsonObject = gson.toJsonTree(ssConfigBean).getAsJsonObject();
+                    if (bridgeCallback != null) {
+                        bridgeCallback.callback(jsonObject.toString());
+                    }
+
                 }
 
             }
@@ -3036,6 +3060,93 @@ public class MainActivity extends BaseHHActivity implements DeviceConfigContract
         }
     }
 
+    /**
+     *
+     * desc:发送社保卡信息数据
+     * @author xia weihao
+     * @date 2024/6/25
+     *
+     */ 
+    private void sendSSCardtoApplet(String jsonStr) {
+        // 监听,主动推送给小程序
+        sendMessageToApplet(Constants.Ampe.EVENT_SOCIALSECURITYCARD_LISTENER, jsonStr);
+        // 单次发送给小程序
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                AmpeActionDataBean ampeActionDataBean = ampeActionMap.get(ACTION_SOCIALSECURITYCARDINFO);
+                ampeActionMap.remove(ACTION_SOCIALSECURITYCARDINFO);
+                if (ampeActionDataBean == null) {
+                    return;
+                }
+                AromeServiceInvoker.BridgeCallback bridgeCallback = null;
+                try {
+                    bridgeCallback = ampeActionDataBean.getBridgeCallback();
+                } catch (NullPointerException e) {
+                    e.printStackTrace();
+                }
+
+                AmpeAppletResultBean bean = new AmpeAppletResultBean();
+                bean.setAction(ACTION_SOCIALSECURITYCARDINFO);
+                bean.setEvent(ampeActionDataBean.getEvent());
+                bean.setTaskId(ampeActionDataBean.getTaskId());
+                bean.setSuccess(true);
+                bean.setMessage("成功");
+                AmpeAppletResultBean.Data dataBean = gson.fromJson(jsonStr,AmpeAppletResultBean.Data.class);
+                bean.setData(dataBean);
+
+
+
+                // 回传处理结果给小程序
+                try {
+                    JsonObject jsonObject = gson.toJsonTree(bean).getAsJsonObject();
+                    if (bridgeCallback != null) {
+                        bridgeCallback.callback(jsonObject.toString());
+                    }
+                } catch (Throwable t) {
+                    AppLogUtils.e("onCalled--t" + t);
+                }
+            }
+        });
+    }
+
+    /**
+     *
+     * desc:启动社保卡读卡器
+     * @author xia weihao
+     * @date 2024/6/25
+     *
+     */ 
+    private void startSSCardReader() {
+        if (reader == null) {
+            synchronized (MainActivity.class) {
+                if(reader==null) {
+                    reader = new DX_SSCardReader();
+                    reader.init(MainActivity.this);
+
+                    SocialSecurityCardConfig config = new SocialSecurityCardConfig();
+                    config.setnType(1);
+                    config.setSlotPSAM(0x11);
+                    reader.setConfig(config);
+                    reader.setListener(new SimpleSocialSecurityCardResaultListener() {
+                        @Override
+                        public void onSuccess(BaseSocialSecurityCardBean data) {
+                         //   AppLogUtils.i("_____________123"+data.getAllInfoJson());
+                            sendSSCardtoApplet(data.getAllInfoJson());
+
+                        }
+
+                        @Override
+                        public void onInfoLog(String infoMsg) {
+                            AppNetLogUtils.sendLogs(mLogcatAddPresenter, isNetAvailable,
+                                    LOG_SOCIAL_SECURITY_CARD, infoMsg);
+                        }
+                    });
+                    reader.startRead();
+                }
+            }
+        }
+    }
 
     /**
      *
@@ -3069,7 +3180,7 @@ public class MainActivity extends BaseHHActivity implements DeviceConfigContract
             LogcatAddRequestBean logBean = new LogcatAddRequestBean();
             logBean.setLogType(NET_LOGCAT);
             // 对应web端"日志标签"
-            logBean.setLogTag(logLine + WARP + LOG_NODE_APPLET + LOG_NODE_MICROPHONE);
+            logBean.setLogTag(logLine + WARP + LOG_NODE_APPLET + action);
             logBean.setLogContent(logContentSb.toString());
             requestLogcatAdd(logBean);
             // 日志开始----------------end
@@ -3265,6 +3376,8 @@ public class MainActivity extends BaseHHActivity implements DeviceConfigContract
                 } else if (eventName.equals(EVENT_INFRARED_INDUCTION_LISTENER)) {
                     // 开启红外感应持续监听
                     type = EVENT_INFRARED_INDUCTION_LISTENER;
+                }else  if(eventName.equals(EVENT_SOCIALSECURITYCARD_LISTENER)){
+                    type=LOG_SOCIAL_SECURITY_CARD;
                 }
 
                 // 日志行数——对应web端"日志标签"
@@ -6333,9 +6446,10 @@ public class MainActivity extends BaseHHActivity implements DeviceConfigContract
     @Override
     protected void onDestroy() {
         AppLogUtils.e(mTag + "onDestroy");
-
         onDestroyUnregister();
-
+        if(reader!=null){
+            reader.release(MainActivity.this);
+        }
         super.onDestroy();
 
 

+ 115 - 0
app/src/main/java/com/hh/arome/utlis/log/AppNetLogUtils.java

@@ -0,0 +1,115 @@
+package com.hh.arome.utlis.log;
+
+import static com.hh.arome.common.Constants.LogcatValue.LINE;
+import static com.hh.arome.common.Constants.LogcatValue.LOG_NODE_APPLET;
+import static com.hh.arome.common.Constants.LogcatValue.LOG_NODE_MICROPHONE;
+import static com.hh.arome.common.Constants.LogcatValue.NET_LOGCAT;
+import static com.hh.arome.common.Constants.LogcatValue.NODE;
+import static com.hh.arome.common.Constants.LogcatValue.WARP;
+import static com.hh.arome.common.Constants.Value.TOKEN;
+
+import com.google.gson.JsonObject;
+import com.hh.arome.bean.LogcatAddRequestBean;
+import com.hh.arome.mvp.presenter.LogcatAddPresenter;
+import com.hh.arome.utlis.device.DeviceUtils;
+
+/**
+ * @Description:
+ * @author: Xia WeiHao
+ * @date: 2024/6/25
+ */
+public class AppNetLogUtils {
+
+
+    public static void sendLogs(LogcatAddPresenter presenter, boolean isNetAvailable,
+                          String action, JsonObject jsonObject, String defaultLog) {
+        try {
+            // 日志开始----------------begin
+            // 日志行数——对应web端"日志标签"
+            String logLine = (new Throwable().getStackTrace())[0].toString();
+            // 日志节点
+            String logNode = action + "--回传处理结果给小程序--";
+            // 日志内容
+            StringBuilder logContentSb = new StringBuilder();
+            logContentSb.append(logNode).append(defaultLog).append(WARP)
+                    .append("jsonObject = ").append(jsonObject);
+
+            // 开始保存本地日志
+            AppLogUtils.saveLog(LogType.Logcat, new StringBuilder()
+                    .append(LINE)
+                    .append(logLine).append(WARP)
+                    .append(NODE)
+                    .append(logContentSb)
+                    .toString()
+            );
+
+            // 开始网络在线日志
+            LogcatAddRequestBean logBean = new LogcatAddRequestBean();
+            logBean.setLogType(NET_LOGCAT);
+            // 对应web端"日志标签"
+            logBean.setLogTag(logLine + WARP + LOG_NODE_APPLET + action);
+            logBean.setLogContent(logContentSb.toString());
+            requestLogcatAdd(presenter,isNetAvailable,logBean);
+            // 日志开始----------------end
+
+            // 打印编译器输出日志
+            AppLogUtils.e(logContentSb);
+
+        } catch (Throwable t) {
+            AppLogUtils.e("onCalled--t" + t);
+        }
+    }
+
+
+    public static void sendLogs(LogcatAddPresenter presenter, boolean isNetAvailable,
+                                String action, String errLog) {
+        try {
+            // 日志开始----------------begin
+            // 日志行数——对应web端"日志标签"
+            String logLine = (new Throwable().getStackTrace())[0].toString();
+            // 日志节点
+            String logNode = action + "--错误日志--";
+            // 日志内容
+            StringBuilder logContentSb = new StringBuilder();
+            logContentSb.append(logNode).append(errLog);
+
+
+            // 开始保存本地日志
+            AppLogUtils.saveLog(LogType.Logcat, new StringBuilder()
+                    .append(LINE)
+                    .append(logLine).append(WARP)
+                    .append(NODE)
+                    .append(logContentSb)
+                    .toString()
+            );
+
+            // 开始网络在线日志
+            LogcatAddRequestBean logBean = new LogcatAddRequestBean();
+            logBean.setLogType(NET_LOGCAT);
+            // 对应web端"日志标签"
+            logBean.setLogTag(logLine + WARP + LOG_NODE_APPLET + action);
+            logBean.setLogContent(logContentSb.toString());
+            requestLogcatAdd(presenter,isNetAvailable,logBean);
+            // 日志开始----------------end
+
+            // 打印编译器输出日志
+            AppLogUtils.e(logContentSb);
+
+        } catch (Throwable t) {
+            AppLogUtils.e("onCalled--t" + t);
+        }
+    }
+
+    private static void requestLogcatAdd(LogcatAddPresenter presenter, boolean isNetAvailable,LogcatAddRequestBean bean) {
+        if(presenter==null){
+            return;
+        }
+        bean.setToken(TOKEN);
+        bean.setSn(DeviceUtils.getDeviceSN());
+        if (isNetAvailable) {
+            presenter.requestLogcatAdd(bean);
+        }
+
+    }
+
+}

+ 1 - 0
lib_basecard/.gitignore

@@ -0,0 +1 @@
+/build

+ 27 - 0
lib_basecard/build.gradle

@@ -0,0 +1,27 @@
+plugins {
+    id 'com.android.library'
+    id 'org.jetbrains.kotlin.android'
+    id 'kotlin-android-extensions'
+}
+android {
+    compileSdkVersion rootProject.ext.android["compileSdkVersion"]
+    buildToolsVersion rootProject.ext.android["buildToolsVersion"]
+
+    defaultConfig {
+
+        minSdkVersion 19
+        targetSdkVersion 25
+        versionCode 1
+        versionName "1.0"
+
+    }
+
+}
+
+dependencies {
+    implementation fileTree(include: ['*.jar'], dir: 'libs')
+    implementation 'androidx.appcompat:appcompat:1.3.0-alpha02'//1.1.0
+    implementation 'com.google.android.material:material:1.1.0'
+    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+    implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
+}

+ 0 - 0
lib_basecard/consumer-rules.pro


+ 21 - 0
lib_basecard/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 26 - 0
lib_basecard/src/androidTest/java/com/hh/arome/basecard/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.hh.arome.basecard;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        assertEquals("com.hh.arome.basecard.test", appContext.getPackageName());
+    }
+}

+ 6 - 0
lib_basecard/src/main/AndroidManifest.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+
+    package="com.hh.arome.lib_basecard">
+
+</manifest>

+ 135 - 0
lib_basecard/src/main/java/com/hh/arome/basecard/BaseSocialSecurityCardBean.java

@@ -0,0 +1,135 @@
+package com.hh.arome.basecard;
+
+import com.google.gson.JsonObject;
+
+/**
+ * @Description:
+ * @author: Xia WeiHao
+ * @date: 2024/6/24
+ */
+public class BaseSocialSecurityCardBean {
+
+    public String cardNumber="";
+
+    public String name="";
+    public String sex="";
+
+    public String idNumber="";
+    public String birthDate="";
+    public String issueDate="";
+    public String expireDate="";
+    public String fullVersion="";
+    public String nation="";
+    public String cityCode="";
+
+    public String address="";
+
+    public BaseSocialSecurityCardBean() {
+    }
+
+    public String getIdNumber() {
+        return idNumber;
+    }
+
+    public void setIdNumber(String idNumber) {
+        this.idNumber = idNumber;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getSex() {
+        return sex;
+    }
+
+    public void setSex(String sex) {
+        this.sex = sex;
+    }
+
+
+
+    public String getBirthDate() {
+        return birthDate;
+    }
+
+    public void setBirthDate(String birthDate) {
+        this.birthDate = birthDate;
+    }
+
+    public String getIssueDate() {
+        return issueDate;
+    }
+
+    public void setIssueDate(String issueDate) {
+        this.issueDate = issueDate;
+    }
+
+    public String getExpireDate() {
+        return expireDate;
+    }
+
+    public void setExpireDate(String expireDate) {
+        this.expireDate = expireDate;
+    }
+
+    public String getFullVersion() {
+        return fullVersion;
+    }
+
+    public void setFullVersion(String fullVersion) {
+        this.fullVersion = fullVersion;
+    }
+
+    public String getNation() {
+        return nation;
+    }
+
+    public void setNation(String nation) {
+        this.nation = nation;
+    }
+
+    public String getCityCode() {
+        return cityCode;
+    }
+
+    public void setCityCode(String cityCode) {
+        this.cityCode = cityCode;
+    }
+
+    public String toString() {
+        return "姓名: " + this.name + '\n' + "性别: " + this.sex + '\n' + "民族: " + this.nation + '\n' + "地址: " + this.address + '\n'+ "出生日期: " + this.birthDate + '\n' + "发证日期: " + this.issueDate + '\n' + "有效日期: " + this.expireDate + '\n' + "卡号: " + this.cardNumber + '\n' + "社会保障号码: " + this.idNumber + '\n' + "城市代码: " + this.cityCode + '\n' + "社保卡版本: " + this.fullVersion + '\n';
+    }
+    public String getBasicsInfoJson(){
+        JsonObject jsonObject=new JsonObject();
+        jsonObject.addProperty("cardNumber",cardNumber);
+        jsonObject.addProperty("name",name);
+        jsonObject.addProperty("sex",sex);
+        jsonObject.addProperty("birthDate",birthDate);
+        jsonObject.addProperty("idNumber",idNumber);
+        return jsonObject.toString();
+    }
+
+
+    public String getAllInfoJson(){
+        JsonObject jsonObject=new JsonObject();
+        jsonObject.addProperty("cardNumber",cardNumber);
+        jsonObject.addProperty("name",name);
+        jsonObject.addProperty("sex",sex);
+        jsonObject.addProperty("nation",nation);
+        jsonObject.addProperty("address",address);
+        jsonObject.addProperty("birthDate",birthDate);
+        jsonObject.addProperty("idNumber",idNumber);
+        jsonObject.addProperty("issueDate",issueDate);
+        jsonObject.addProperty("expireDate",expireDate);
+        jsonObject.addProperty("nation",nation);
+        jsonObject.addProperty("cityCode",cityCode);
+        jsonObject.addProperty("fullVersion",fullVersion);
+        return jsonObject.toString();
+    }
+
+}

+ 58 - 0
lib_basecard/src/main/java/com/hh/arome/basecard/BaseSocialSecurityCardReader.java

@@ -0,0 +1,58 @@
+package com.hh.arome.basecard;
+
+import android.content.Context;
+
+import com.hh.arome.basecard.listener.SocialSecurityCardResaultListener;
+
+/**
+ * @Description:
+ * @author: Xia WeiHao
+ * @date: 2024/6/24
+ */
+public abstract class BaseSocialSecurityCardReader {
+
+    private int mCardReadState=0; //0 设备未连接  1 已加载读卡器 2 插入USB设备 3  拔出USB设备
+
+    SocialSecurityCardConfig config;
+
+    public SocialSecurityCardResaultListener listener;
+
+    public BaseSocialSecurityCardReader() {
+    }
+
+    public BaseSocialSecurityCardReader(SocialSecurityCardConfig config, SocialSecurityCardResaultListener listener) {
+        this.config = config;
+        this.listener = listener;
+    }
+
+    public void setConfig(SocialSecurityCardConfig config) {
+        this.config = config;
+    }
+
+    public SocialSecurityCardConfig getConfig() {
+        return config;
+    }
+
+    public abstract void init(Context context);
+
+
+    public int getmCardReadState() {
+        return mCardReadState;
+    }
+
+    public void setmCardReadState(int mCardReadState) {
+        this.mCardReadState = mCardReadState;
+    }
+
+    public SocialSecurityCardResaultListener getListener() {
+        return listener;
+    }
+
+    public void setListener(SocialSecurityCardResaultListener listener) {
+        this.listener = listener;
+    }
+    public abstract void startRead();
+    public abstract void  stopRead();
+
+    public abstract void release(Context context);
+}

+ 49 - 0
lib_basecard/src/main/java/com/hh/arome/basecard/SocialSecurityCardConfig.java

@@ -0,0 +1,49 @@
+package com.hh.arome.basecard;
+
+/**
+ * @Description:
+ * @author: Xia WeiHao
+ * @date: 2024/6/24
+ */
+public class SocialSecurityCardConfig {
+
+   private int slotPSAM;
+    private int nType;
+
+    private int repeatIntervalTime=-1;
+
+    private long singleTimeoutTime=0L;
+
+
+    public int getSlotPSAM() {
+        return slotPSAM;
+    }
+
+    public void setSlotPSAM(int slotPSAM) {
+        this.slotPSAM = slotPSAM;
+    }
+
+    public int getnType() {
+        return nType;
+    }
+
+    public void setnType(int nType) {
+        this.nType = nType;
+    }
+
+    public int getRepeatIntervalTime() {
+        return repeatIntervalTime;
+    }
+
+    public void setRepeatIntervalTime(int repeatIntervalTime) {
+        this.repeatIntervalTime = repeatIntervalTime;
+    }
+
+    public long getSingleTimeoutTime() {
+        return singleTimeoutTime;
+    }
+
+    public void setSingleTimeoutTime(long singleTimeoutTime) {
+        this.singleTimeoutTime = singleTimeoutTime;
+    }
+}

+ 20 - 0
lib_basecard/src/main/java/com/hh/arome/basecard/listener/SimpleSocialSecurityCardResaultListener.java

@@ -0,0 +1,20 @@
+package com.hh.arome.basecard.listener;
+
+/**
+ * @Description:
+ * @author: Xia WeiHao
+ * @date: 2024/6/25
+ */
+public abstract class SimpleSocialSecurityCardResaultListener implements SocialSecurityCardResaultListener {
+
+
+    @Override
+    public void onFail(String errMsg) {
+
+    }
+
+    @Override
+    public void onError(String errMsg) {
+
+    }
+}

+ 20 - 0
lib_basecard/src/main/java/com/hh/arome/basecard/listener/SocialSecurityCardResaultListener.java

@@ -0,0 +1,20 @@
+package com.hh.arome.basecard.listener;
+
+import com.hh.arome.basecard.BaseSocialSecurityCardBean;
+
+/**
+ * @Description:
+ * @author: Xia WeiHao
+ * @date: 2024/6/24
+ */
+public interface SocialSecurityCardResaultListener {
+
+    void onSuccess(BaseSocialSecurityCardBean data);
+    void onFail(String errMsg);
+
+    void onError(String errMsg);
+
+    void onInfoLog(String infoMsg);
+
+
+}

+ 17 - 0
lib_basecard/src/test/java/com/hh/arome/basecard/ExampleUnitTest.java

@@ -0,0 +1,17 @@
+package com.hh.arome.basecard;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() {
+        assertEquals(4, 2 + 2);
+    }
+}

+ 1 - 0
lib_sscard/.gitignore

@@ -0,0 +1 @@
+/build

+ 27 - 0
lib_sscard/build.gradle

@@ -0,0 +1,27 @@
+plugins {
+    id 'com.android.library'
+    id 'org.jetbrains.kotlin.android'
+    id 'kotlin-android-extensions'
+}
+android {
+    compileSdkVersion rootProject.ext.android["compileSdkVersion"]
+    buildToolsVersion rootProject.ext.android["buildToolsVersion"]
+
+    defaultConfig {
+
+        minSdkVersion 19
+        targetSdkVersion 25
+        versionCode 1
+        versionName "1.0"
+
+    }
+
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
+    implementation 'androidx.appcompat:appcompat:1.3.0-alpha02'//1.1.0
+    implementation 'com.google.android.material:material:1.1.0'
+    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+    implementation project(':lib_basecard')
+}

+ 0 - 0
lib_sscard/consumer-rules.pro


BIN
lib_sscard/libs/DonseeDevice.aar


BIN
lib_sscard/libs/jar_4_2_8.jar


+ 21 - 0
lib_sscard/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 26 - 0
lib_sscard/src/androidTest/java/com/hh/arome/lib_sscard/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.hh.arome.lib_sscard;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        assertEquals("com.hh.arome.lib_sscard.test", appContext.getPackageName());
+    }
+}

+ 5 - 0
lib_sscard/src/main/AndroidManifest.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.hh.arome.lib_sscard">
+
+</manifest>

+ 261 - 0
lib_sscard/src/main/java/com/hh/arome/lib_sscard/DX_SSCardReader.java

@@ -0,0 +1,261 @@
+package com.hh.arome.lib_sscard;
+
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbManager;
+import android.os.Build;
+
+import com.donsee.bean.SciCardInfo;
+import com.donsee.devices.CardReader;
+import com.donsee.devices.LogUtils;
+import com.hh.arome.basecard.BaseSocialSecurityCardBean;
+import com.hh.arome.basecard.BaseSocialSecurityCardReader;
+import com.hh.arome.basecard.SocialSecurityCardConfig;
+import com.pgyer.pgyersdk.PgyerSDKManager;
+
+import java.util.HashMap;
+
+/**
+ * @Description:
+ * @author: Xia WeiHao
+ * @date: 2024/6/24
+ */
+public class DX_SSCardReader extends BaseSocialSecurityCardReader {
+
+    private UsbDevice usbDevice;
+    private UsbManager usbManager;
+    private PendingIntent mPendingIntent;
+    private int pid = 57407;
+    private int vid = 1742;
+    private final String ACTION_USB_PERMISSION = "com.donsee.devices.DonseeDeviceActivity.USB_PERMISSION";
+    long result = -1;
+
+    private USBReceiver mUsbReceiver;
+
+    private CardReader cardReader;
+    private CReaderThread cReaderDataThread;
+
+    private volatile boolean isRuning = false;
+
+    private boolean isStop = false;
+
+
+    public static void initPgyerSDK(Context context) {
+        new PgyerSDKManager.Init()
+                .setContext(context) //设置上下问对象
+                .start();
+    }
+
+    @Override
+    public void init(Context context) {
+        cardReader = new CardReader(context);
+        initUSB(context);
+        result = cardReader.Donsee_Open("USB");
+        if (result == 0) {
+            setmCardReadState(1);
+        }
+        if (listener != null) {
+            listener.onInfoLog(result == 0 ? "社保卡读卡器初始化成功!" : "错误码:"+result+" 社保卡读卡器初始化失败!");
+        }
+        registerReceiver(context);
+    }
+
+    private void initUSB(Context mContext) {
+        usbManager = (UsbManager) mContext.getApplicationContext().getSystemService(Context.USB_SERVICE);
+        if (Build.VERSION.SDK_INT >= 31) {
+            mPendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_IMMUTABLE);
+        } else {
+            mPendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0);
+        }
+        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
+        mContext.registerReceiver(mUsbReceiver, filter);
+        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
+        if (!deviceList.isEmpty()) {
+            for (UsbDevice next : deviceList.values()) {
+                /*   private int pid = 57407;  private int vid = 1742;*/
+                if (next.getVendorId() == vid && next.getProductId() == pid) {
+                    usbDevice = next;
+                    if (!usbManager.hasPermission(usbDevice)) {
+                        usbManager.requestPermission(usbDevice, mPendingIntent);
+                    } else {
+                        result = cardReader.Donsee_Open("USB");
+                        if (result == 0) {
+                            setmCardReadState(1);
+                        }
+                    }
+                }
+            }
+        }
+        if (usbDevice == null) {
+            setmCardReadState(0);
+        }
+    }
+
+
+
+
+
+    private class CReaderThread extends Thread {
+        private final Object lock = new Object();
+        private volatile boolean pause = false;
+
+        public CReaderThread() {
+        }
+
+        void pauseThread() {
+            pause = true;
+        }
+
+        void resumeThread() {
+            pause = false;
+            synchronized (lock) {
+                lock.notifyAll();
+            }
+        }
+
+        void onPause() {
+            synchronized (lock) {
+                try {
+                    lock.wait();
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+        @Override
+        public void run() {
+            super.run();
+            while (isRuning) {
+                while (pause) onPause();
+                readSSCard();
+                try {
+                    Thread.sleep(200);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+
+            }
+        }
+    }
+
+
+    public void startRead() {
+        if (cReaderDataThread == null) {
+            cReaderDataThread = new CReaderThread();
+        }
+        if (!cReaderDataThread.isAlive()) {
+            isRuning = true;
+            cReaderDataThread.start();
+        }
+
+    }
+
+    public void stopRead() {
+        if (cReaderDataThread == null) {
+//            showString("请先启动读卡");
+            return;
+        }
+        isRuning = false;
+        cReaderDataThread.pause = false;
+        cReaderDataThread.interrupt();
+        cReaderDataThread = null;
+    }
+    private void readSSCard() {
+        SciCardInfo sciCardInfo = new SciCardInfo();
+        //nType 1,	有SAM卡返回全部信息   2,	无SAM卡返回卡号
+        byte[] errInfor = new byte[256];
+        SocialSecurityCardConfig config = getConfig();
+        long result = cardReader.Donsee_ReadSSCard(config.getSlotPSAM(), config.getnType(), sciCardInfo, errInfor);
+
+        if (listener != null && isRuning) {
+            if (result == 0) {
+                BaseSocialSecurityCardBean info = new BaseSocialSecurityCardBean();
+                info.cardNumber = sciCardInfo.cardNO;
+                info.name = sciCardInfo.name;
+                info.sex = sciCardInfo.sex;
+                info.nation=sciCardInfo.nation;
+                info.idNumber = sciCardInfo.idNO;
+                info.birthDate = sciCardInfo.birthDate;
+                info.issueDate = sciCardInfo.issueDate;
+                info.expireDate = sciCardInfo.expireDate;
+                info.cityCode = sciCardInfo.cityCode;
+                info.fullVersion = sciCardInfo.fullVersion;
+                listener.onSuccess(info);
+            } else {
+                listener.onFail("读社保卡失败:" + CardReader.getErrorMessage(result));
+            }
+        }
+
+    }
+    public void registerReceiver(Context mContext) {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
+        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
+        mUsbReceiver = new USBReceiver();
+        mContext.registerReceiver(mUsbReceiver, filter);
+    }
+
+    private class USBReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // 这里可以拿到插入的USB设备对象
+            LogUtils.d("intent.getAction = " + intent.getAction());
+            UsbDevice receiveDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+            if (receiveDevice != null) {
+                /*    private int pid = 57407;  private int vid = 1742;*/
+                if (receiveDevice.getProductId() != pid || receiveDevice.getVendorId() != vid)
+                    return;
+            }
+            switch (intent.getAction()) {
+                case UsbManager.ACTION_USB_DEVICE_ATTACHED: // 插入USB设备
+                    if (result == -1) {
+                        cardReader = null;
+                        cardReader = new CardReader(context);
+                        setmCardReadState(2);
+                    }
+
+                    break;
+                case UsbManager.ACTION_USB_DEVICE_DETACHED: // 拔出USB设备
+                    usbDevice = null;
+                    if (result == 0) {
+                        setmCardReadState(3);
+                        usbDevice = null;
+                        cardReader.Donsee_Close();
+                        result = -1;
+                    }
+                    break;
+                case ACTION_USB_PERMISSION:
+                    UsbDevice usbDevice1 = (UsbDevice) intent.getParcelableExtra("device");
+                    if (intent.getBooleanExtra("permission", false) && usbDevice1 != null) {
+                        result = cardReader.Donsee_Open("USB");
+                        if (result == 0) {
+                            setmCardReadState(1);
+                        }
+                    }
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+
+
+    @Override
+    public void release(Context context) {
+        {
+            stopRead();
+            if(mUsbReceiver != null){
+                context.unregisterReceiver(mUsbReceiver);
+            }
+            if(cardReader != null){
+                cardReader.Donsee_Close();
+                cardReader.unregisterUSBReceiver();
+            }
+        }
+    }
+}

+ 17 - 0
lib_sscard/src/test/java/com/hh/arome/lib_sscard/ExampleUnitTest.java

@@ -0,0 +1,17 @@
+package com.hh.arome.lib_sscard;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() {
+        assertEquals(4, 2 + 2);
+    }
+}

+ 2 - 0
settings.gradle

@@ -5,3 +5,5 @@ include ':app', ':lib_base','SeriaApp',':lib_print'
 rootProject.name = "HHContainer"
 include ':EnterIDNumber'
 include ':secondaryscreen'
+include ':lib_sscard'
+include ':lib_basecard'