NFC手機(jī)二代身份證閱讀開發(fā)說明
- 2019-07-01 16:23:00
- 諾塔斯智能科技 原創(chuàng)
- 4076
實(shí)名認(rèn)證是市場經(jīng)濟(jì)中不能跳過的流程,那是否意味著每一次的認(rèn)證都要讓人百般懷疑的進(jìn)行“拍照”、“上傳”這一系列步驟嗎,萬一真遇上“釣魚網(wǎng)站”,個(gè)人信息遭到泄露,后果將不堪設(shè)想,并且繁復(fù)的上傳回饋過程也大大降低了工作效率。再者,如遇到假冒偽造證件,普通民眾用肉眼并不能立即識(shí)別真假,
隨著NFC手機(jī)的不斷普及,利用手機(jī)NFC進(jìn)行身份證證件識(shí)別和判斷真?zhèn)?,檢測身份證信息并讀取內(nèi)容進(jìn)行實(shí)名認(rèn)證。未來,人們?cè)诰€交易或簽署合同時(shí),只需用手機(jī)掃描身份證即可完成身份驗(yàn)證,隨后便可使用該身份進(jìn)行交易、合同簽署,方便快捷的同時(shí),安全性更是上升到更高層級(jí)。
NFC手機(jī)二代身份證閱讀開發(fā)說明
1、首先需要在AndroidManifest.xml文件中進(jìn)行權(quán)限配置,我們需要手機(jī)上網(wǎng)和打開NFC功能的權(quán)限。
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" > </uses-permission> <uses-permission android:name="android.permission.INTERNET" > </uses-permission> <uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="true" />
2、在Android NFC手機(jī)二代身份證閱讀工程中建立一個(gè)libs文件夾并導(dǎo)入.so庫文件,我們提供了包括,arm64-v8a、armeabi、armeabi-v7a、mips、mips64、x86、x86_64等一系列的庫文件,開發(fā)者可以根據(jù)自己項(xiàng)目需求,選擇性的導(dǎo)入.so庫文件。
3、定義二代身份證閱讀過程中的關(guān)鍵參數(shù),如:姓名,性別,地址等。參數(shù)定義如下:
package cc.lotuscard; public class TwoIdInfoParam { public TwoIdInfoParam() { arrTwoIdName = new byte[30]; arrTwoIdSex = new byte[2]; arrTwoIdNation = new byte[4]; arrTwoIdBirthday = new byte[16]; arrTwoIdAddress = new byte[70]; arrTwoIdNo = new byte[36]; arrTwoIdSignedDepartment = new byte[30]; arrTwoIdValidityPeriodBegin = new byte[16]; arrTwoIdValidityPeriodEnd = new byte[16]; arrTwoIdNewAddress = new byte[70]; arrTwoIdPhoto = new byte[1024]; arrTwoIdFingerprint = new byte[1024]; arrTwoIdPhotoJpeg = new byte[4096]; } /** * 姓名 UNICODE */ public byte[] arrTwoIdName; /** * 性別 UNICODE */ public byte[] arrTwoIdSex; /** * 民族 UNICODE */ public byte[] arrTwoIdNation; /** * 出生日期 UNICODE YYYYMMDD */ public byte[] arrTwoIdBirthday; /** * 住址 UNICODE */ public byte[] arrTwoIdAddress; /** * 身份證號(hào)碼 UNICODE */ public byte[] arrTwoIdNo; /** * 簽發(fā)機(jī)關(guān) UNICODE */ public byte[] arrTwoIdSignedDepartment; /** * 有效期起始日期 UNICODE YYYYMMDD */ public byte[] arrTwoIdValidityPeriodBegin; /** * 有效期截止日期 UNICODE YYYYMMDD 有效期為長期時(shí)存儲(chǔ)“長期” */ public byte[] arrTwoIdValidityPeriodEnd; /** * 最新住址 UNICODE */ public byte[] arrTwoIdNewAddress; /** * 照片信息 */ public byte[] arrTwoIdPhoto; /** * 指紋信息 */ public byte[] arrTwoIdFingerprint; /** * 照片信息 JPEG 格式 */ public byte[] arrTwoIdPhotoJpeg; /** * 照片信息長度 JPEG格式 */ public int unTwoIdPhotoJpegLength; }
注意,NFC手機(jī)二代身份證閱讀開發(fā)過程中,建立項(xiàng)目的時(shí)候,包名必須要遵循以下格式,否則無法編譯通過。
package cc.lotuscard;
package cn.highwillow.iddemo; import android.Manifest; import android.annotation.TargetApi; import android.app.Activity; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbEndpoint; import android.hardware.usb.UsbInterface; import android.hardware.usb.UsbManager; import android.net.DhcpInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.tech.IsoDep; import android.nfc.tech.MifareClassic; import android.nfc.tech.Ndef; import android.nfc.tech.NfcA; import android.nfc.tech.NfcB; import android.os.Parcelable; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.telephony.TelephonyManager; import android.util.Log; import android.view.View; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import android.os.Build.VERSION; import android.os.Bundle; import android.os.Handler; import android.os.Message; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.Reader; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.NetworkInterface; import java.text.SimpleDateFormat; import java.sql.Date; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import cc.lotuscard.ILotusCallBack; import cc.lotuscard.LotusCardDriver; import cc.lotuscard.LotusCardParam; import cc.lotuscard.TwoIdInfoParam; //import static GuoTeng.GtTermb.Wlt2Bmp2; import static cc.lotuscard.LotusCardDriver.isZero; public class MainActivity extends AppCompatActivity implements ILotusCallBack { private static final int REQUEST_READ_PHONE_STATE = 0; // 請(qǐng)求碼 private UsbDeviceConnection m_UsbDeviceConnection = null; private UsbEndpoint m_InEndpoint = null; private UsbEndpoint m_OutEndpoint = null; private final static char[] HEX = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; private LotusCardDriver mLotusCardDriver; private NfcAdapter m_NfcAdpater; private PendingIntent pendingIntent; private IntentFilter[] mFilters; private String[][] mTechLists; private Handler m_Handler = null; private EditText m_edtLog; private TextView m_txtCommandIndex; private ImageView m_imgIdPhoto; private Activity m_MainActivity = null; private UsbManager m_UsbManager = null; private UsbDevice m_LotusCardDevice = null; private UsbInterface m_LotusCardInterface = null; private UsbDeviceConnection m_LotusCardDeviceConnection = null; private final int m_nVID = 1306; private final int m_nPID = 20763; private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; private Boolean m_bUseUsbHostApi = true; private Boolean m_bCanUseUsbHostApi = true; private String m_strDeviceNode; private long m_nDeviceHandle = -1; private int m_nSystemVersion = -1; private int m_nCommandInex = 0; private static final String Activity_TAG = "IdDemo"; private EditText m_edtPostCode = null; private EditText m_edtAccoutCode = null; private EditText m_edtUserPassword = null; private void requestPermission() { List<String> permissionsNeeded = new ArrayList<>(); if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) { permissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); } if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) { permissionsNeeded.add(Manifest.permission.READ_EXTERNAL_STORAGE); } if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) { permissionsNeeded.add(Manifest.permission.CAMERA); } if (permissionsNeeded.size() > 0) { ActivityCompat.requestPermissions(this, permissionsNeeded.toArray(new String[permissionsNeeded.size()]), 1); } } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int [] grantResults) { switch (requestCode) { case 1: { boolean allowed = true; if (grantResults.length > 0) { for (int i = 0; i < grantResults.length; i++) { if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { //Timber.e("case 1權(quán)限沒有打開"); AddLog(permissions[i] + "打開"); } else { //Timber.e("case 1權(quán)限沒有"); AddLog(permissions[i] + "關(guān)閉"); allowed = false; break; } } } if (!allowed) { //O TODO 自定義處理 //dialog(); //Timber.e("case 1自定義處理"); } break; } } } /** * 獲取手機(jī)的MAC地址 * * @return */ public static String getMac() { String str = ""; String macSerial = ""; try { Process pp = Runtime.getRuntime().exec( "cat /sys/class/net/wlan0/address "); InputStreamReader ir = new InputStreamReader(pp.getInputStream()); LineNumberReader input = new LineNumberReader(ir); for (; null != str; ) { str = input.readLine(); if (str != null) { macSerial = str.trim();// 去空格 break; } } } catch (Exception ex) { ex.printStackTrace(); } if (macSerial == null || "".equals(macSerial)) { try { return loadFileAsString("/sys/class/net/eth0/address") .toUpperCase().substring(0, 17); } catch (Exception e) { e.printStackTrace(); } } return macSerial; } public static String loadFileAsString(String fileName) throws Exception { FileReader reader = new FileReader(fileName); String text = loadReaderAsString(reader); reader.close(); return text; } public static String loadReaderAsString(Reader reader) throws Exception { StringBuilder builder = new StringBuilder(); char[] buffer = new char[4096]; int readLength = reader.read(buffer); while (readLength >= 0) { builder.append(buffer, 0, readLength); readLength = reader.read(buffer); } return builder.toString(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); m_MainActivity = this; try { m_NfcAdpater = NfcAdapter.getDefaultAdapter(this); if (m_NfcAdpater == null) { Toast.makeText(this, "Not Found NfcAdapter!", Toast.LENGTH_SHORT) .show(); // finish(); // return; } else if (!m_NfcAdpater.isEnabled()) { Toast.makeText(this, "Please Enabled NfcAdapter", Toast.LENGTH_SHORT).show(); // finish(); // return; } } catch (java.lang.NullPointerException e) { Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show(); } m_edtLog = (EditText) findViewById(R.id.edtLog); m_imgIdPhoto = (ImageView) findViewById(R.id.imgIdPhoto); m_txtCommandIndex = (TextView) findViewById(R.id.txtCommandIndex); m_edtPostCode = (EditText) findViewById(R.id.edtPostCode); m_edtAccoutCode = (EditText) findViewById(R.id.edtAccountCode); m_edtUserPassword = (EditText) findViewById(R.id.edtUserPassword); pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED); ndef.addCategory("*/*"); mFilters = new IntentFilter[]{ndef};// 過濾器 mTechLists = new String[][]{ new String[]{MifareClassic.class.getName()}, new String[]{NfcB.class.getName()}, new String[]{IsoDep.class.getName()}, new String[]{NfcA.class.getName()}};// 允許掃描的標(biāo)簽類型 // 設(shè)置USB讀寫回調(diào) 串口可以不用此操作 m_bCanUseUsbHostApi = SetUsbCallBack(); if (m_bCanUseUsbHostApi) { AddLog("Find IC Reader!"); AddLog("Device Node:" + m_strDeviceNode); } else { AddLog("Not Find IC Reader!"); } mLotusCardDriver = new LotusCardDriver(); mLotusCardDriver.m_lotusCallBack = this; m_Handler = new Handler() { public void handleMessage(Message msg) { AddLog(msg.obj.toString()); super.handleMessage(msg); } }; int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE); if (permissionCheck != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, REQUEST_READ_PHONE_STATE); } else { //TODO } requestPermission(); TelephonyManager mTelephonyMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); String imsi = mTelephonyMgr.getSubscriberId(); String imei = mTelephonyMgr.getDeviceId(); //String tel = mTelephonyMgr.getLine1Number(); String tel = mTelephonyMgr.getLine1Number(); if (tel == null) tel = ""; if (tel.equals("")) { tel = mTelephonyMgr.getSubscriberId(); } if (tel == null) tel = ""; String iccid = mTelephonyMgr.getSimSerialNumber(); //取出ICCID } public static String int2ip(long ipInt) { StringBuilder sb = new StringBuilder(); sb.append(ipInt & 0xFF).append("."); sb.append((ipInt >> 8) & 0xFF).append("."); sb.append((ipInt >> 16) & 0xFF).append("."); sb.append((ipInt >> 24) & 0xFF); return sb.toString(); } public void OnClearLogListener(View arg0) { m_imgIdPhoto.setBackgroundColor(0); if (null == m_edtLog) return; m_edtLog.setText(""); } public void OnIdOtgTestListener(View arg0) { if (m_nDeviceHandle == -1) { m_nDeviceHandle = mLotusCardDriver.OpenDevice("", 0, 0, 0, 0,// 使用內(nèi)部默認(rèn)超時(shí)設(shè)置 true); } if (m_nDeviceHandle == -1) return; TwoIdInfoParam tTwoIdInfo = new TwoIdInfoParam(); boolean bResult = false; int nResult = 0; boolean bWlDecodeResult = false; byte[] arrBmpAndWl = null; String temp; int nErrorCode = 0; LotusCardParam tLotusCardParam1 = new LotusCardParam(); bResult = mLotusCardDriver.Beep(m_nDeviceHandle, 10); // bResult = mLotusCardDriver.Beep(nDeviceHandle, 10); if (!bResult) { AddLog("Call Beep Error!"); return; } AddLog("Call Beep Ok!"); bResult = mLotusCardDriver.SetCardType(m_nDeviceHandle, 'B'); if (!bResult) { AddLog("Call SetCardType Error!"); return; } //mLotusCardDriver.GetTwoGenerationIDCardNo(m_nDeviceHandle); AddLog("Call SetCardType Ok!"); nResult = mLotusCardDriver.RequestB(m_nDeviceHandle,0, tLotusCardParam1); if(nResult== 0) { AddLog("Call RequestB Error!"); return; } nResult = mLotusCardDriver.SelectB(m_nDeviceHandle, tLotusCardParam1); if(nResult== 0) { AddLog("Call SelectB Error!"); return; } bResult = mLotusCardDriver.GetTwoIdInfoByMcuServer(this, null, m_nDeviceHandle, "samv.highwillow.cn", Integer.valueOf(m_edtAccoutCode.getText().toString()), m_edtUserPassword.getText().toString(), tTwoIdInfo, Long.valueOf(m_edtPostCode.getText().toString()), 0, 2, true); if (!bResult) { nErrorCode = mLotusCardDriver.GetTwoIdErrorCode(m_nDeviceHandle); AddLog("Call GetTwoIdInfoByMcuServer Error! ErrorCode:" + nErrorCode); AddLog("ErrorInfo:" + mLotusCardDriver.GetIdErrorInfo(nErrorCode)); return; } AddLog("Call GetTwoIdInfoByMcuServer Ok!"); if (true == bResult) { // 姓名 try { temp = new String(tTwoIdInfo.arrTwoIdName, 0, 30, "UTF-16LE").trim(); if (temp.equals("")) { AddLog("數(shù)據(jù)為空"); return; } AddLog("姓名:" + temp); // 性別 temp = new String(tTwoIdInfo.arrTwoIdSex, 0, 2, "UTF-16LE").trim(); if (temp.equals("1")) temp = "男"; else temp = "女"; AddLog("性別:" + temp); // 民族 temp = new String(tTwoIdInfo.arrTwoIdNation, 0, 4, "UTF-16LE").trim(); try { int code = Integer.parseInt(temp.toString()); temp = decodeNation(code); } catch (Exception e) { temp = ""; } AddLog("民族:" + temp); // 出生日期 temp = new String(tTwoIdInfo.arrTwoIdBirthday, 0, 16, "UTF-16LE").trim(); AddLog("出生日期:" + temp); // 住址 temp = new String(tTwoIdInfo.arrTwoIdAddress, 0, 70, "UTF-16LE").trim(); AddLog("住址:" + temp); // 身份證號(hào)碼 temp = new String(tTwoIdInfo.arrTwoIdNo, 0, 36, "UTF-16LE").trim(); AddLog("身份證號(hào)碼:" + temp); // 簽發(fā)機(jī)關(guān) temp = new String( tTwoIdInfo.arrTwoIdSignedDepartment, 0, 30, "UTF-16LE").trim(); AddLog("簽發(fā)機(jī)關(guān):" + temp); // 有效期起始日期 temp = new String( tTwoIdInfo.arrTwoIdValidityPeriodBegin, 0, 16, "UTF-16LE").trim(); AddLog("有效期起始日期:" + temp); // 有效期截止日期 UNICODE YYYYMMDD 有效期為長期時(shí)存儲(chǔ)“長期” temp = new String( tTwoIdInfo.arrTwoIdValidityPeriodEnd, 0, 16, "UTF-16LE").trim(); AddLog("有效期截止日期:" + temp); if (tTwoIdInfo.unTwoIdPhotoJpegLength > 0) { final Bitmap photo = BitmapFactory.decodeByteArray( tTwoIdInfo.arrTwoIdPhotoJpeg, 0, tTwoIdInfo.unTwoIdPhotoJpegLength); runOnUiThread(new Runnable() { @Override public void run() { m_imgIdPhoto.setBackgroundDrawable(new BitmapDrawable(photo)); } }); } } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } else { AddLog("GetTwoIdInfoByMcuServer執(zhí)行失敗"); } } public void AddLog(String strLog) { final String strText = strLog; runOnUiThread(new Runnable() { @Override public void run() { //SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss"); //SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS"); SimpleDateFormat formatter = new SimpleDateFormat("MM-dd HH:mm:ss:SSS"); Date curDate = new Date(System.currentTimeMillis());// 獲取當(dāng)前時(shí)間 String strDate = formatter.format(curDate); if (null == m_edtLog) return; String strLogs = m_edtLog.getText().toString().trim(); if (strLogs.equals("")) { strLogs = strDate + " " + strText; } else { strLogs += "\r\n" + strDate + " " + strText; } m_edtLog.setText(strLogs); } }); } public void showCommandIndex(int nIndex) { final int nTmp = nIndex; runOnUiThread(new Runnable() { @Override public void run() { m_txtCommandIndex.setText("索引" + nTmp); } }); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); Log.i(Activity_TAG, "This is Information"); if (m_NfcAdpater != null) { m_NfcAdpater.enableForegroundDispatch(this, pendingIntent, mFilters, mTechLists); enableReaderMode(); } } @Override protected void onPause() { super.onPause(); if (m_NfcAdpater != null) { m_NfcAdpater.disableForegroundDispatch(this); disableReaderMode(); } } @TargetApi(19) private void enableReaderMode() { if (m_nSystemVersion < 19) return; Bundle options = new Bundle(); options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 5000); //int READER_FLAGS = NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK; int READER_FLAGS = NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_NFC_B | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK; if (m_NfcAdpater != null) { m_NfcAdpater.enableReaderMode(this, new IdReaderCallback(), READER_FLAGS, options); } } @TargetApi(19) public class IdReaderCallback implements NfcAdapter.ReaderCallback { @Override public void onTagDiscovered(Tag tag) { boolean bResult = false; boolean bWlDecodeResult = false; String temp; int nErrorCode = 0; byte[] arrBmpBuffer = new byte[38862]; NfcB nfcbId = NfcB.get(tag); byte[] arrRequest = new byte[3]; byte[] arrSelect = new byte[9]; byte[] arrResult; //byte[] arrBmpAndWl = null; arrRequest[0] = (byte) 0x5; arrRequest[1] = (byte) 0x0; arrRequest[2] = (byte) 0x0; arrSelect[0] = (byte) 0x1D;//1D 00 00 00 00 00 08 01 08 arrSelect[1] = (byte) 0x0; arrSelect[2] = (byte) 0x0; arrSelect[3] = (byte) 0x0; arrSelect[4] = (byte) 0x0; arrSelect[5] = (byte) 0x0; arrSelect[6] = (byte) 0x8; arrSelect[7] = (byte) 0x1; arrSelect[8] = (byte) 0x8; if (nfcbId != null) { try { nfcbId.connect(); if (nfcbId.isConnected()) AddLog("connect"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (nfcbId.isConnected()) { TwoIdInfoParam tTwoIdInfo = new TwoIdInfoParam(); try { arrResult = nfcbId.transceive(arrRequest); AddLog("length" + arrResult.length); arrResult = nfcbId.transceive(arrSelect); AddLog("length" + arrResult.length); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (m_nDeviceHandle == -1) { m_nDeviceHandle = mLotusCardDriver.OpenDevice("", 0, 0, 0, 0,// 使用內(nèi)部默認(rèn)超時(shí)設(shè)置 true); } m_nCommandInex = 0; bResult = mLotusCardDriver.GetTwoIdInfoByMcuServer(m_MainActivity, nfcbId, m_nDeviceHandle, "samv.highwillow.cn", Integer.valueOf(m_edtAccoutCode.getText().toString()), //m_nDeviceHandle, "192.168.1.21", 99999, m_edtUserPassword.getText().toString(), tTwoIdInfo, Long.valueOf(m_edtPostCode.getText().toString()), 0, 3, false); if (!bResult) { nErrorCode = mLotusCardDriver.GetTwoIdErrorCode(m_nDeviceHandle); AddLog("Call GetTwoIdInfoByMcuServer Error! ErrorCode:" + nErrorCode); AddLog("ErrorInfo:" + mLotusCardDriver.GetIdErrorInfo(nErrorCode)); return; } AddLog("Call GetTwoIdInfoByMcuServer Ok!"); if (true == bResult) { // 姓名 try { temp = new String(tTwoIdInfo.arrTwoIdName, 0, 30, "UTF-16LE").trim(); if (temp.equals("")) { AddLog("數(shù)據(jù)為空"); return; } AddLog("姓名:" + temp); // 性別 temp = new String(tTwoIdInfo.arrTwoIdSex, 0, 2, "UTF-16LE").trim(); if (temp.equals("1")) temp = "男"; else temp = "女"; AddLog("性別:" + temp); // 民族 temp = new String(tTwoIdInfo.arrTwoIdNation, 0, 4, "UTF-16LE").trim(); try { int code = Integer.parseInt(temp.toString()); temp = decodeNation(code); } catch (Exception e) { temp = ""; } AddLog("民族:" + temp); // 出生日期 temp = new String(tTwoIdInfo.arrTwoIdBirthday, 0, 16, "UTF-16LE").trim(); AddLog("出生日期:" + temp); // 住址 temp = new String(tTwoIdInfo.arrTwoIdAddress, 0, 70, "UTF-16LE").trim(); AddLog("住址:" + temp); // 身份證號(hào)碼 temp = new String(tTwoIdInfo.arrTwoIdNo, 0, 36, "UTF-16LE").trim(); AddLog("身份證號(hào)碼:" + temp); // 簽發(fā)機(jī)關(guān) temp = new String( tTwoIdInfo.arrTwoIdSignedDepartment, 0, 30, "UTF-16LE").trim(); AddLog("簽發(fā)機(jī)關(guān):" + temp); // 有效期起始日期 temp = new String( tTwoIdInfo.arrTwoIdValidityPeriodBegin, 0, 16, "UTF-16LE").trim(); AddLog("有效期起始日期:" + temp); // 有效期截止日期 UNICODE YYYYMMDD 有效期為長期時(shí)存儲(chǔ)“長期” temp = new String( tTwoIdInfo.arrTwoIdValidityPeriodEnd, 0, 16, "UTF-16LE").trim(); AddLog("有效期截止日期:" + temp); //顯示JPEG //顯示BMP if(true == mLotusCardDriver.GetIdPhotoBmpBuffer(m_nDeviceHandle,arrBmpBuffer)) { final Bitmap photo = BitmapFactory.decodeByteArray( arrBmpBuffer, 0, 38862); runOnUiThread(new Runnable() { @Override public void run() { m_imgIdPhoto.setBackgroundDrawable(new BitmapDrawable(photo)); } }); } } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } else { AddLog("GetTwoIdInfoByMcuServer執(zhí)行失敗"); } } } } } @TargetApi(19) private void disableReaderMode() { if (m_nSystemVersion < 19) return; if (m_NfcAdpater != null) { m_NfcAdpater.disableReaderMode(this); } } //@Override protected void onNewIntent(Intent intent) { // TODO Auto-generated method stub super.onNewIntent(intent); boolean bResult = false; boolean bWlDecodeResult = false; String temp; int nErrorCode = 0; Log.d(Activity_TAG, intent.getAction()); Log.i(Activity_TAG, "onNewIntent"); if (m_nSystemVersion >= 19) return; if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) { Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); NfcB nfcbId = NfcB.get(tagFromIntent); if (nfcbId != null) { try { nfcbId.connect(); if (nfcbId.isConnected()) AddLog("connect"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (nfcbId.isConnected()) { TwoIdInfoParam tTwoIdInfo = new TwoIdInfoParam(); if (m_nDeviceHandle == -1) { m_nDeviceHandle = mLotusCardDriver.OpenDevice("", 0, 0, 0, 0,// 使用內(nèi)部默認(rèn)超時(shí)設(shè)置 true); } bResult = mLotusCardDriver.GetTwoIdInfoByMcuServer(this, nfcbId, m_nDeviceHandle, "samv.highwillow.cn", 99999, "123456", tTwoIdInfo, 400000, 0, 2, false); if (!bResult) { nErrorCode = mLotusCardDriver.GetTwoIdErrorCode(m_nDeviceHandle); AddLog("Call GetTwoIdInfoByMcuServer Error! ErrorCode:" + nErrorCode); AddLog("ErrorInfo:" + mLotusCardDriver.GetIdErrorInfo(nErrorCode)); return; } AddLog("Call GetTwoIdInfoByMcuServer Ok!"); //處理照片 if (0x00 == tTwoIdInfo.unTwoIdPhotoJpegLength) { bWlDecodeResult = mLotusCardDriver.WlDecodeByServer(m_nDeviceHandle, "119.29.18.30", tTwoIdInfo); if (!bWlDecodeResult) { AddLog("Call WlDecodeByServer Error! "); } else { AddLog("Call WlDecodeByServer Ok!"); } } if (true == bResult) { // 姓名 try { temp = new String(tTwoIdInfo.arrTwoIdName, 0, 30, "UTF-16LE").trim(); if (temp.equals("")) { AddLog("數(shù)據(jù)為空"); return; } AddLog("姓名:" + temp); // 性別 temp = new String(tTwoIdInfo.arrTwoIdSex, 0, 2, "UTF-16LE").trim(); if (temp.equals("1")) temp = "男"; else temp = "女"; AddLog("性別:" + temp); // 民族 temp = new String(tTwoIdInfo.arrTwoIdNation, 0, 4, "UTF-16LE").trim(); try { int code = Integer.parseInt(temp.toString()); temp = decodeNation(code); } catch (Exception e) { temp = ""; } AddLog("民族:" + temp); // 出生日期 temp = new String(tTwoIdInfo.arrTwoIdBirthday, 0, 16, "UTF-16LE").trim(); AddLog("出生日期:" + temp); // 住址 temp = new String(tTwoIdInfo.arrTwoIdAddress, 0, 70, "UTF-16LE").trim(); AddLog("住址:" + temp); // 身份證號(hào)碼 temp = new String(tTwoIdInfo.arrTwoIdNo, 0, 36, "UTF-16LE").trim(); AddLog("身份證號(hào)碼:" + temp); // 簽發(fā)機(jī)關(guān) temp = new String( tTwoIdInfo.arrTwoIdSignedDepartment, 0, 30, "UTF-16LE").trim(); AddLog("簽發(fā)機(jī)關(guān):" + temp); // 有效期起始日期 temp = new String( tTwoIdInfo.arrTwoIdValidityPeriodBegin, 0, 16, "UTF-16LE").trim(); AddLog("有效期起始日期:" + temp); // 有效期截止日期 UNICODE YYYYMMDD 有效期為長期時(shí)存儲(chǔ)“長期” temp = new String( tTwoIdInfo.arrTwoIdValidityPeriodEnd, 0, 16, "UTF-16LE").trim(); AddLog("有效期截止日期:" + temp); if (tTwoIdInfo.unTwoIdPhotoJpegLength > 0) { Bitmap photo = BitmapFactory.decodeByteArray( tTwoIdInfo.arrTwoIdPhotoJpeg, 0, tTwoIdInfo.unTwoIdPhotoJpegLength); m_imgIdPhoto.setBackgroundDrawable(new BitmapDrawable(photo)); } } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } else { AddLog("GetTwoIdInfoByMcuServer執(zhí)行失敗"); } } } } } private String decodeNation(int code) { String nation; switch (code) { case 1: nation = "漢"; break; case 2: nation = "蒙古"; break; case 3: nation = "回"; break; case 4: nation = "藏"; break; case 5: nation = "維吾爾"; break; case 6: nation = "苗"; break; case 7: nation = "彝"; break; case 8: nation = "壯"; break; case 9: nation = "布依"; break; case 10: nation = "朝鮮"; break; case 11: nation = "滿"; break; case 12: nation = "侗"; break; case 13: nation = "瑤"; break; case 14: nation = "白"; break; case 15: nation = "土家"; break; case 16: nation = "哈尼"; break; case 17: nation = "哈薩克"; break; case 18: nation = "傣"; break; case 19: nation = "黎"; break; case 20: nation = "傈僳"; break; case 21: nation = "佤"; break; case 22: nation = "畬"; break; case 23: nation = "高山"; break; case 24: nation = "拉祜"; break; case 25: nation = "水"; break; case 26: nation = "東鄉(xiāng)"; break; case 27: nation = "納西"; break; case 28: nation = "景頗"; break; case 29: nation = "柯爾克孜"; break; case 30: nation = "土"; break; case 31: nation = "達(dá)斡爾"; break; case 32: nation = "仫佬"; break; case 33: nation = "羌"; break; case 34: nation = "布朗"; break; case 35: nation = "撒拉"; break; case 36: nation = "毛南"; break; case 37: nation = "仡佬"; break; case 38: nation = "錫伯"; break; case 39: nation = "阿昌"; break; case 40: nation = "普米"; break; case 41: nation = "塔吉克"; break; case 42: nation = "怒"; break; case 43: nation = "烏孜別克"; break; case 44: nation = "俄羅斯"; break; case 45: nation = "鄂溫克"; break; case 46: nation = "德昂"; break; case 47: nation = "保安"; break; case 48: nation = "裕固"; break; case 49: nation = "京"; break; case 50: nation = "塔塔爾"; break; case 51: nation = "獨(dú)龍"; break; case 52: nation = "鄂倫春"; break; case 53: nation = "赫哲"; break; case 54: nation = "門巴"; break; case 55: nation = "珞巴"; break; case 56: nation = "基諾"; break; case 97: nation = "其他"; break; case 98: nation = "外國血統(tǒng)中國籍人士"; break; default: nation = ""; } return nation; } public String toHexString(byte[] d, int s, int n) { final char[] ret = new char[n * 2]; final int e = s + n; int x = 0; for (int i = s; i < e; ++i) { final byte v = d[i]; ret[x++] = HEX[0x0F & (v >> 4)]; ret[x++] = HEX[0x0F & v]; } return new String(ret); } public String toHexStringR(byte[] d, int s, int n) { final char[] ret = new char[n * 2]; int x = 0; for (int i = s + n - 1; i >= s; --i) { final byte v = d[i]; ret[x++] = HEX[0x0F & (v >> 4)]; ret[x++] = HEX[0x0F & v]; } return new String(ret); } public boolean callBackExtendIdDeviceProcess(Object objUser, byte[] arrBuffer) { // TODO Auto-generated method stub boolean bResult = false; NfcB nfcbId = (NfcB) objUser; if (null == nfcbId) return false; byte[] arrCommnad = new byte[arrBuffer[0]]; System.arraycopy(arrBuffer, 1, arrCommnad, 0, arrBuffer[0]); //AddLog("執(zhí)行指令"+arrCommnad.length); m_nCommandInex++; showCommandIndex(m_nCommandInex); try { //Log.i("LOTUS_CARD_DRIVER","Send "+toHexString(arrCommnad, 0, arrCommnad.length)); byte[] arrResult = nfcbId.transceive(arrCommnad); //Log.i("LOTUS_CARD_DRIVER","Receive "+toHexString(arrResult, 0, arrResult.length)); if (LotusCardDriver.isZero(arrResult)) { AddLog("讀取卡片數(shù)據(jù)全部為0"); } else { if (arrResult.length > 2) { if (((byte) 0x90 == arrResult[arrResult.length - 3]) && ((byte) 0x00 == arrResult[arrResult.length - 2]) && ((byte) 0x00 == arrResult[arrResult.length - 1])) { arrBuffer[0] = (byte) (arrResult.length - 1); } else { arrBuffer[0] = (byte) (arrResult.length); } } else { arrBuffer[0] = (byte) (arrResult.length); } System.arraycopy(arrResult, 0, arrBuffer, 1, arrBuffer[0]); bResult = true; } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); AddLog(e.getMessage()); } return bResult; } private Boolean SetUsbCallBack() { Boolean bResult = false; PendingIntent pendingIntent; pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent( ACTION_USB_PERMISSION), 0); m_UsbManager = (UsbManager) getSystemService(USB_SERVICE); if (null == m_UsbManager) return bResult; HashMap<String, UsbDevice> deviceList = m_UsbManager.getDeviceList(); if (!deviceList.isEmpty()) { for (UsbDevice device : deviceList.values()) { if ((m_nVID == device.getVendorId()) && (m_nPID == device.getProductId())) { m_LotusCardDevice = device; m_strDeviceNode = m_LotusCardDevice.getDeviceName(); break; } } } if (null == m_LotusCardDevice) return bResult; m_LotusCardInterface = m_LotusCardDevice.getInterface(0); if (null == m_LotusCardInterface) return bResult; if (false == m_UsbManager.hasPermission(m_LotusCardDevice)) { m_UsbManager.requestPermission(m_LotusCardDevice, pendingIntent); } UsbDeviceConnection conn = null; if (m_UsbManager.hasPermission(m_LotusCardDevice)) { conn = m_UsbManager.openDevice(m_LotusCardDevice); } if (null == conn) return bResult; if (conn.claimInterface(m_LotusCardInterface, true)) { m_LotusCardDeviceConnection = conn; } else { conn.close(); } if (null == m_LotusCardDeviceConnection) return bResult; // 把上面獲取的對(duì)性設(shè)置到接口中用于回調(diào)操作 m_UsbDeviceConnection = m_LotusCardDeviceConnection; if (m_LotusCardInterface.getEndpoint(1) != null) { m_OutEndpoint = m_LotusCardInterface.getEndpoint(1); } if (m_LotusCardInterface.getEndpoint(0) != null) { m_InEndpoint = m_LotusCardInterface.getEndpoint(0); } bResult = true; return bResult; } @Override public boolean callBackReadWriteProcess(long nDeviceHandle, boolean bRead, byte[] arrBuffer) { int nResult = 0; boolean bResult = false; int nBufferLength = arrBuffer.length; int nWaitCount = 0; if (null == m_UsbDeviceConnection) return false; if (null == m_OutEndpoint) return false; if (null == m_InEndpoint) return false; //AddLog("callBackReadWriteProcess nBufferLength:" + nBufferLength); if (nBufferLength < 65) return false; if (true == bRead) { arrBuffer[0] = 0; while (true) { nResult = m_UsbDeviceConnection.bulkTransfer(m_InEndpoint, arrBuffer, 64, 5000); if (nResult <= 0) break; if (arrBuffer[0] != 0) { //此處調(diào)整一下 System.arraycopy(arrBuffer, 0, arrBuffer, 1, nResult); arrBuffer[0] = (byte) nResult; break; } nWaitCount++; if (nWaitCount > 1000) break; } if (nResult < 64) AddLog("m_InEndpoint bulkTransfer Read:" + nResult); if (nResult == 64) { bResult = true; } else { bResult = false; } } else { nResult = m_UsbDeviceConnection.bulkTransfer(m_OutEndpoint, arrBuffer, 64, 3000); //AddLog("m_OutEndpoint bulkTransfer Write:"+nResult); if (nResult == 64) { bResult = true; //AddLog("m_OutEndpoint bulkTransfer Write Ok!"); } else { bResult = false; } } return bResult; } }
注意:以下兩個(gè)文本框需要輸入并獲取正確的用戶名和密碼才能接入解析服務(wù)器。
m_nDeviceHandle, "samv.highwillow.cn", Integer.valueOf(m_edtAccoutCode.getText().toString()), m_edtUserPassword.getText().toString(), tTwoIdInfo, Long.valueOf(m_edtPostCode.getText().toString()), 0, 2, true);
以上內(nèi)容是關(guān)于NFC手機(jī)二代身份證閱讀開發(fā)說明,僅供參考!
聯(lián)系人: | 張經(jīng)理 |
---|---|
電話: | 400-023-6659 |
傳真: | 023-68798110 |
Email: | 843718693@qq.com |
QQ: | 843718693 |
微信: | Lotus-Smart |
微博: | lotusreader |
旺旺: | 諾塔斯智能科技有限公司 |
地址: | 重慶市江北區(qū)宏帆路36號(hào)宏帆天地1棟6樓 |