萬盛學電腦網

 萬盛學電腦網 >> 網絡編程 >> 安卓開發 >> 移動支付之智能IC卡與Android手機的NFC通信如何實現

移動支付之智能IC卡與Android手機的NFC通信如何實現

這是我們為大家提供的一篇介紹移動支付之智能IC卡與Android手機的NFC通信如何實現的文章,接下來就讓我們一起來了解一下吧!

目前常見的智能IC卡運行著JavaCard虛擬機,智能IC卡上可以運行由精簡後的Java語言編寫的卡應用(簡稱Applet)。智能IC卡的Applet不能自己啟動,必須由外部終端(例如POS機,地鐵刷卡終端等)向卡片發送Select命令,由此選中卡片的Applet,Applet才能運行。Appplet側重於數據的處理,沒有花銷的I/O功能。Applet的程序有生命周期和指定入口,其中最主要的幾個方法如下:

public static void install(byte[] bArray, short bOffset, byte bLength)

構建了Applet子類的實例,JCRE將會最先調用這個;所有的初始化和分配內存的操作應該在這個裡面實現;可以獲取卡外實體傳進來的一些應用初始化參數。

public void process(APDU apdu)

類似於正常java class的main,在安裝後,APDU的執行將在這裡實現。

protected final void register()

applet用來在JCRE中注冊該applet實例

register(byte[] bArray, short bOffset, byte bLength)

register( )功能一樣,增加了可以分配其特定的AID的功能。

public boolean select()

JCRE一旦接收到SELECT[by name]命令時,將尋找命令中指示的AID對應的Applet,使之處於活躍狀態,接收並處理接下來的APDU命令;在選擇新的Applet前,JCRE先調用當前Applet的 deselect 方法;Applet可以拒絕被選擇,此時 select 方法返回false;SELECT[by name]命令本身也將傳遞給applet處理,此時通過 selectingApplet 用以判斷當前狀態。

本文的DEMO運行效果如下,包含一個JavaCard的Applet實現和一個Android端的NFC讀寫程序,實現智能IC卡與Android手機的簡單通信。

移動支付之智能IC卡與Android手機的NFC通信

接下來貼段簡單的Applet 源碼,下載地址:http://download.csdn.net/detail/hellogv/8090041。

大概的思路是:Applet定義了2個開頭標識皆為CMD_CLA的自定義命令CMD_INS_1和CMD_INS_2,當Android手機通過NFC分別發送CMD_INS_1和CMD_INS_2,Applet分別返回strHello和strWorld。

核心源碼如下:

[java] view plaincopyprint?

在CODE上查看代碼片

派生到我的代碼片

 

private static final byte[] strHello= { (byte) 'H', (byte) 'e',

(byte) 'l', (byte) 'l', (byte) 'o'};

private static final byte[] strWorld = {(byte) 'W',

(byte) 'o', (byte) 'r', (byte) 'l', (byte) 'd', };

private static final byte CMD_CLA = (byte) 0x80;

private static final byte CMD_INS_1 = (byte) 0x10;

private static final byte CMD_INS_2 = (byte) 0x20;

public static void install(byte[] bArray, short bOffset, byte bLength) {

// GP-compliant JavaCard applet registration

new mytest().register(bArray, (short) (bOffset + 1), bArray[bOffset]);

}

/*

* 當Java卡Applet被選中時,由JCRE調用。Java卡Applet可以定義select()完成初始化,

* 否則,JCRE調用父類的select()。

* @see javacard.framework.Applet#select()

*/

public boolean select() {

short debug=100;

debug++;//用於斷點調試,當被select時觸發。

return super.select();

}

/*

* 當Java卡Applet被放棄時,由JCRE調用。Java卡Applet可以定義deselect()完成清除,

* 否則,JCRE調用父類的deselect()。

* @see javacard.framework.Applet#deselect()

*/

public void deselect() {

short debug=100;

debug++;//用於斷點調試

super.deselect();

}

/*

* 每次收到APDU命令,都會執行

* @see javacard.framework.Applet#process(javacard.framework.APDU)

*/

public void process(APDU apdu) {

if (selectingApplet()) {

return;

}

//獲取外部終端發過來的數據

byte[] buffer = apdu.getBuffer();

//獲取第一位數據

byte CLA = (byte) (buffer[ISO7816.OFFSET_CLA] & 0xFF);

//獲取第二位數據

byte INS = (byte) (buffer[ISO7816.OFFSET_INS] & 0xFF);

if (CLA != CMD_CLA) {//格式不對

ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);

}

switch (INS) {

case CMD_INS_1:

sendBytes(apdu,strHello);

break;

case CMD_INS_2:

sendBytes(apdu,strWorld);

break;

default:

ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);

}

}

private void sendBytes(APDU apdu,byte[] arrays) {

byte[] buffer = apdu.getBuffer();

short length = (short) arrays.length;

Util.arrayCopyNonAtomic(arrays, (short) 0, buffer, (short) 0,

(short) length);

apdu.setOutgoingAndSend((short) 0, length);

}

}

接下來貼出Android端的核心代碼,下載地址:http://download.csdn.net/detail/hellogv/8090053。

大概的思路是:Android端的NFC讀寫程序定義1個Applet的ID(AID),SELECT命令的報文頭(SELECT_APDU_HEADER),2個自定義命令CMD_INS_1和CMD_INS_2。首先使用AID和SELECT_APDU_HEADER生成完整的SELECT命令,transceive(發送)到卡片,用於啟動卡片裡的AID對應的Applet。啟動卡片裡的Applet後,NFC讀寫程序發送SAMPLE_COMMAND裡面的2條自定義命令,Applet分別返回"Hello""World"。

核心源碼如下:

[java] view plaincopyprint?

在CODE上查看代碼片

派生到我的代碼片

 

private static final String TAG = "LoyaltyCardReader";

// AID for our loyalty card service.

private static final String SAMPLE_CARD_AID = "1122001122";

// ISO-DEP command HEADER for selecting an AID.

// Format: [Class | Instruction | Parameter 1 | Parameter 2]

private static final String SELECT_APDU_HEADER = "00A40400";

// "OK" status word sent in response to SELECT AID command (0x9000)

private static final byte[] SELECT_OK_SW = {(byte) 0x90, (byte) 0x00};

//自定義的命令

private static final String[] SAMPLE_COMMAND={"8010000000",//卡片收到後返回"Hello"

"8020000000"};//卡片收到後返回"World"

public static String[][] TECHLISTS;

public static IntentFilter[] FILTERS;

static {

try {

//the tech lists used to perform matching f

copyright © 萬盛學電腦網 all rights reserved