本文来自http://blog.csdn.net/hellogv/ 。引用必须注明出处。
       眼下常见的智能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手机的简单通信。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVsbG9ndg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

接下来贴段简单的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。

核心源代码例如以下:

public class mytest extends Applet {

	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"。

核心源代码例如以下:

public final class CardReader {
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 for dispatching of the ACTION_TECH_DISCOVERED intent
TECHLISTS = new String[][] { { IsoDep.class.getName() }}; FILTERS = new IntentFilter[] { new IntentFilter(
NfcAdapter.ACTION_TECH_DISCOVERED, "*/*") };
} catch (Exception e) {
}
} static public String tagDiscovered(Tag tag) {
Log.e(TAG, "New tag discovered"); String strResult="";
IsoDep isoDep = IsoDep.get(tag);
if (isoDep != null) {
try {
// Connect to the remote NFC device
isoDep.connect(); //发送select 命令,卡片会返回SELECT_OK_SW(90 00)
byte[] cmdSelect = BuildSelectApdu(SAMPLE_CARD_AID);
Log.e(TAG, "Sending: " + ByteArrayToHexString(cmdSelect));
byte[] result = isoDep.transceive(cmdSelect);
Log.e(TAG, "Receive: " + ByteArrayToHexString(result));
byte[][] response = getResponse(result);
byte[] statusWord =response[0]; if (Arrays.equals(SELECT_OK_SW, statusWord) == false)
return ""; //循环发送自己定义命令
for(int i=0;i<SAMPLE_COMMAND.length;i++){
String command = SAMPLE_COMMAND[i];
result = HexStringToByteArray(command);
Log.e(TAG, "Sending: " + command); result = isoDep.transceive(result);
Log.e(TAG, "Receive: " + ByteArrayToHexString(result));
response = getResponse(result);
byte[] body =response[1]; strResult=strResult+new String(body)+":"+ByteArrayToHexString(body)+"\r\n";
} return strResult; } catch (IOException e) {
Log.e(TAG, "Error communicating with card: " + e.toString());
}
}
return null;
} /***
* 分解卡片返回的数据
* @param b
* @return [0]表示返回的状态值,[1]表示返回的正文
*/
private static byte[][] getResponse(byte[] b){
byte[][] result = new byte[2][]; int length = b.length;
byte[] status = { b[length - 2],b[length - 1] }; byte[] body = Arrays.copyOf(b, length - 2); result[0]=status;
result[1]=body;
return result;
} public static String load(Parcelable parcelable) {
// 从Parcelable筛选出各类NFC标准数据
final Tag tag = (Tag) parcelable;
return tagDiscovered(tag);
} /**
* Build APDU for SELECT AID command. This command indicates which service a reader is
* interested in communicating with. See ISO 7816-4.
*
* @param aid Application ID (AID) to select
* @return APDU for SELECT AID command
*/
public static byte[] BuildSelectApdu(String aid) {
// Format: [CLASS | INSTRUCTION | PARAMETER 1 | PARAMETER 2 | LENGTH | DATA]
return HexStringToByteArray(SELECT_APDU_HEADER + String.format("%02X", aid.length() / 2) + aid);
} /**
* Utility class to convert a byte array to a hexadecimal string.
*
* @param bytes Bytes to convert
* @return String, containing hexadecimal representation.
*/
public static String ByteArrayToHexString(byte[] bytes) {
final char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
char[] hexChars = new char[bytes.length * 2];
int v;
for ( int j = 0; j < bytes.length; j++ ) {
v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
} /**
* Utility class to convert a hexadecimal string to a byte string.
*
* <p>Behavior with input strings containing non-hexadecimal characters is undefined.
*
* @param s String containing hexadecimal characters to convert
* @return Byte array generated from input
*/
public static byte[] HexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
}

移动支付之智能IC卡与Android手机进行NFC通信的更多相关文章

  1. "软掩膜"和“硬掩膜”-智能IC卡

    目录 一.“软掩膜”和“硬掩膜”... 2 二.EMV迁移进程... 3 三.PBOC规范和EMV规范对比... 3 四.总结... 5 五.关于SDA和DDA. 6 一.“软掩膜”和“硬掩膜” “软 ...

  2. 智能IC卡中的文件系统

    1.文件系统是COS的重要模块之一,它负责组织.管理.维护IC卡内存储的所有数据. 文件系统的设计和实现既是COS系统中最灵活.最有个性的部分,也是对系统整体结构影响最大的模块之一. 2.在IC卡内, ...

  3. 智能IC卡与终端(读卡器)之间的传输协议

    1.有两种协议 T=0,异步半双工字符传输协议 T=1,异步半双工块传输协议 终端一般都支持这两种协议,IC卡可以选择支持其中的一种.(因为终端可能需要面对各种类型的卡片,所以必须两种协议都支持,而卡 ...

  4. WIFI环境下Android手机和电脑通信

    前面已经写过一篇java实现最基础的socket网络通信,这篇和之前那篇大同小异,只是将客户端代码移植到手机中,然后获取本机IP的方法略有不同. 先讲一下本篇中用到Android studio的使用吧 ...

  5. IC卡

    本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . IC卡 (Integrated Circuit Card,集成电路卡),也称智能卡(Smart card).智慧卡(Intelligent ...

  6. IC卡读卡器在安卓(android)下的开发

    友我科技推出IC卡读卡器的Android开发包,软件工程师只需要导入jar类库文件,就可以在App中操作IC卡读卡器了. 目前IC卡读卡器的Android开发包开放操作的卡类型有:M1, S50, U ...

  7. 电感耦合非接触IC卡系统的EMI问题

    射频识别(RFID)技术近年来发展迅速,并获得了广泛应用.但作为一种无线射频技术,其电磁兼容(EMC)性能也越来越受到人们的关注.RFID涉及的频率范围甚广,包括低于135kHz.13.56MHz.4 ...

  8. IC卡制作常识概述

    ic卡主要有9种:    1.接触型IC卡:    2.非接触型IC卡:    3.串行传输型IC卡:    4.并行传输型IC卡:    5.存储型IC卡:    6.智能型IC卡:    7.超级 ...

  9. 磁条卡,IC卡,ID卡,信用卡芯片卡,信用卡磁条卡 等等的区别

    1.条码卡:该卡卡面上有一串条码,通过扫描枪或者相应的条码读卡器读出该条码卡的卡号.根据条码的不同又分为39码等其它码.条码卡仅仅是一个编号,不存蓄其它内容.特点:价格便宜类似磁卡. 2.磁条卡:类似 ...

随机推荐

  1. [转] unix/linux下线程私有数据实现原理及使用方法

     在维护每个线程的私有数据的时候,我们可能会想到分配一个保存线程数据的数组,用线程的ID作为数组的索引来实现访问,但是有一个问题是系统生成的线程 ID不能保证是一个小而连续的整数,并且用数组实现的时候 ...

  2. LINUX进程上锁查看方法

    jps -l 获取进程列表 jstack -l 8672  查看详细信息 查找启动任务的class 查看状态

  3. Linux基础知识(一)

    1. Unix 和 Linux之间有什么关系? Linux可以说是Unix衍生过来的,它借鉴了很多Unix的设计理念,应该说,它们类似于父子关系,Linux又被称为类Unix系统. 2. BSD是什么 ...

  4. ASP.NET优化性能方法之一禁用调试模式(转)

    若要设置 ASP.NET 应用程序的调试模式,必须编辑应用程序的 Web.config 配置文件. 通常,ASP.NET 应用程序的 Web.config 文件与应用程序位于相同的 URL 位置上. ...

  5. AVD启动不了 ANDROID_SDK_HOME is defined but could not find *.ini

    报错提示______________________________________________________________________ Starting emulator for AVD ...

  6. Linq 关键字

    from var lowNums = from num in numbers            where num < 5            select num; numbers 是数 ...

  7. Tomcat 默认应用

    在部署应用时需要更改默认的端口号及应用,以免让别人知道使用的服务器类型而进行攻击.tomca的部署有多种方式,这里简单谈一下.目前想到有三种方式:一.添加 Context在Tomcat的配置文件中,一 ...

  8. tomcat 支持https

    HTTP是平时浏览网页时候使用的一种协议.HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全.为了保证 这些隐私数据能加密传输,于是网景公司设计了SSL(Se ...

  9. Contains Duplicate,Contains Duplicate II,Contains Duplicate III

    217. Contains Duplicate Given an array of integers, find if the array contains any duplicates. Your ...

  10. hdu5338 ZZX and Permutations(贪心、线段树)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud ZZX and Permutations Time Limit: 6000/300 ...