Android系統(tǒng)接入IC卡讀寫器 Android系統(tǒng)IC卡讀寫器二次開發(fā)說明
- 2019-07-01 14:41:00
- 諾塔斯智能科技 原創(chuàng)
- 3547
隨著國家2035年計劃的提出,以及國家十三五規(guī)劃等全面的提出信息安全被提升到國家安全的層面,工業(yè)領(lǐng)域的發(fā)展更是提高到新的高度,搭載Android系統(tǒng)的設(shè)備被廣泛用于電力行業(yè)、石油石化行業(yè)軌道交通及先進制造業(yè)。目前,市面上支持Android系統(tǒng)的智能卡讀寫器還是比較少,有部分采用串口通信的IC卡讀寫,在與Android設(shè)備進行接入和二次開發(fā)過程中非常不方便。因此,諾塔斯智能科技有限公司早在2013年就推出了基于Android系統(tǒng)免驅(qū)的USB 和串口,藍(lán)牙,WIFI、RJ45有線網(wǎng)絡(luò)等多種通信方式的智能卡讀寫器。
以下內(nèi)容是針對諾塔斯L3-U非接觸式IC卡讀寫器在Android系統(tǒng)中的二次開發(fā)范例說明,其它型號的智能卡讀寫器在Android系統(tǒng)中的二次開發(fā),大致相同,修改設(shè)備初始化參數(shù)即可,具體可以在開發(fā)過程中咨詢技術(shù)支持。
首先,需要Android設(shè)備支持USB HOST或者OTG通信,在AndroidManifest.xml文件中進行USB權(quán)限配置。
Android配置文件要求
在你使用以上API進行開發(fā)之前,你需要在你的AndroidManifest.xml文件中添加以下內(nèi)容:
1.因為并不能保證所有的安卓設(shè)備都支持以上API,所以你需要聲明:
<uses-sdk android:minSdkVersion="12" />12以下的版本是不支持以上APId的。
<uses-feature android:name="android.hardware.usb.host" />
2.如果你想有一個USB設(shè)備接入你的安卓設(shè)備時能夠通知你的應(yīng)用程序,那么你需要在你的Activity標(biāo)簽中聲明以下內(nèi)容
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" />
Resource屬性指定了要過濾的數(shù)據(jù)設(shè)備信息,包括:
1) vendor-id 設(shè)備生產(chǎn)商id
2) product-id 設(shè)備id
3) class 設(shè)備類別
4) subclass 設(shè)備子類
5) protocol(device or interface) 協(xié)議類別
device_filter.xml文件放在res\xml目錄下,其中文件名不包括擴展名部分需要與<meta-data/> 標(biāo)簽中聲明的一致。示例如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="1234" product-id="5678" class="255" subclass="66" protocol="1" />
</resources>
開發(fā)步驟
1、在Android開發(fā)工程文件夾libs文件夾中導(dǎo)入外部.so庫文件,我們?yōu)榭蛻籼峁┝硕喾N平臺的庫。包括,arm64-v8a、armeabi、armeabi-v7a、mips、mips64、x86、x86_64等,具體可以參考Android IC卡讀寫器二次開發(fā)范例。
2、定義關(guān)鍵參數(shù),以ISO14443 A卡為例,定義相關(guān)參數(shù)如下:
package cc.lotuscard; public class LotusCardParam { public LotusCardParam() { arrCardNo = new byte[8]; arrBuffer = new byte[64]; arrKeys = new byte[64]; arrCosResultBuffer = new byte[256]; arrCosSendBuffer = new byte[256]; } /** * 卡片類型 */ public int nCardType; /** * 8字節(jié)卡號 */ public byte[] arrCardNo; /** * 卡片容量大小 */ public int nCardSize; /** * 讀寫緩沖 */ public byte[] arrBuffer; /** * 緩沖大小 */ public int nBufferSize; /** * 密鑰 */ public byte[] arrKeys; /** * KEYs大小 * */ public int nKeysSize; /** * pCosResultBuffer COS執(zhí)行結(jié)果緩沖 */ public byte[] arrCosResultBuffer; /** * unCosReultBufferLength COS執(zhí)行結(jié)果緩沖長度 */ public int unCosReultBufferLength; /** * pCosSendBuffer COS指令發(fā)送緩沖 */ public byte[] arrCosSendBuffer; /** * unCosSendBufferLength COS指令發(fā)送緩沖長度 */ public int unCosSendBufferLength; }
注意:包名必須按照 package cc.lotuscard;這種格式。
3、針對Mifare S50非接觸式IC卡的讀寫操作,如下:
package cn.highwillow.m1test; import android.app.PendingIntent; import android.content.Intent; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbInterface; import android.hardware.usb.UsbManager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.ImageView; import android.os.Bundle; import android.os.Handler; import android.os.Message; import java.sql.Date; import java.text.SimpleDateFormat; import java.util.HashMap; import cc.lotuscard.ILotusCallBack; import cc.lotuscard.LotusCardDriver; import cc.lotuscard.LotusCardParam; import static cc.lotuscard.LotusCardDriver.m_InEndpoint; import static cc.lotuscard.LotusCardDriver.m_OutEndpoint; import static cc.lotuscard.LotusCardDriver.m_UsbDeviceConnection; public class MainActivity extends AppCompatActivity implements ILotusCallBack { private EditText m_edtLog; private ImageView m_imgIdPhoto; 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 Handler m_Handler = null; private LotusCardDriver mLotusCardDriver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); m_edtLog = (EditText) findViewById(R.id.edtLog); m_imgIdPhoto = (ImageView) findViewById(R.id.imgIdPhoto); // 設(shè)置USB讀寫回調(diào) 串口可以不用此操作 m_bCanUseUsbHostApi = SetUsbCallBack(); if (m_bCanUseUsbHostApi) { AddLog("Find LotusSmart IC Reader!"); AddLog("Device Node:" + m_strDeviceNode); } else { AddLog("Not Find LotusSmart IC Reader!"); } mLotusCardDriver = new LotusCardDriver(); mLotusCardDriver.m_lotusCallBack = this; } public void OnClearLogListener(View arg0) { if (null != m_imgIdPhoto) { m_imgIdPhoto.setBackgroundColor(0); } if (null == m_edtLog) return; m_edtLog.setText(""); } 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; // 把上面獲取的對性設(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; } public void AddLog(String strLog) { //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)前時間 String strDate = formatter.format(curDate); if (null == m_edtLog) return; String strLogs = m_edtLog.getText().toString().trim(); if (strLogs.equals("")) { strLogs = strDate + " " + strLog; } else { strLogs += "\r\n" + strDate + " " + strLog; } m_edtLog.setText(strLogs); } public void OnTestM1Listener(View arg0) { if (null == mLotusCardDriver) return; if (m_nDeviceHandle == -1) { m_nDeviceHandle = mLotusCardDriver.OpenDevice("", 0, 0, 0, 0,// 使用內(nèi)部默認(rèn)超時設(shè)置 true); } if (m_nDeviceHandle != -1) { AddLog("Open Device Success!"); testIcCardReader(m_nDeviceHandle); } else { AddLog("Open Device False!"); } } public long bytes2long(byte[] byteNum) { long num = 0; for (int ix = 3; ix >= 0; --ix) { num <<= 8; if (byteNum[ix] < 0) { num |= (256 + (byteNum[ix]) & 0xff); } else { num |= (byteNum[ix] & 0xff); } } return num; } public String leftString(String strText, int nLeftLength) { if (1 == strText.length()) strText = "0" + strText; if (strText.length() <= nLeftLength) return strText; return strText.substring(strText.length() - nLeftLength, strText.length()); } private void testIcCardReader(long nDeviceHandle) { boolean bResult = false; int nRequestType; long lCardNo = 0; LotusCardParam tLotusCardParam1 = new LotusCardParam(); bResult = mLotusCardDriver.Beep(nDeviceHandle, 10); // bResult = mLotusCardDriver.Beep(nDeviceHandle, 10); if (!bResult) { AddLog("Call Beep Error!"); return; } AddLog("Call Beep Ok!"); nRequestType = LotusCardDriver.RT_NOT_HALT; // 以下3個函數(shù)可以用GetCardNo替代 // bResult = mLotusCardDriver.Request(nDeviceHandle, nRequestType, // tLotusCardParam1); // if (!bResult) // return; // bResult = mLotusCardDriver.Anticoll(nDeviceHandle, tLotusCardParam1); // if (!bResult) // return; // bResult = mLotusCardDriver.Select(nDeviceHandle, tLotusCardParam1); // if (!bResult) // return; bResult = mLotusCardDriver.GetCardNo(nDeviceHandle, nRequestType, tLotusCardParam1); if (!bResult) { AddLog("Call GetCardNo Error!"); return; } lCardNo = bytes2long(tLotusCardParam1.arrCardNo); AddLog("Call GetCardNo Ok!"); AddLog("CardNo(DEC):" + lCardNo); AddLog("CardNo(HEX):" + leftString( Integer.toHexString(tLotusCardParam1.arrCardNo[3]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrCardNo[2]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrCardNo[1]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrCardNo[0]), 2) .toUpperCase()); tLotusCardParam1.arrKeys[0] = (byte) 0xff; tLotusCardParam1.arrKeys[1] = (byte) 0xff; tLotusCardParam1.arrKeys[2] = (byte) 0xff; tLotusCardParam1.arrKeys[3] = (byte) 0xff; tLotusCardParam1.arrKeys[4] = (byte) 0xff; tLotusCardParam1.arrKeys[5] = (byte) 0xff; tLotusCardParam1.nKeysSize = 6; boolean bUseLoadKey = false; if(true == bUseLoadKey) { bResult = mLotusCardDriver.LoadKey(nDeviceHandle, LotusCardDriver.AM_A, 0, tLotusCardParam1); if (!bResult) { AddLog("Call LoadKey Error!"); return; } AddLog("Call LoadKey Ok!"); bResult = mLotusCardDriver.Authentication(nDeviceHandle, LotusCardDriver.AM_A, 0, tLotusCardParam1); } else { //直接使用參數(shù)里面的密碼 bResult = mLotusCardDriver.AuthenticationWithPassword(nDeviceHandle, LotusCardDriver.AM_A, 0, tLotusCardParam1); } if (!bResult) { AddLog("Call Authentication(A) Error!"); return; } AddLog("Call Authentication(A) Ok!"); bResult = mLotusCardDriver.Read(nDeviceHandle, 1, tLotusCardParam1); if (!bResult) { AddLog("Call Read Error!"); return; } AddLog("Call Read Ok!"); AddLog("Buffer(HEX):" + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[0]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[1]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[2]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[3]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[4]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[5]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[6]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[7]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[8]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[9]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[0xa]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[0xb]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[0xc]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[0xd]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[0xe]), 2) .toUpperCase() + leftString( Integer.toHexString(tLotusCardParam1.arrBuffer[0xf]), 2) .toUpperCase()); tLotusCardParam1.arrBuffer[0] = (byte) 0x10; tLotusCardParam1.arrBuffer[1] = (byte) 0x01; tLotusCardParam1.arrBuffer[2] = (byte) 0x02; tLotusCardParam1.arrBuffer[3] = (byte) 0x03; tLotusCardParam1.arrBuffer[4] = (byte) 0x04; tLotusCardParam1.arrBuffer[5] = (byte) 0x05; tLotusCardParam1.arrBuffer[6] = (byte) 0x06; tLotusCardParam1.arrBuffer[7] = (byte) 0x07; tLotusCardParam1.arrBuffer[8] = (byte) 0x08; tLotusCardParam1.arrBuffer[9] = (byte) 0x09; tLotusCardParam1.arrBuffer[10] = (byte) 0x0a; tLotusCardParam1.arrBuffer[11] = (byte) 0x0b; tLotusCardParam1.arrBuffer[12] = (byte) 0x0c; tLotusCardParam1.arrBuffer[13] = (byte) 0x0d; tLotusCardParam1.arrBuffer[14] = (byte) 0x0e; tLotusCardParam1.arrBuffer[15] = (byte) 0x0f; tLotusCardParam1.nBufferSize = 16; bResult = mLotusCardDriver.Write(nDeviceHandle, 1, tLotusCardParam1); if (!bResult) { AddLog("Call Write Error!"); return; } AddLog("Call Write Ok!"); } @Override public boolean callBackExtendIdDeviceProcess(Object objUser, byte[] arrBuffer) { return false; } @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, 3000); 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; } //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; } }
以上內(nèi)容是關(guān)于Android系統(tǒng)接入IC卡讀寫器,以讀寫Mifare One S50非接觸式IC卡為例的非接觸式IC卡讀寫器Android開發(fā)范例。更多IC卡讀寫器Android開發(fā)范例,請下載我們的SDK范例源碼。
聯(lián)系人: | 張經(jīng)理 |
---|---|
電話: | 400-023-6659 |
傳真: | 023-68798110 |
Email: | 843718693@qq.com |
QQ: | 843718693 |
微信: | Lotus-Smart |
微博: | lotusreader |
旺旺: | 諾塔斯智能科技有限公司 |
地址: | 重慶市江北區(qū)宏帆路36號宏帆天地1棟6樓 |