左晓为主开发手持机充值管理机
zuoxiao
1 天以前 14b15539a8fbbce1145197993e0c062400174ef1
baselibrary/src/main/java/com/dayu/baselibrary/tools/nfc/NativeNfcReadHelper.java
@@ -20,71 +20,131 @@
import java.util.Map;
/**
 * author: zuo
 * Date: 2024-09-25
 * Time: 10:33
 * 备注:原生读写卡方式
 * 原生NFC读卡工具类
 *
 * 功能说明:
 * 1. 使用Android原生NFC API读取Mifare Classic卡片数据
 * 2. 支持读取用户卡信息、管理卡信息、卡号、卡类型等
 * 3. 支持扇区级别的数据读取和验证
 * 4. 提供多种密钥验证方式(KeyA验证)
 * 5. 支持单例模式,确保资源正确管理
 *
 * 使用场景:
 * - 用户卡信息读取
 * - 管理卡信息读取
 * - 卡片类型识别
 * - 卡号获取
 * - 扇区数据读取
 *
 * 注意事项:
 * - 需要确保NFC功能已开启
 * - 读取前需要进行密钥验证
 * - 使用完毕后需要关闭连接,释放资源
 * - 异常情况下要正确处理连接关闭
 *
 * @author zuo
 * @date 2024-09-25
 * @time 10:33
 */
public class NativeNfcReadHelper extends BaseNfcReadHelper {
    /** NFC标签对象,包含卡片的基本信息 */
    private Tag tag;
    //    private NFCCallback callback;
    /** 单例实例 */
    private static NativeNfcReadHelper helper;
    public NativeNfcReadHelper(Intent intent, Activity activity) {
    /**
     * 设置Intent,从中提取NFC标签信息
     *
     * @param intent 包含NFC标签信息的Intent
     */
    @Override
    public void setIntent(Intent intent) {
        this.tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    }
    /**
     * 单例初始化
     *
     * @param intent
     * @return
     * 获取单例实例
     *
     * @param intent   包含NFC标签信息的Intent
     * @param activity 当前Activity实例
     * @return NativeNfcReadHelper实例
     */
    public static NativeNfcReadHelper getInstence(Intent intent, Activity activity) {
        if (helper == null) {
            helper = new NativeNfcReadHelper(intent, activity);
            helper = new NativeNfcReadHelper();
        }
        helper.setIntent(intent);
        return helper;
    }
    /**
     * 获取用户卡信息
     *
     * @return
     * 获取用户卡数据(默认从扇区1读取)
     *
     * @param userCardCard 用户卡数据模板对象,用于解析读取的字节数据
     * @return 解析后的用户卡数据对象,失败返回null
     */
    public BaseUserCardCard getUserCardData(BaseUserCardCard userCardCard) {
        if (userCardCard!=null){
        return getUserCardData(1, userCardCard);
    }
    /**
     * 从指定扇区获取用户卡信息
     *
     * 读取流程:
     * 1. 建立NFC连接
     * 2. 使用密钥验证扇区访问权限
     * 3. 读取扇区内所有块的数据
     * 4. 将字节数据解析为用户卡对象
     * 5. 关闭连接并返回结果
     *
     * @param sectorIndex  要读取的扇区索引(从0开始)
     * @param userCardCard 用户卡数据模板对象
     * @return 解析后的用户卡数据对象,失败返回null
     */
    @Override
    public BaseUserCardCard getUserCardData(int sectorIndex, BaseUserCardCard userCardCard) {
        if (userCardCard != null) {
            BaseUserCardCard userCard = null;
            Map<String, List<byte[]>> map = new HashMap<>();
            MifareClassic mfc = MifareClassic.get(tag);
            if (null != mfc) {
                try {
                    //链接NFC
                    // 建立NFC连接
                    mfc.connect();
                    //获取扇区数量
                    int count = mfc.getSectorCount();
                    //存储空间
                    int size = mfc.getSize();
                    //用于判断时候有内容读取出来
                    // 用于判断是否有内容读取出来
                    boolean flag = false;
                    List<byte[]> list = new ArrayList<>();
                    //验证扇区密码,否则会报错(链接失败错误)
                    // 验证扇区密码,否则会报错(连接失败错误)
                    boolean isOpen = false;
                    for (int i = 0; i < listKeyA.size(); i++) {
                        if (mfc.authenticateSectorWithKeyA(1, listKeyA.get(i))) {
                    if (!listKeyA.isEmpty()) {
                        // 遍历所有可用的KeyA密钥进行验证
                        for (int i = 0; i < listKeyA.size(); i++) {
                            if (mfc.authenticateSectorWithKeyA(sectorIndex, listKeyA.get(i))) {
                                isOpen = true;
                                break;
                            }
                        }
                    } else if (!listA_PS.isEmpty()) {
                        // 使用默认密钥或特定扇区密钥进行验证
                        if (mfc.authenticateSectorWithKeyA(sectorIndex, defauleKey)) {
                            isOpen = true;
                            break;
                        } else if (mfc.authenticateSectorWithKeyA(sectorIndex, listA_PS.get(sectorIndex))) {
                            isOpen = true;
                        }
                    }
                    if (isOpen) {
                        //获取扇区里面块的数量
                        int bCount = mfc.getBlockCountInSector(1);
                        //获取扇区第一个块对应芯片存储器的位置(我是这样理解的,因为第0扇区的这个值是4而不是0)
                        int bIndex = mfc.sectorToBlock(1);
                        //String data1 = "";
                        // 获取扇区里面块的数量
                        int bCount = mfc.getBlockCountInSector(sectorIndex);
                        // 获取扇区第一个块对应芯片存储器的位置
                        int bIndex = mfc.sectorToBlock(sectorIndex);
                        // 读取扇区内所有块的数据
                        for (int j = 0; j < bCount; j++) {
                            //读取数据
                            byte[] data = null;
                            try {
                                data = mfc.readBlock(bIndex);
@@ -98,6 +158,7 @@
                    }
                    if (flag) {
                        // 将读取的字节数据解析为用户卡对象
                        userCard = userCardCard.getBean(list);
                        return userCard;
                    }
@@ -106,6 +167,7 @@
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    // 确保连接被正确关闭,释放资源
                    try {
                        mfc.close();
                    } catch (Exception e) {
@@ -117,34 +179,45 @@
        return null;
    }
    /**
     * 获取卡片类型
     *
     * 读取扇区1第一个块的第一个字节作为卡片类型标识
     *
     * @return 卡片类型的十六进制字符串,失败返回错误码
     */
    @Override
    public String getCradType() {
        MifareClassic mfc = MifareClassic.get(tag);
        if (null != mfc) {
            try {
                mfc.connect();
                boolean isOpen = false;
                // 使用KeyA密钥验证扇区1的访问权限
                for (int i = 0; i < listKeyA.size(); i++) {
                    if (mfc.authenticateSectorWithKeyA(1, listKeyA.get(i))) {
                        isOpen = true;
                        break;
                    }
                }
                if (isOpen) {
                    // 读取扇区1第一个块的数据
                    int bIndex = mfc.sectorToBlock(1);
                    byte[] data = mfc.readBlock(bIndex + 0);
                    if (data != null && data.length > 0) {
                        // 将第一个字节转换为十六进制字符串作为卡片类型
                        String hex = HexUtil.byteToHex(data[0]);
                        Log.i("NFCWreatActivity", "hex===" + hex);
                        return hex;
                    }
                } else {
                    Log.i("NFCWreatActivity", "isOpen===" + isOpen);
                    return BaseCommon.CARD_TYPE_ERROR2;
                    return BaseCommon.CARD_TYPE_ERROR2; // 密钥验证失败
                }
            } catch (IOException e) {
                return BaseCommon.CARD_TYPE_ERROR1;
                return BaseCommon.CARD_TYPE_ERROR1; // IO异常
            } finally {
                try {
                    mfc.close();
@@ -158,25 +231,30 @@
    /**
     * 读取NFC卡的全部信息
     *
     * @param callback
     *
     * 遍历所有扇区,读取每个扇区的所有块数据
     *
     * @param callback 数据读取完成后的回调接口
     */
    @Override
    public void getAllData(final NFCCallMapback callback) {
        Map<String, List<byte[]>> map = new HashMap<>();
        MifareClassic mfc = MifareClassic.get(tag);
        if (null != mfc) {
            try {
                //链接NFC
                // 建立NFC连接
                mfc.connect();
                //获取扇区数量
                // 获取扇区数量
                int count = mfc.getSectorCount();
                //存储空间
                // 存储空间大小
                int size = mfc.getSize();
                //用于判断时候有内容读取出来
                // 用于判断是否有内容读取出来
                boolean flag = false;
                // 遍历所有扇区
                for (int i = 0; i < count; i++) {
                    List<byte[]> list = new ArrayList<>();
                    //验证扇区密码,否则会报错(链接失败错误)
                    // 验证扇区密码
                    boolean isOpen = false;
                    for (int j = 0; j < listKeyA.size(); j++) {
                        if (mfc.authenticateSectorWithKeyA(i, listKeyA.get(i))) {
@@ -184,14 +262,15 @@
                            break;
                        }
                    }
                    if (isOpen) {
                        //获取扇区里面块的数量
                        // 获取扇区里面块的数量
                        int bCount = mfc.getBlockCountInSector(i);
                        //获取扇区第一个块对应芯片存储器的位置(我是这样理解的,因为第0扇区的这个值是4而不是0)
                        // 获取扇区第一个块对应芯片存储器的位置
                        int bIndex = mfc.sectorToBlock(i);
                        //String data1 = "";
                        // 读取扇区内所有块的数据
                        for (int j = 0; j < bCount; j++) {
                            //读取数据
                            byte[] data = null;
                            try {
                                data = mfc.readBlock(bIndex);
@@ -205,6 +284,7 @@
                    }
                    map.put(i + "", list);
                }
                if (flag) {
                    callback.callBack(map);
                } else {
@@ -226,29 +306,31 @@
        }
    }
    /**
     * 获取1扇区信息
     *
     * @param callback
     * 获取扇区1的信息
     *
     * 专门用于读取扇区1的所有块数据,通常用于读取用户卡信息
     *
     * @param callback 数据读取完成后的回调接口
     */
    @Override
    public void getOneSectorData(NFCCallListback callback) {
        MifareClassic mfc = null;
        try {
            mfc = MifareClassic.get(tag);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (null != mfc) {
            try {
                //链接NFC
                // 建立NFC连接
                mfc.connect();
                //用于判断时候有内容读取出来
                // 用于判断是否有内容读取出来
                boolean flag = false;
                List<byte[]> list = new ArrayList<>();
                //验证扇区密码,否则会报错(链接失败错误)
                // 验证扇区1的密码
                boolean isOpen = false;
                for (int i = 0; i < listKeyA.size(); i++) {
                    if (mfc.authenticateSectorWithKeyA(1, listKeyA.get(i))) {
@@ -256,14 +338,15 @@
                        break;
                    }
                }
                if (isOpen) {
                    //获取扇区里面块的数量
                    // 获取扇区1里面块的数量
                    int bCount = mfc.getBlockCountInSector(1);
                    //获取扇区第一个块对应芯片存储器的位置(我是这样理解的,因为第0扇区的这个值是4而不是0)
                    // 获取扇区1第一个块对应芯片存储器的位置
                    int bIndex = mfc.sectorToBlock(1);
                    //String data1 = "";
                    // 读取扇区1内所有块的数据
                    for (int j = 0; j < bCount; j++) {
                        //读取数据
                        byte[] data = null;
                        try {
                            data = mfc.readBlock(bIndex);
@@ -275,6 +358,7 @@
                    }
                    flag = true;
                }
                if (flag) {
                    callback.callBack(list);
                } else {
@@ -287,7 +371,6 @@
                callback.error(CardCommonState.ERROR);
                e.printStackTrace();
            } finally {
                try {
                    mfc.close();
                } catch (Exception e) {
@@ -297,14 +380,14 @@
        }
    }
    /**
     * 读取NFC卡的特定扇区信息
     *
     * @param a        扇区
     * @param b        块
     * @param callback
     * 读取NFC卡的特定扇区特定块信息
     *
     * @param a        扇区索引(从0开始)
     * @param b        块索引(从0开始,相对于扇区内的块)
     * @param callback 数据读取完成后的回调接口
     */
    @Override
    public void getData(final int a, final int b, final NFCCallByteback callback) {
        new Thread(new Runnable() {
            @Override
@@ -315,17 +398,22 @@
                    try {
                        mfc.connect();
                        int count = mfc.getSectorCount();
                        // 验证扇区索引是否有效
                        if (a < 0 || a > count - 1) {
                            callback.error(CardCommonState.ERROR);
                            return;
                        }
                        int bCount = mfc.getBlockCountInSector(a);
                        // 验证块索引是否有效
                        if (b < 0 || b > bCount - 1) {
                            callback.error(CardCommonState.ERROR);
                            return;
                        }
                        int type = mfc.getType();//获取TAG的类型
                        // 获取TAG的类型(用于调试)
                        int type = mfc.getType();
                        String typeS = "";
                        switch (type) {
                            case MifareClassic.TYPE_CLASSIC:
@@ -341,6 +429,8 @@
                                typeS = "TYPE_UNKNOWN";
                                break;
                        }
                        // 验证扇区密码
                        boolean isOpen = false;
                        for (int i = 0; i < listKeyA.size(); i++) {
                            if (mfc.authenticateSectorWithKeyA(a, listKeyA.get(i))) {
@@ -348,7 +438,9 @@
                                break;
                            }
                        }
                        if (isOpen) {
                            // 读取指定扇区指定块的数据
                            int bIndex = mfc.sectorToBlock(a);
                            byte[] data = mfc.readBlock(bIndex + b);
                            callback.callBack(data);
@@ -372,38 +464,63 @@
        }).start();
    }
    /**
     * 获取卡号(读取后自动关闭连接)
     *
     * 从扇区0第一个块读取卡的UID作为卡号
     *
     * @return 卡号的十六进制字符串(大写),失败返回错误码或空字符串
     */
    @Override
    public String getCardNumber() {
        if (tag == null) {
            return "";
        }
        MifareClassic mfc = MifareClassic.get(tag);
        if (null != mfc) {
            try {
                mfc.connect();
                //获取当前卡号
                // 获取当前卡号
                boolean isOpen = false;
                for (int i = 0; i < listKeyA.size(); i++) {
                    if (mfc.authenticateSectorWithKeyA(0, listKeyA.get(i))) {
                        isOpen = true;
                        break;
                if (!listKeyA.isEmpty()) {
                    // 使用KeyA密钥验证扇区0
                    for (int i = 0; i < listKeyA.size(); i++) {
                        if (mfc.authenticateSectorWithKeyA(0, listKeyA.get(i))) {
                            isOpen = true;
                            break;
                        }
                    }
                }
                if (isOpen) {
                    int bIndex = mfc.sectorToBlock(0);
                    byte[] data = mfc.readBlock(bIndex + 0);
                    if (data != null && data.length > 0) {
                        String hex = HexUtil.bytesToHex(Arrays.copyOfRange(data, 0, 4));
                        hex = HexUtil.spaceHex(hex);
                        hex = HexUtil.HighLowHex(hex);
                        Log.i("NFCWreatActivity", "hex===" + hex);
                        return hex.toUpperCase();
                } else if (!listA_PS.isEmpty()) {
                    // 使用默认密钥或特定密钥验证扇区0
                    if (mfc.authenticateSectorWithKeyA(0, defauleKey)) {
                        isOpen = true;
                    } else if (mfc.authenticateSectorWithKeyA(0, listA_PS.get(0))) {
                        isOpen = true;
                    }
                }
                if (isOpen) {
                    // 读取扇区0第一个块的数据
                    int bIndex = mfc.sectorToBlock(0);
                    byte[] data = mfc.readBlock(bIndex + 0);
                    if (data != null && data.length > 0) {
                        // 提取前4个字节作为UID
                        String hex = HexUtil.bytesToHex(Arrays.copyOfRange(data, 0, 4));
                        hex = HexUtil.spaceHex(hex); // 添加空格分隔
                        hex = HexUtil.HighLowHex(hex); // 高低位转换
                        Log.i("NFCWreatActivity", "hex===" + hex);
                        return hex.toUpperCase();
                    }
                } else {
                    return BaseCommon.CARD_TYPE_ERROR2; // 密钥验证失败
                }
            } catch (IOException e) {
                return BaseCommon.CARD_TYPE_ERROR1;
                return BaseCommon.CARD_TYPE_ERROR1; // IO异常
            } finally {
                try {
                    mfc.close();
                    mfc.close(); // 确保关闭连接
                } catch (IOException e) {
                    e.printStackTrace();
                }
@@ -413,63 +530,178 @@
    }
    /**
     * 获取卡片类型和卡号
     *
     * @return
     * 获取卡号(不关闭连接)
     *
     * 与getCardNumber()功能相同,但不关闭NFC连接
     * 适用于需要连续进行多次NFC操作的场景
     *
     * @return 卡号的十六进制字符串(大写),失败返回错误码或空字符串
     */
    @Override
    public String getCradTypeAndCardNumber() {
    public String getCardNumberNoClose() {
        if (tag == null) {
            return "";
        }
        MifareClassic mfc = MifareClassic.get(tag);
        if (null != mfc) {
            try {
                mfc.connect();
                StringBuilder strData = new StringBuilder();
                //获取当前卡号
                // 获取当前卡号
                boolean isOpen = false;
                for (int i = 0; i < listKeyA.size(); i++) {
                    if (mfc.authenticateSectorWithKeyA(0, listKeyA.get(i))) {
                if (!listKeyA.isEmpty()) {
                    // 使用KeyA密钥验证扇区0
                    for (int i = 0; i < listKeyA.size(); i++) {
                        if (mfc.authenticateSectorWithKeyA(0, listKeyA.get(i))) {
                            isOpen = true;
                            break;
                        }
                    }
                } else if (!listA_PS.isEmpty()) {
                    // 使用默认密钥或特定密钥验证扇区0
                    if (mfc.authenticateSectorWithKeyA(0, defauleKey)) {
                        isOpen = true;
                        break;
                    } else if (mfc.authenticateSectorWithKeyA(0, listA_PS.get(0))) {
                        isOpen = true;
                    }
                }
                if (isOpen) {
                    // 读取扇区0第一个块的数据
                    int bIndex = mfc.sectorToBlock(0);
                    byte[] data = mfc.readBlock(bIndex + 0);
                    if (data != null && data.length > 0) {
                        // 提取前4个字节作为UID
                        String hex = HexUtil.bytesToHex(Arrays.copyOfRange(data, 0, 4));
                        hex = HexUtil.spaceHex(hex); // 添加空格分隔
                        hex = HexUtil.HighLowHex(hex); // 高低位转换
                        Log.i("NFCWreatActivity", "hex===" + hex);
                        return hex.toUpperCase();
                    }
                } else {
                    return BaseCommon.CARD_TYPE_ERROR2; // 密钥验证失败
                }
            } catch (IOException e) {
                Log.i("NFCWreatActivity", e.toString());
                return BaseCommon.CARD_TYPE_ERROR1; // IO异常
            }
            // 注意:这里不关闭连接
        }
        return "";
    }
    /**
     * 获取卡片类型和卡号(默认参数)
     *
     * @return "卡号,卡片类型"格式的字符串
     */
    @Override
    public String getCradTypeAndCardNumber() {
        return getCradTypeAndCardNumber(1, 0, 0);
    }
    /**
     * 获取卡片类型和卡号(自动关闭连接)
     *
     * @param sectorIndex   读取卡片类型的扇区索引
     * @param blockIndex    读取卡片类型的块索引
     * @param cardTypeIndex 卡片类型字节在块中的位置索引
     * @return "卡号,卡片类型"格式的字符串
     */
    public String getCradTypeAndCardNumber(int sectorIndex, int blockIndex, int cardTypeIndex) {
        return getCradTypeAndCardNumber(sectorIndex, blockIndex, cardTypeIndex, true);
    }
    /**
     * 获取卡片类型和卡号
     *
     * 读取流程:
     * 1. 从扇区0读取卡号
     * 2. 从指定扇区读取卡片类型
     * 3. 返回"卡号,卡片类型"格式的字符串
     *
     * @param sectorIndex   读取卡片类型的扇区索引
     * @param blockIndex    读取卡片类型的块索引
     * @param cardTypeIndex 卡片类型字节在块中的位置索引
     * @param isClose       是否在读取完成后关闭连接
     * @return "卡号,卡片类型"格式的字符串,失败返回错误码
     */
    public String getCradTypeAndCardNumber(int sectorIndex, int blockIndex, int cardTypeIndex, boolean isClose) {
        MifareClassic mfc = MifareClassic.get(tag);
        if (null != mfc) {
            try {
                mfc.connect();
                StringBuilder strData = new StringBuilder();
                // 第一步:获取当前卡号(从扇区0读取)
                boolean isOpen = false;
                if (!listKeyA.isEmpty()) {
                    for (int i = 0; i < listKeyA.size(); i++) {
                        if (mfc.authenticateSectorWithKeyA(0, listKeyA.get(i))) {
                            isOpen = true;
                            break;
                        }
                    }
                } else if (!listA_PS.isEmpty()) {
                    if (mfc.authenticateSectorWithKeyA(0, listA_PS.get(0))) {
                        isOpen = true;
                    } else if (mfc.authenticateSectorWithKeyA(0, defauleKey)) {
                        isOpen = true;
                    }
                }
                if (isOpen) {
                    int bIndex = mfc.sectorToBlock(0);
                    byte[] data = mfc.readBlock(bIndex + 0);
                    if (data != null && data.length > 0) {
                        // 提取卡号并格式化
                        String hex = HexUtil.bytesToHex(Arrays.copyOfRange(data, 0, 4));
                        hex = HexUtil.spaceHex(hex);
                        hex = HexUtil.HighLowHex(hex);
                        strData.append(hex);
                        strData.append(",");
                        strData.append(","); // 分隔符
                        Log.i("NFCWreatActivity", "hex===" + hex);
                    }
                }
                //获取卡片类型
                for (int i = 0; i < listKeyA.size(); i++) {
                    if (mfc.authenticateSectorWithKeyA(1, listKeyA.get(i))) {
                // 第二步:获取卡片类型(从指定扇区读取)
                if (!listKeyA.isEmpty()) {
                    for (int i = 0; i < listKeyA.size(); i++) {
                        if (mfc.authenticateSectorWithKeyA(sectorIndex, listKeyA.get(i))) {
                            isOpen = true;
                            break;
                        }
                    }
                } else if (!listA_PS.isEmpty()) {
                    if (mfc.authenticateSectorWithKeyA(sectorIndex, listA_PS.get(sectorIndex))) {
                        isOpen = true;
                        break;
                    } else if (mfc.authenticateSectorWithKeyA(sectorIndex, defauleKey)) {
                        isOpen = true;
                    }
                }
                if (isOpen) {
                    int bIndex = mfc.sectorToBlock(1);
                    int bIndex = mfc.sectorToBlock(sectorIndex);
                    byte[] data = mfc.readBlock(bIndex + 0);
                    if (data != null && data.length > 0) {
                        String hex = HexUtil.byteToHex(data[0]);
                        // 提取指定位置的字节作为卡片类型
                        String hex = HexUtil.byteToHex(data[cardTypeIndex]);
                        strData.append(hex);
                        Log.i("NFCWreatActivity", "hex===" + hex);
                        return strData.toString().toUpperCase();
                    }
                } else {
                    Log.i("NFCWreatActivity", "isOpen===" + isOpen);
                    return BaseCommon.CARD_TYPE_ERROR2;
                    return BaseCommon.CARD_TYPE_ERROR2; // 密钥验证失败
                }
            } catch (IOException e) {
                return BaseCommon.CARD_TYPE_ERROR1;
                e.printStackTrace();
                return BaseCommon.CARD_TYPE_ERROR1; // IO异常
            } finally {
                try {
                    mfc.close();
                    if (isClose) {
                        mfc.close(); // 根据参数决定是否关闭连接
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
@@ -478,7 +710,11 @@
        return "";
    }
    /**
     * 获取扇区1的数据(返回字节数组列表)
     *
     * @return 扇区1所有块的字节数据列表,失败返回null
     */
    @Override
    public List<byte[]> getOnesectorData() {
        MifareClassic mfc = null;
@@ -487,15 +723,16 @@
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<byte[]> list = new ArrayList<>();
        if (null != mfc) {
            try {
                //链接NFC
                // 建立NFC连接
                mfc.connect();
                //用于判断时候有内容读取出来
                // 用于判断是否有内容读取出来
                boolean flag = false;
                //验证扇区密码,否则会报错(链接失败错误)
                // 验证扇区1的密码
                boolean isOpen = false;
                for (int i = 0; i < listKeyA.size(); i++) {
                    if (mfc.authenticateSectorWithKeyA(1, listKeyA.get(i))) {
@@ -503,14 +740,15 @@
                        break;
                    }
                }
                if (isOpen) {
                    //获取扇区里面块的数量
                    // 获取扇区1里面块的数量
                    int bCount = mfc.getBlockCountInSector(1);
                    //获取扇区第一个块对应芯片存储器的位置(我是这样理解的,因为第0扇区的这个值是4而不是0)
                    // 获取扇区1第一个块对应芯片存储器的位置
                    int bIndex = mfc.sectorToBlock(1);
                    //String data1 = "";
                    // 读取扇区1内所有块的数据
                    for (int j = 0; j < bCount; j++) {
                        //读取数据
                        byte[] data = null;
                        try {
                            data = mfc.readBlock(bIndex);
@@ -529,7 +767,7 @@
            } finally {
                try {
                    mfc.close();
                    return list;
                    return list; // 在finally中返回结果
                } catch (Exception e) {
                    e.printStackTrace();
                }
@@ -539,39 +777,44 @@
    }
    /**
     * 获取用户卡信息
     *
     * @return
     * 获取管理卡转用户卡的数据
     *
     * 用于读取管理卡中存储的用户卡信息,通常用于管理卡向用户卡的数据转换
     *
     * @param baseManagerToUserCard 管理卡数据模板对象
     * @return 解析后的管理卡数据对象,失败返回null
     */
    @Override
    public BaseManagerToUserCard getManagerToUserCardData(BaseManagerToUserCard baseManagerToUserCard) {
        BaseManagerToUserCard managerToUserCard = null;
        Map<String, List<byte[]>> map = new HashMap<>();
        MifareClassic mfc = MifareClassic.get(tag);
        if (null != mfc) {
            try {
                //链接NFC
                // 建立NFC连接
                mfc.connect();
                //获取扇区数量
                // 获取扇区数量
                int count = mfc.getSectorCount();
                //存储空间
                // 存储空间大小
                int size = mfc.getSize();
                //用于判断时候有内容读取出来
                // 用于判断是否有内容读取出来
                boolean flag = false;
                List<byte[]> list = new ArrayList<>();
                //验证扇区密码,否则会报错(链接失败错误)
                // 验证扇区1的密码(先尝试默认密钥,再尝试公司密钥)
                boolean isOpen = mfc.authenticateSectorWithKeyA(1, defauleKey);
                if (!isOpen) {
                    isOpen = mfc.authenticateSectorWithKeyA(1, companyKey);
                }
                if (isOpen) {
                    //获取扇区里面块的数量
                    // 获取扇区1里面块的数量
                    int bCount = mfc.getBlockCountInSector(1);
                    //获取扇区第一个块对应芯片存储器的位置(我是这样理解的,因为第0扇区的这个值是4而不是0)
                    // 获取扇区1第一个块对应芯片存储器的位置
                    int bIndex = mfc.sectorToBlock(1);
                    //String data1 = "";
                    // 读取扇区1内所有块的数据
                    for (int j = 0; j < bCount; j++) {
                        //读取数据
                        byte[] data = null;
                        try {
                            data = mfc.readBlock(bIndex);
@@ -585,6 +828,7 @@
                }
                if (flag) {
                    // 将读取的字节数据解析为管理卡对象
                    managerToUserCard = baseManagerToUserCard.getBean(list);
                    return managerToUserCard;
                }
@@ -594,7 +838,7 @@
                e.printStackTrace();
            } finally {
                try {
                    mfc.close();
                    mfc.close(); // 确保连接被正确关闭
                } catch (Exception e) {
                    e.printStackTrace();
                }