本文来自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手机的简单通信。

接下来贴段简单的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 registrationnew 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 intentTECHLISTS = 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 deviceisoDep.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卡信息保存在服务器,智能IC卡网络数据安全保密系统

    <智能IC卡网络数据安全保密系统>由会员分享,可在线阅读,更多相关<智能IC卡网络数据安全保密系统(3页珍藏版)>请在人人文库网上搜索. 1.一. 系统组成智能IC卡是一种内部 ...

  2. 商用密码产品认证-智能IC卡

    商用密码产品认证-智能IC卡 产品概述 相关标准规范 应用要点 产品概述 智能IC卡是将一个或多个集成电路芯片嵌装于塑料基片上制成的卡片,卡内的集成电路具有数据存储.运算和判断功能,并能与外部进行数据 ...

  3. 基于51单片机智能IC卡电表控制系统

    资料编号:201 功能介绍: 采用51单片机作为主控CPU,使用按键进行模拟冲卡(模拟缴费冲卡),通过按键来控制当前是否使用电力,并且LCD1602实时显示当前电力可用量剩余多少,当电力余额不足时,发 ...

  4. 智能IC卡国密标准GMT0041-2015

    智能IC卡是实现密码运算和密钥管理 功能的含 CPU(中央处理 器)的集成电路卡,包括应 用于金融等行业领域的智能IC卡.相关标准包括: (1)GM/T0041-2015 智能IC卡密码检测规范(密码 ...

  5. 智能IC卡称重系统流程及技术要求

    1.司机至开卡处凭行车本或身份证领取智能IC卡:发卡主要有两种模式: 自助发卡:系统内已有车辆信息,司机可通过身份证扫描,自助领取IC卡,对于装车量等信息,由司机手动通过触摸屏录入,录入完毕,点击&q ...

  6. 电子门禁系统及智能IC卡标准与产品

    电子门禁系统及智能IC卡标准与产品 产品概述 电子门禁系统能够对重要区域人员进出的进行管理管理,是实现物理和环境访问控制的有效手段,目前常见的是以人员拥有非接触式智能IC卡(以下统称智能IC卡)为鉴别 ...

  7. 在web浏览器中如何使用智能IC卡来登录系统

    在web浏览器中如何使用智能IC卡来登录系统呢? 在BS架构软件中,使用刷智能IC卡来登录系统,而不是输入用户名和密码,这样不仅快而且方便,让使用者有更好的体验.要实现这种功能,其实并不难.按照以下步 ...

  8. 基于51单片机智能IC卡水表控制系统(仿真+源程序+全套资料)

    资料编号:200 功能介绍: 采用51单片机作为主控CPU,使用按键进行模拟冲卡(模拟缴费冲卡),通过按键来控制当前是否使用自来水,并且LCD1602实时显示当前自来水可用量剩余多少,当自来水余额不足 ...

  9. Android手机 通过NFC读取二代证信息

    Android手机 通过NFC读取二代证信息 APK安装包和源码链接 代码示例 本文推荐一个安卓手机通过NFC读取二代证的SDK,目前市面上已经很多通过云解析来读取二代证的SDK,但是都有一个通病:对 ...

最新文章

  1. 一篇与众不同的 String、StringBuilder 和 StringBuffer 详解
  2. 成立两年,他们用产品描绘出了基于第三代AI的基础设施蓝图
  3. java 简单的计算器程序,Java 简易计算器程序
  4. 用python查找指定格式或名称的文件及修改指定文件夹名称
  5. php jq异步上传图片,Jquery实现异步上传图片
  6. Spring Boot笔记-JPA中自定义@Query分页查询
  7. 4位格雷码的顺序编码_格雷码的编码和译码算法.doc
  8. mindoc mysql_mindoc
  9. 【基础编程】最大子列和问题
  10. 计算机网络中处理通信控制功能的是,在计算机网络中处理通信控制功能的计算机是()。A.通信线路B.终端C.主计算机D.通信控制处理机...
  11. c语言程序主要的结构特点是什么,1. C语言的结构特点?
  12. iOS10访问通讯录、相册等隐私权限设置
  13. Python变量命名用法(一般变量、常量、私有变量、内置变量)
  14. 如何在小内存主机上搭建博客
  15. 贴花纸怎么贴_谁知道墙壁贴花纸怎么贴
  16. 20、MySQL分库分表,原理实战
  17. 蓝牙(七)L2CAP层协议解析
  18. java源文件的编写与保存_1.编写源代码编写源文件:CardLayoutDemo.java并保存,例如:I:myAppCardLayoutDemo.java。程序结构如下:p...
  19. 用python写了个全国疫情中高风险地区查询
  20. 判断某年某月有多少天

热门文章

  1. 965七年我失去了什么?得到了什么?
  2. 从阿里巴巴IPO联想到创始人和资方关系
  3. 嵌入式最全的C和C++面试题
  4. Mac 定时关机、重启、休眠命令
  5. 《web课程设计》 基于HTML+CSS+JavaScript实现中国水墨风的小学学校网站模板(6个网页)
  6. html隐藏文字 点击查看更多,js 文字超出部分隐藏、点击显示更多示例
  7. 知识与知识表示的概念
  8. 排序之快速排序的java语言简单实现
  9. 富华力鼎:抖音短视频的运营技巧
  10. python两个除号什么意思_python中的除号