赞
踩
商米介绍地址:https://www.sunmi.com/
商米是一个提供手持PDA的一个很好的解决方案厂商,
也有其他的一些桌面设备。
其中商米提供的软件服务中,比较特别的是 身份证云解功能。
此处重点说明一下,身份证云解功能。
以往市面上的身份证读卡功能,都是找公安申请身份证读卡器硬件模块。比较贵。
商米的身份证读卡,是利用商米的NFC功能,配合身份证云解功能来实现
单独实现身份证读卡,和单独实现NFC刷IC卡,在商米提供的SDK很容易能实现
但是同时实现兼容 读IC卡和身份证,现在的商米SDK 就兼容性做的很差。
这里主要说明一下同时兼容 读IC卡和身份证,
package com.smk.travelpda.common.nfc; import android.app.Activity; import android.content.Context; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.util.Log; import android.widget.Toast; import com.smk.travelpda.common.util.RString; /** * luoyang */ public class NfcUtils { private static final String TAG = "NfcUtils"; private static NfcAdapter mNfcAdapter; private NfcUtils(){} private static NfcUtils nfcUtils = null; private static boolean isOpen = false; /** * 获取NFC的单例 * @return NfcUtils */ public static NfcUtils getInstance(){ if (nfcUtils == null){ synchronized (NfcUtils.class){ if (nfcUtils == null){ nfcUtils = new NfcUtils(); } } } return nfcUtils; } private NfcListener nfcListener; public void setNfcListener(NfcListener listener){ nfcListener = listener; } /** * 在onStart中检测是否支持nfc功能 * @param context 当前页面上下文 */ public void onStartNfcAdapter(Context context){ //设备的NfcAdapter对象 mNfcAdapter = NfcAdapter.getDefaultAdapter(context); } /** * 在onResume中开启nfc功能 * @param activity */ public void onResumeNfcAdapter(final Activity activity){ if(mNfcAdapter==null){//判断设备是否支持NFC功能 RString.showDia(activity,"提醒","设备不支持NFC功能"); return; } if (!mNfcAdapter.isEnabled()){//判断设备NFC功能是否打开 RString.showDia(activity,"提醒","请到系统设置中打开NFC功能!"); return; } if (!isOpen) { mNfcAdapter.enableReaderMode(activity, new NfcAdapter.ReaderCallback() { @Override public void onTagDiscovered(final Tag tag) { if (nfcListener != null){ (activity).runOnUiThread(new Runnable() { @Override public void run() { nfcListener.nfcReadHander(tag); } }); } } }, (NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_NFC_B | NfcAdapter.FLAG_READER_NFC_F | NfcAdapter.FLAG_READER_NFC_V | NfcAdapter.FLAG_READER_NFC_BARCODE ), null); isOpen = true; } } /** * 在onPause中关闭nfc功能 * @param activity */ public void onPauseNfcAdapter(Activity activity){ if(mNfcAdapter!=null && mNfcAdapter.isEnabled()){ if (isOpen){ mNfcAdapter.disableReaderMode(activity); } isOpen = false; } } }
package com.smk.travelpda.common.nfc;
import android.nfc.Tag;
/**
* 自定义的NFC接口
*/
public interface NfcListener{
/**
* 用于扫到nfc后的后续操作
*/
void nfcReadHander(Tag tag);
}
package com.smk.travelpda.common.yidcard; import android.util.Log; import com.smk.travelpda.MainActivity; import com.smk.travelpda.common.util.RJson; import com.sunmi.eidlibrary.EidCall; import com.sunmi.eidlibrary.EidConstants; import com.sunmi.eidlibrary.EidSDK; import java.util.Map; //云解身份证读卡回调方法 public class EidCardReadCall implements EidCall { private String TAG = "IdCardHander"; private EidcardListener eidcardListener; private String eventType; public EidCardReadCall(EidcardListener eidcardListener,String eventType){ this.eidcardListener = eidcardListener; this.eventType = eventType; } @Override public void onCallData(int code, String msg) { if(this.eventType.endsWith(EidHanderEo.EID_INIT)){ initEidHanderCall(code, msg); }else if(this.eventType.endsWith(EidHanderEo.Eid_READY_NFC)){ readerForNfc(code, msg); } else if (this.eventType.endsWith(EidHanderEo.GETIDCARDINFO)) { getIDCardInfo(code, msg); } } public void initEidHanderCall(int i, String s){ EidHanderEo inttEo = new EidHanderEo(this.eventType); inttEo.setEventCode(i); switch (i) { case EidConstants.EID_INIT_SUCCESS: inttEo.setSucces(true); break; default: inttEo.setSucces(false); inttEo.setMsg(s); break; } eidcardListener.handEidEvent(inttEo); } public void getIDCardInfo(int i, String s) { EidHanderEo eo = new EidHanderEo(this.eventType); eo.setEventCode(i); if (i == EidConstants.DECODE_SUCCESS) { eo.setSucces(true); eo.setCardType("sfz"); try{ Map<String,Object> sfzMap = RJson.parseJson2Map(s); String idnum = (String)((Map<String,Object>)sfzMap.get("base_info")).get("idnum"); eo.setCardId(idnum); } catch (Exception e){ eo.setSucces(false); eo.setMsg("身份证解析失败,请重试"); } } else { //解码失败,code 为错误吗,data为错误原因 // typetext.setText("解析失敗:code:"+i); //typetext.setText("解析失敗:data:"+s); eo.setSucces(false); eo.setMsg(s); } eidcardListener.handEidEvent(eo); } public void readerForNfc(int code, String msg) { System.out.println("code:" + code + ":msg:" + msg); EidHanderEo eidHanderEo = new EidHanderEo(this.eventType); eidHanderEo.setEventCode(code); switch (code) { case EidConstants.EID_INIT_SUCCESS: eidHanderEo.setSucces(true); break; case EidConstants.ERR_NFC_NOT_SUPPORT: // 该机器不支持NFC功能,无法使用SDK eidHanderEo.setSucces(false); eidHanderEo.setMsg("机器不支持NFC"); break; case EidConstants.ERR_NETWORK_NOT_CONNECTED: eidHanderEo.setSucces(false); eidHanderEo.setMsg("网络未连接,请联网后重试"); // *** 异常处理: 连接网络后,需要重新调用 startCheckCard 方法 (手动触发,非自动)*** break; case EidConstants.ERR_NFC_CLOSED: eidHanderEo.setSucces(false); eidHanderEo.setMsg("NFC 未打开,打开后重试 "); // *** 异常处理: 打开NFC后,需要重新调用 startCheckCard 方法 (手动触发,非自动)*** break; case EidConstants.READ_CARD_READY: //Step 3 读卡准备完成 -> 业务方可以引导用户开始进行刷卡操作 eidHanderEo.setSucces(true); eidHanderEo.setMsg("SDK准备完成,请刷卡"); break; case EidConstants.READ_CARD_START: //Step 4 读卡中 -> 业务方可以提醒用户"读卡中,请勿移动卡片" eidHanderEo.setSucces(true); eidHanderEo.setMsg("开始读卡,请勿移动"); break; case EidConstants.READ_CARD_SUCCESS: //Step 5 读卡成功 -> 返回的msg为reqId,通过 reqId 业务方走云对云方案获取身份证信息 //注:如不需要循环读卡,可在此处调用stopCheckCard方法 eidHanderEo.setSucces(true); eidHanderEo.setMsg("读卡成功"); eidHanderEo.setCardId(msg);//设置读取的身份证ID break; case EidConstants.READ_CARD_FAILED: //*** 异常处理: 读卡失败,请重新读卡 *** eidHanderEo.setSucces(false); eidHanderEo.setMsg("读卡失败,请重试"+ msg); break; case EidConstants.ERR_ACCOUNT_EXCEPTION: //*** 异常处理: 读卡失败,请重新读卡 *** eidHanderEo.setSucces(false); eidHanderEo.setMsg("该设备未开通身份证读卡权限!"); break; default: //*** 异常处理: 其他失败 - code为错误码,msg为详细错误原因 需要重新调用 startCheckCard 方法 (手动触发,非自动)*** eidHanderEo.setSucces(false); eidHanderEo.setMsg("读卡异常,请重试code:"+code+ msg); break; } eidcardListener.handEidEvent(eidHanderEo); } }
package com.smk.travelpda.common.yidcard;
/**
* 处理EID的事件
*/
public interface EidcardListener {
public void handEidEvent(EidHanderEo eidHanderEo);
}
package com.smk.travelpda; import android.content.IntentFilter; import android.nfc.Tag; import android.nfc.tech.IsoDep; import android.nfc.tech.MifareClassic; import android.nfc.tech.NfcA; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.TextView; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import com.smk.travelpda.common.macinfo.MacInfoHander; import com.smk.travelpda.common.nfc.NfcListener; import com.smk.travelpda.common.nfc.NfcReadHander; import com.smk.travelpda.common.nfc.NfcUtils; import com.smk.travelpda.common.scan.ScanEventEo; import com.smk.travelpda.common.scan.ScanListener; import com.smk.travelpda.common.util.BusinessException; import com.smk.travelpda.common.util.RString; import com.smk.travelpda.common.util.VersionCheckUtil; import com.smk.travelpda.common.yidcard.EidCardReadCall; import com.smk.travelpda.common.yidcard.EidHanderEo; import com.smk.travelpda.common.scan.ScanMachinReceive; import com.smk.travelpda.common.yidcard.EidcardListener; import com.sunmi.eidlibrary.EidCall; import com.sunmi.eidlibrary.EidConstants; import com.sunmi.eidlibrary.EidReader; import com.sunmi.eidlibrary.EidSDK; /** * luoyang 2024-04-17 */ public class MainActivity extends AppCompatActivity implements NfcListener, ScanListener, EidcardListener { public final static String APP_ID = "商米的APPID"; public final static String APP_KEY = "商米的APPKEY"; private TextView datatext; //绑定的归属方,景区名称 private TextView tourname; private TextView sntext; private TextView visionnum; private NfcUtils nfcUtils = NfcUtils.getInstance(); private EidReader eid; private ScanMachinReceive myReceiver ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); datatext = findViewById(R.id.data); tourname = findViewById(R.id.tourname); sntext = findViewById(R.id.sntext); visionnum = findViewById(R.id.visionnum); sntext.setText("序列号:"+MacInfoHander.getSN()); visionnum.setText("V1.0.0"); tourname.setText("景区"); //初始化NFC读卡器 nfcUtils.setNfcListener(this); //商米的扫码监听 initScanReceiveLislen();//初始话监听 //初始化身份证读卡 initCardEidSdk(); } @Override protected void onDestroy() { super.onDestroy(); // 注销扫码接收广播 unregisterReceiver(myReceiver); //注销读卡服务 EidSDK.destroy(); } @Override protected void onStart() { super.onStart(); System.out.println("onStart................................"); nfcUtils.onStartNfcAdapter(this); //初始化Nfc对象 } @Override protected void onResume() { super.onResume(); System.out.println("onResume................................"); nfcUtils.onResumeNfcAdapter(this); //activity激活的时候开始扫描 datatext.append("NFC初始化成功\n"); } @Override protected void onPause() { super.onPause(); System.out.println("onPause................................"); nfcUtils.onPauseNfcAdapter(this); //activity切换到后台的时候停止扫描 } //读NFC卡后的返回事件 @Override public void nfcReadHander(Tag tag) { datatext.setText("start new card"); String tl[] = tag.getTechList(); //POS机器,只支持2代和3代卡,身份证,其他证件不支持 try { boolean isHandCard = false; for (String s:tl) { if(s.equals("android.nfc.tech.MifareClassic")){ //String data = NfcReadHander.readMifareTag(tag,MifareClassic.get(tag)); datatext.setText(RString.byteToString(tag.getId())); isHandCard = true; break; //旅游卡PDA 无需支持M1卡类型 }else if(s.equals("android.nfc.tech.IsoDep")){ String cardType = "smk"; //读取IC卡 String cardId = NfcReadHander.readIsoDepTag(tag, IsoDep.get(tag)); System.out.println("cardId"+cardId); datatext.setText(cardId); isHandCard = true; break; }else if(s.equals("android.nfc.tech.NfcB")){ //跳转到身份证云解读取,NFCB为身份证模块,此处调用身份证云解,其他的为IC卡读取 eid.nfcReadCard(tag); isHandCard = true; break; } } if(!isHandCard){ throw new BusinessException("请刷IC卡或身份证"); } }catch (BusinessException e){ //捕获自定义异常 datatext.setText(e.getMessage()); } } /** * 实现扫码事件 * @return */ @Override public void scanEventHander(ScanEventEo eventEo) { String eventType = eventEo.getEventType(); if(eventType.equals(ScanEventEo.SCAN_START)){ //typetext.setText("开始扫码"); datatext.setText("开始扫码"); } else if (eventType.equals(ScanEventEo.SCAN_RECEVIE)) { //typetext.setText("扫码成功"); datatext.setText(""); datatext.append(eventEo.isAllow()+":"+ eventEo.getQrData()); } else if (eventType.equals(ScanEventEo.SCAN_END)) { datatext.setText("扫码结束"); } } //实现云解身份证的事件 @Override public void handEidEvent(EidHanderEo eidHanderEo) { String eventType = eidHanderEo.getEventType(); if(eventType.equals(EidHanderEo.EID_INIT)){ //typetext.setText("init success"); //init初始化监听时间 if(eidHanderEo.isSucces() && eidHanderEo.getEventCode() == EidConstants.EID_INIT_SUCCESS){ eid = EidSDK.getEidReaderForNfc(3, new EidCardReadCall(this,EidHanderEo.Eid_READY_NFC)); }else { //其他都是失败的, RString.showDia(this,"身份证模块初始化失败",eidHanderEo.getMsg()); } } else if (eventType.equals(EidHanderEo.Eid_READY_NFC)) { // typetext.setText("Eid_READY_NFC"); //读卡的回调 if(eidHanderEo.isSucces() && eidHanderEo.getEventCode() == EidConstants.READ_CARD_SUCCESS){ datatext.setText(eidHanderEo.getCardId()); //读卡成功的回调 EidSDK.getIDCardInfo(eidHanderEo.getCardId(), MainActivity.APP_KEY, new EidCardReadCall(this,EidHanderEo.GETIDCARDINFO)); }else if(!eidHanderEo.isSucces()){ RString.showDia(this,"提醒",eidHanderEo.getMsg()); }else{ //有些成功,是否需要干预流程处理,不需要就不做任何事情 //datatext.setText(eidHanderEo.getMsg()); datatext.append("身份证模块初始化成功"); } } else if (eventType.equals(EidHanderEo.GETIDCARDINFO)) { //typetext.setText("GETIDCARDINFO"); //调用 if(eidHanderEo.isSucces() && eidHanderEo.getEventCode() == EidConstants.DECODE_SUCCESS){ //解析成功 datatext.setText(""); datatext.append(eidHanderEo.getCardId()); }else { RString.showDia(this,"提醒",eidHanderEo.getMsg()); } } } private void initScanReceiveLislen(){ myReceiver = new ScanMachinReceive(this); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ScanEventEo.SCAN_RECEVIE); // 监听网络变化广播 intentFilter.addAction(ScanEventEo.SCAN_START); // 监听网络变化广播 intentFilter.addAction(ScanEventEo.SCAN_END); // 监听网络变化广播 // 注册广播 只从原生获取,不从外部APP获取 registerReceiver(myReceiver, intentFilter); datatext.append("扫码初始化成功\n"); } private void initCardEidSdk(){ EidSDK.init(this, APP_ID, new EidCardReadCall(this,EidHanderEo.EID_INIT)); // EidSDK.startCheckCard不要使用这个API } public void visionClick(View view){ //startActivity(VersionCheckUtil.check(false)); } }
EidReader eid = EidSDK.getEidReaderForNfc(3, new EidCardReadCall(this,EidHanderEo.Eid_READY_NFC));
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。