本文来自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. 运行Python的三种方法
  2. Hibernate之mappedBy
  3. angular 指令渲染_Angular JS指令有后期渲染回调吗?
  4. CocoaPods 的使用与一些异常情况的处理
  5. linux proc 占用空间,一种诡异的Linux磁盘空间被占满问题
  6. 【51单片机快速入门指南】5.3:SPI控制晶联讯JLX12864G_08602 LCD屏幕
  7. FCPX插件:Color Titles动画彩色文本标题
  8. ResNet、Faster RCNN、Mask RCNN 是专利算法吗?盘点何恺明参与发明的专利!
  9. 细胞亚器文献阅读之酵母液泡与线粒体的动态互作A Dynamic Interface between Vacuoles and Mitochondria in Yeast
  10. Ubuntu安装caj阅读器
  11. 汽车计算机英语词汇,汽车专用英语词汇?
  12. yilia 的html模板,自己动手修改完善yilia主题(下)
  13. 电脑16G内存升级成32G内存日常使用区别大么?
  14. 离散数学在计算机科学中的应用
  15. jquery 身份证工具类插件
  16. 专访三维空间雷成老师 | 原来水墨画风格的3D建筑动画可以如此惊艳……
  17. python计算正方形边长_计算圆周率,使用点模拟法,如何从以下python代码中看出正方形的边长?...
  18. Java实现 LeetCode 730 统计不同回文子字符串(动态规划)
  19. 华为Mate30 4G电路原理图
  20. 以专业素质和优秀技术能力 瑞星获高端企业级市场青睐

热门文章

  1. 用纯CSS画出蓝天白云(详细版)
  2. Auto.js Pro离线打包源代码加密算法分析
  3. Pr 入门教程:如何添加视觉效果?
  4. 【机器学习】机器学习基本概念术语
  5. 用机器算法预测自杀倾向
  6. 智能生活的风,怎样才能吹进“父母”的心
  7. ASP实现Excel导入Access数据库
  8. C++ 中 冒号 :的作用
  9. 什么样的领导者会把员工用废?
  10. AIDL跨进程通信和Service调用