Android NFC的初次使用——公交卡信息读取
博格巴世界杯 9745 2025-11-06 00:20:26

通过NFC的读模式,读取公交卡的余额和交易记录。这是一个开源的工程,可以读取深圳通、羊城通、北京卡、八达通、武汉通等等。

1.首先要在AndroidManifest.xml中声明如下配置信息:

使用元素允许设备访问NFC硬件:

使用元素设置最小SDK版本,本人基于android 4.4环境,因此声明如下:

备注:API Level 9只通过ACTION_TAG_DISCOVERED来支持有限的标签调度,并且只能通过EXTRA_NDEF_MESSAGES来访问NDEF消息。没有其他的标签属性或I/O操作可用。API Level 10中包含了广泛的读写支持,从而更好的推动了NDEF的应用前景,并且API Leve 14用Android Beam和额外的方便的创建NDEF记录的方法,向外提供了更容易的把NDEF消息推送给其他设备的方法。

下面这项不一定需要,如果你希望你的软件可以在android market中显示有NFC硬件,可以使用元素声明:

2.NFC TAG的发布系统:

当android设备扫描到一个NFC标签时,会自动寻找最适合的Activity来处理这个TAG,如果有多个Activity满足条件的话,会让用户来选择到底使用哪一个Activity来处理,可以理解为就是简单的事件响应与事件处理。

那么如何让一个Activity监听 ”当扫描到NFC标签时” 的这一个事件呢?使用intent filter。

可以理解为当检测到一个NFC标签时,系统自动创建一个相关的Intent对象,含有响应intent filter的Activity将处理这个Intent。

其中,intent filter声明如下:(在AndroidManifest.xml中声明在你需要捕获这个Intent的Activity里)(如下是识别公交卡的TECH格式过滤标签):

android:resource="@xml/nfc_tech_filter" />

在res文件夹下新建一个xml的文件夹,里面放的是Android支持的NFC类型的配置数据。nfc_tech_filter.xml如下:

android.nfc.tech.IsoDep

android.nfc.tech.NfcA

android.nfc.tech.NfcB

android.nfc.tech.NfcF

android.nfc.tech.NfcV

android.nfc.tech.Ndef

android.nfc.tech.NdefFormatable

android.nfc.tech.MifareUltralight

android.nfc.tech.MifareClassic

另外还有:

NDEF格式

TAG格式

有兴趣的同学可以看看Google官方的NFC介绍说明:

https://developer.android.com/guide/topics/connectivity/nfc/nfc.html

到此你所写的activity就能通过刷一下公交卡被调起来了,剩下的是怎么读取卡内信息,读取部分相对麻烦,因为区分了多种模式卡的数据解析,在此不做详细说明,可参照最下方源码下载;

简单来说分四个步骤:

1.select PSF (1PAY.SYS.DDF01)

选择支付系统文件,它的名字是1PAY.SYS.DDF01。

byte[] DFN_PSE = { (byte) '1', (byte) 'P',

(byte) 'A', (byte) 'Y', (byte) '.', (byte) 'S', (byte) 'Y',

(byte) 'S', (byte) '.', (byte) 'D', (byte) 'D', (byte) 'F',

(byte) '0', (byte) '1', };

2.选择公交卡应用的名字或者ID

每个公交卡的名字都会不一样。

深圳通:

byte[] DFN_SRV = { (byte) 'P', (byte) 'A', (byte) 'Y',

(byte) '.', (byte) 'S', (byte) 'Z', (byte) 'T' };

武汉通:

byte[] DFN_SRV = { (byte) 0x41, (byte) 0x50,

(byte) 0x31, (byte) 0x2E, (byte) 0x57, (byte) 0x48, (byte) 0x43,

(byte) 0x54, (byte) 0x43, };

羊城通:

byte[] DFN_SRV = { (byte) 'P', (byte) 'A', (byte) 'Y',

(byte) '.', (byte) 'A', (byte) 'P', (byte) 'P', (byte) 'Y', };

长安通:

byte[] DFN_SRV = { (byte) 0xA0, (byte) 0x00,

(byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x86, (byte) 0x98,

(byte) 0x07, (byte) 0x01, };

北京市政交通卡ID:

byte[] DFI_EP = { (byte) 0x10, (byte) 0x01 };

其他公交卡:

3.读取余额

发送命令读取电子钱包的余额:

final byte[] cmd = { (byte) 0x80, // CLA Class

(byte) 0x5C, // INS Instruction

(byte) 0x00, // P1 Parameter 1

(byte) 0x02, // P2 Parameter 2

(byte) 0x04, // Le

};

获取到的余额数据是byte[] data, 前4字节合并成int,再除以100(两个小数点),得到的结果就是余额。

4.读取交易记录

一次性读取命令,在不知道有多少条记录的时候,用这个命令:

byte[] cmd = { (byte) 0x00, // CLA Class

(byte) 0xB2, // INS Instruction

(byte) 0x01, // P1 Parameter 1

(byte) 0xC5, // P2 Parameter 2

(byte) 0x00, // Le

};

返回所有的记录byte[] data,每23个字节代表一条记录

也可以一条一条的读取:

cmd = { (byte) 0x00, // CLA Class

(byte) 0xB2, // INS Instruction

(byte) index, // P1 Parameter 1

(byte) 0xC4, // P2 Parameter 2

(byte) 0x00, // Le

};

一条记录是23个字节byte[] data,对其解码如下

data[0]-data[1]:index

data[2]-data[4]:over,金额溢出?

data[5]-data[8]:交易金额

data[9]:如果等于0x06或者0x09,表示刷卡;否则是充值

data[10]-data[15]:刷卡机或充值机编号

data[16]-data[22]:日期String.format("%02X%02X.%02X.%02X %02X:%02X:%02X",data[16], data[17], data[18], data[19], data[20], data[21], data[22]);

源码下载地址

http://download.csdn.net/detail/bbenskye/9845382

Copyright © 2022 98世界杯_乌拉圭世界杯 - cy078.com All Rights Reserved.