使用android (android studio)和苹果ios手机读写NFC卡内容(MifareUltralight)方法 亲身完美体验过程

最近工作需要购买了一些nfc卡进行读写操作,目标是使用手机实现一些业务流程

淘宝购买1-2块钱一张卡,卖家提供的信息:卡的芯片是215

网上找的内容都是一段一段的,我现在把用到的资料都整合起来,以便看一篇就可以知道怎么操作。

安卓支持NFC手机,都比较容易的使用,比较舒服

苹果手机有点特别,限制比较多,没有安卓那么开放,NFC卡使用说明如下:

苹果手机读取,需要iphone7+  ios12以上,才有nfc功能,读取时不能直接读取卡序列号,需要用安卓手机安装NFC TagWriter by NXP_v4.8.2_apkpure.com.apk (Google play可以下载)进行写卡后,苹果才可以读取写入的内容

一、该卡属于MifareUltralight格式规范,规范如下:

https://blog.csdn.net/wxh0000mm/article/details/79708807?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

这里有两个地方特别独家补充一下的,网上的网文都没有说明清楚,看得到有点晕

1、是卡的序列号使用16进制读取

2、page2中lock使用二进制来标记(再转16进制)设置

存储结构:

页号

Byte0

Byte1

Byte2

Byte3

说明

0

SN0

SN1

SN2

BCC0

只读,存放卡的序列号:Page0前3字节+整个Page1

这里是16进制读取(注意读取方式,其它网文都没有标明)

1

SN3

SN4

SN5

SN6

2

BCC1

保留

LOCK0

LOCK1

只读,通过设置LOCK0和LOCK1可以讲16个page设为只读

二进制方式设置(注意读取方式,其它网文都没有标明)

3

OTP0

OTP1

OTP2

OTP3

可读写,一次性交易计数器,不可逆

4

Data0

Data1

Data2

Data3

可读写,数据存放区域

5

Data0

Data1

Data2

Data3

6

Data0

Data1

Data2

Data3

7

Data0

Data1

Data2

Data3

8

Data0

Data1

Data2

Data3

9

Data0

Data1

Data2

Data3

10

Data0

Data1

Data2

Data3

11

Data0

Data1

Data2

Data3

12

Data0

Data1

Data2

Data3

13

Data0

Data1

Data2

Data3

14

Data0

Data1

Data2

Data3

15

Data0

Data1

Data2

Data3

 

 Page2的第3和第4个字节用于将存储区锁定为只读,如下图示,L4-L15的某一位设置为1,则对应序号的Page内容锁定为只读,每一个Page都可以单独设置。Lotp用于锁定Page3为只读。Lotp-L15可以锁定别人,这些位本身又被三个BL位锁定,BL15-10用于锁定L15-L10,BL9-4用于锁定L9-L4,BLotp用于锁定Lotp。所有的这16个锁定位也具有OTP特性,通俗的讲就是这些“锁”没有“钥匙”,一旦锁死就改不回来,所以锁定时一定要小心。

 

如lock1对应8位二进制11110000,1代表锁定只读,然后把二进制转换成16进制写入卡

二进制方式设置(注意读取方式,其它网文都没有标明)

二、读写方法网上有比较多,写法如下:

https://www.cnblogs.com/sjjg/p/4783743.html

亲测有效,我的测试源代码下载地址:https://download.csdn.net/download/qq_16005627/12366636

通过以上读写方法扩展

1、 读取卡序列号方法

public String readTagc(Tag tag) throws Exception {
    //读数据 第1步,从nfc标签中得到MifareUltralight
    MifareUltralight ultralight = MifareUltralight.get(tag);

    try {
        //读数据 第2步,接连
        ultralight.connect();
        //读数据 第3步,从ultralight数据中的下标为4的位开始读数据.
        byte[] data = ultralight.readPages(0);
        byte[] serialNumber = new byte[7];
        serialNumber[0] = data[0];
        serialNumber[1] = data[1];
        serialNumber[2] = data[2];
        serialNumber[3] = data[4];
        serialNumber[4] = data[5];
        serialNumber[5] = data[6];
        serialNumber[6] = data[7];
        String CardCode = bytes2HexString(serialNumber);       
        return CardCode ;
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            ultralight.close();
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }
    return null;
}

//16进制转字符串

private static String bytes2HexString(final byte[] bytes) {
    if (bytes == null) return "";
    int len = bytes.length;
    if (len <= 0) return "";
    char[] ret = new char[len << 1];
    for (int i = 0, j = 0; i < len; i++) {
        ret[j++] = HEX_DIGITS[bytes[i] >> 4 & 0x0f];
        ret[j++] = HEX_DIGITS[bytes[i] & 0x0f];
    }
    return new String(ret);
}

private static final char[] HEX_DIGITS =
        {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

二、设置page2中lock

ultralight.writePage(2, hexString2Bytes("DF48f000"));//第2页 LOCK设置     11110000二进制转16进制

//16进制转字节

public static byte[] hexString2Bytes(String src) 
    int l = src.length() / 2;
    byte[] ret = new byte[l];
    for (int i = 0; i < l; i++) {
        ret[i] = (byte) Integer
                .valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
    }
    return ret;
}

觉得好的同学,记得点个赞!

猜你喜欢

转载自blog.csdn.net/qq_16005627/article/details/105786523
今日推荐