Android系統接入IC卡讀寫器 Android系統IC卡讀寫器二次開發說明
- 2019-07-01 14:41:00
- 諾塔斯智能科技 原創
- 4764
隨著國家2035年計劃的提出,以及國家十三五規劃等全面的提出信息安全被提升到國家安全的層面,工業領域的發展更是提高到新的高度,搭載Android系統的設備被廣泛用于電力行業、石油石化行業軌道交通及先進制造業。目前,市面上支持Android系統的智能卡讀寫器還是比較少,有部分采用串口通信的IC卡讀寫,在與Android設備進行接入和二次開發過程中非常不方便。因此,諾塔斯智能科技有限公司早在2013年就推出了基于Android系統免驅的USB 和串口,藍牙,WIFI、RJ45有線網絡等多種通信方式的智能卡讀寫器。
以下內容是針對諾塔斯L3-U非接觸式IC卡讀寫器在Android系統中的二次開發范例說明,其它型號的智能卡讀寫器在Android系統中的二次開發,大致相同,修改設備初始化參數即可,具體可以在開發過程中咨詢技術支持。
首先,需要Android設備支持USB HOST或者OTG通信,在AndroidManifest.xml文件中進行USB權限配置。
Android配置文件要求
在你使用以上API進行開發之前,你需要在你的AndroidManifest.xml文件中添加以下內容:
1.因為并不能保證所有的安卓設備都支持以上API,所以你需要聲明:
<uses-sdk android:minSdkVersion="12" />12以下的版本是不支持以上APId的。
<uses-feature android:name="android.hardware.usb.host" />
2.如果你想有一個USB設備接入你的安卓設備時能夠通知你的應用程序,那么你需要在你的Activity標簽中聲明以下內容
<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屬性指定了要過濾的數據設備信息,包括:
1) vendor-id 設備生產商id
2) product-id 設備id
3) class 設備類別
4) subclass 設備子類
5) protocol(device or interface) 協議類別
device_filter.xml文件放在res\xml目錄下,其中文件名不包括擴展名部分需要與<meta-data/> 標簽中聲明的一致。示例如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="1234" product-id="5678" class="255" subclass="66" protocol="1" />
</resources>
開發步驟
1、在Android開發工程文件夾libs文件夾中導入外部.so庫文件,我們為客戶提供了多種平臺的庫。包括,arm64-v8a、armeabi、armeabi-v7a、mips、mips64、x86、x86_64等,具體可以參考Android IC卡讀寫器二次開發范例。
2、定義關鍵參數,以ISO14443 A卡為例,定義相關參數如下:
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字節卡號
*/
public byte[] arrCardNo;
/**
* 卡片容量大小
*/
public int nCardSize;
/**
* 讀寫緩沖
*/
public byte[] arrBuffer;
/**
* 緩沖大小
*/
public int nBufferSize;
/**
* 密鑰
*/
public byte[] arrKeys;
/**
* KEYs大小
*
*/
public int nKeysSize;
/**
* pCosResultBuffer COS執行結果緩沖
*/
public byte[] arrCosResultBuffer;
/**
* unCosReultBufferLength COS執行結果緩沖長度
*/
public int unCosReultBufferLength;
/**
* pCosSendBuffer COS指令發送緩沖
*/
public byte[] arrCosSendBuffer;
/**
* unCosSendBufferLength COS指令發送緩沖長度
*/
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);
// 設置USB讀寫回調 串口可以不用此操作
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;
// 把上面獲取的對性設置到接口中用于回調操作
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());// 獲取當前時間
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,// 使用內部默認超時設置
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個函數可以用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 {
//直接使用參數里面的密碼
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) {
//此處調整一下
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;
}
}
以上內容是關于Android系統接入IC卡讀寫器,以讀寫Mifare One S50非接觸式IC卡為例的非接觸式IC卡讀寫器Android開發范例。更多IC卡讀寫器Android開發范例,請下載我們的SDK范例源碼。
| 聯系人: | 張經理 |
|---|---|
| 電話: | 400-023-6659 |
| 傳真: | 023-68798110 |
| Email: | 843718693@qq.com |
| QQ: | 843718693 |
| 微信: | Lotus-Smart |
| 微博: | lotusreader |
| 旺旺: | 諾塔斯智能科技有限公司 |
| 地址: | 重慶市江北區宏帆路36號宏帆天地1棟6樓 |
-
在線客服

-
關注微信

-
網上商城

