左晓为主开发手持机充值管理机
zuoxiao
7 天以前 c3edd4a3122b711bc6a0bfef56b6ff6bf5ae03e2
baselibrary/src/main/java/com/dayu/baselibrary/tools/nfc/NativeNfcWriteHelper.java
@@ -9,8 +9,10 @@
import com.dayu.baselibrary.bean.BaseUserCardCard;
import com.dayu.baselibrary.tools.HexUtil;
import com.tencent.bugly.crashreport.CrashReport;
import java.io.IOException;
import java.util.List;
/**
 * author: zuo
@@ -23,7 +25,8 @@
    private static NativeNfcWriteHelper helper;
    public NativeNfcWriteHelper(Intent intent, Activity activity) {
    public void setIntent(Intent intent) {
        this.tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    }
@@ -35,8 +38,9 @@
     */
    public static NativeNfcWriteHelper getInstence(Intent intent, Activity activity) {
        if (helper == null) {
            helper = new NativeNfcWriteHelper(intent, activity);
            helper = new NativeNfcWriteHelper();
        }
        helper.setIntent(intent);
        return helper;
    }
@@ -47,9 +51,10 @@
     * @param userCard 用户卡内容
     * @param
     */
    public boolean writeUserData(BaseUserCardCard userCard) {
    @Override
    public boolean writeUserData(BaseUserCardCard userCard, int sector) {
        if (userCard != null) {
            int a = 1;
            int a = sector;
            try {
                MifareClassic mfc = MifareClassic.get(tag);
                if (null != mfc) {
@@ -113,48 +118,110 @@
     * @param b   书写的块(从0开始数)
     * @param
     */
    @Override
    public boolean writeData(byte[] str, int a, int b) {
        return writeData(str, a, b, null);
    }
    @Override
    public boolean writeData(byte[] str, int a, int b, NFCCallBack callBack) {
        return writeData(str, a, b, true, null);
    }
    @Override
    public boolean writeData(byte[] str, int a, int b, boolean isConnect, NFCCallBack callBack) {
        Log.i("NFCWreatActivity", "writeData: a=" + a + " b=" + b);
        if (str.length <= 16) {
        if (str.length == 16) {
            try {
                MifareClassic mfc = MifareClassic.get(tag);
                if (null != mfc) {
                    try {
                        //连接NFC
                        mfc.connect();
                        if (isConnect) {
                            mfc.connect();
                        }
                        //获取扇区数量
                        int count = mfc.getSectorCount();
                        //如果传进来的扇区大了或者小了直接退出方法
                        if (a > count - 1 || a < 0) {
                            if (callBack != null) {
                                callBack.isSusses(false, "扇区错误--" + a);
                            }
                            return false;
                        }
                        //获取写的扇区的块的数量
                        int bCount = mfc.getBlockCountInSector(a);
                        //如果输入的块大了或者小了也是直接退出
                        if (b > bCount - 1 || b < 0) {
                            if (callBack != null) {
                                callBack.isSusses(false, "块区错误--" + b);
                            }
                            return false;
                        }
                        //验证扇区密码
                        boolean isOpen = false;
                        for (int i = 0; i < listKeyA.size(); i++) {
                            if (mfc.authenticateSectorWithKeyA(0, listKeyA.get(i))) {
                                isOpen = true;
                                if (listKeyA.get(i).equals(defauleKey)) {
                                    //当前为默认白卡密码时写卡时修改密码
                                    changePasword(a, mfc);
                        if (listKeyA.size() != 0) {
                            for (int i = 0; i < listKeyA.size(); i++) {
                                if (mfc.authenticateSectorWithKeyA(0, listKeyA.get(i))) {
                                    isOpen = true;
                                    if (listKeyA.get(i).equals(defauleKey)) {
                                        //当前为默认白卡密码时写卡时修改密码
                                        changePasword(a, mfc);
                                    }
                                    break;
                                }
                                break;
                            }
                        } else if (listA_PS.size() != 0 && listA_PS.size() > a) {
                            if (mfc.authenticateSectorWithKeyA(a, defauleKey)) {
                                isOpen = true;
                            } else if (mfc.authenticateSectorWithKeyA(a, listA_PS.get(a))) {
                                isOpen = true;
                            }
                        }
                        if (isOpen) {
                            int bIndex = mfc.sectorToBlock(a);
                            //写卡
                            mfc.writeBlock(bIndex + b, str);
                            return true;
                            // 校验写入数据是否正确
                            boolean isVerified = true;
                            // 读取数据验证
                            byte[] readResult = mfc.readBlock(bIndex + b);
                            if (readResult == null) {
                                if (callBack != null) {
                                    callBack.isSusses(false, a + "扇区写卡时再次读取验证时失败");
                                }
                                return false;
                            }
                            for (int i = 0; i < str.length; i++) {
                                if (str[i] != readResult[i]) {
                                    isVerified = false;
                                    break;
                                }
                            }
                            if (isVerified) {
                                if (callBack != null) {
                                    callBack.isSusses(true, "写入成功并验证通过");
                                }
                                return true;
                            } else {
                                if (callBack != null) {
                                    callBack.isSusses(false, "写入验证失败");
                                }
                                return false;
                            }
                        }
                        if (callBack != null) {
                            callBack.isSusses(false, a + "扇区密码错误");
                        }
                        return false;
                    } catch (Exception e) {
                        e.printStackTrace();
                        if (callBack != null) {
                            callBack.isSusses(false, a + "扇区写卡报错" + e.getMessage());
                        }
                        return false;
                    } finally {
                        try {
@@ -166,7 +233,14 @@
                }
            } catch (Exception e) {
                e.printStackTrace();
                if (callBack != null) {
                    callBack.isSusses(false, a + "扇区写卡报错" + e.getMessage());
                }
                return false;
            }
        } else {
            if (callBack != null) {
                callBack.isSusses(false, a + "扇区写卡报错,byte数组大小不为16");
            }
        }
        return false;
@@ -176,15 +250,123 @@
    /**
     * 修改密码
     *
     * @param a 书写的扇区
     *          //     * @param callback 返回监听
     * @param         书写的扇区
     * @param passWord 密码
     * @return
     */
    public boolean changePasword(int a, MifareClassic mfc) {
    public boolean changePasword( List<byte[]> passWord, boolean isConnect, boolean isClose, NFCCallBack callBack) {
        if (passWord == null || passWord.size()!=16) {
            if (callBack != null) {
                callBack.isSusses(false, "密码数组为空或长度不为16");
            }
            return false;
        }
        try {
            MifareClassic mfc = MifareClassic.get(tag);
            if (mfc == null) {
                if (callBack != null) {
                    callBack.isSusses(false, "获取MifareClassic实例失败");
                }
                return false;
            }
            try {
                // 连接NFC
                if (isConnect) {
                    mfc.connect();
                }
                for (int i = 0; i < passWord.size(); i++) {
                    byte [] passWordItem = passWord.get(i);
                    // 验证扇区密码
                    boolean isAuthenticated = false;
                    // 尝试使用默认密钥验证
                    if (mfc.authenticateSectorWithKeyA(i, defauleKey)) {
                        isAuthenticated = true;
                    } else if (mfc.authenticateSectorWithKeyA(i, listA_PS.get(i))) {
                        continue;
                    }
                    if (!isAuthenticated) {
                        if (callBack != null) {
                            callBack.isSusses(false, "扇区" + i + "密码验证失败");
                        }
                        return false;
                    }
                    // 准备数据
                    byte[] data = new byte[16];
                    if (passWordItem.length == 16) {
                        // 如果是完整的16字节数据,直接使用
                        System.arraycopy(passWordItem, 0, data, 0, 16);
                    } else if (passWordItem.length == 6) {
                        // 如果只是6字节密钥,构建完整的控制块
                        // 将密码转换为keyA
                        System.arraycopy(passWordItem, 0, data, 0, 6);
                        // 输入控制位
                        data[6] = (byte) 0xFF;
                        data[7] = (byte) 0x07;
                        data[8] = (byte) 0x80;
                        data[9] = (byte) 0x69;
                        // 将密码作为KeyB
                        System.arraycopy(passWordItem, 0, data, 10, 6);
                    } else {
                        if (callBack != null) {
                            callBack.isSusses(false, "扇区" + i + "密码长度不正确,应为6字节或16字节");
                        }
                        return false;
                    }
                    // 获取写入位置
                    int bIndex = mfc.sectorToBlock(i);
                    int bCount = mfc.getBlockCountInSector(i);
                    try {
                        // 写到扇区的最后一个块(控制块)
                        mfc.writeBlock(bIndex + bCount - 1, data);
                    } catch (IOException e) {
                        if (callBack != null) {
                            callBack.isSusses(false, "扇区" + i + "写入控制块失败: " + e.getMessage());
                        }
                        return false;
                    }
                }
                if (callBack != null) {
                    callBack.isSusses(true, "所有扇区密码修改成功");
                }
                return true;
            } finally {
                try {
                    if (isClose) {
                        mfc.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            CrashReport.postCatchedException(e);
            if (callBack != null) {
                callBack.isSusses(false, "修改密码时发生异常: " + e.getMessage());
            }
        }
        return false;
    }
    /**
     * 修改密码
     *
     * @param a  扇区
     * @param mfc MifareClassic实例
     * @return
     */
    @Override
    public boolean changePasword(int a, MifareClassic mfc) {
        byte[] data = new byte[16];
        if (null != mfc) {
            try {
                //将密码转换为keyA
                byte[] dataA = HexUtil.hexToByteArray(companyKeyA);
                for (int i = 0; i < dataA.length; i++) {
@@ -204,20 +386,27 @@
                int bCount = mfc.getBlockCountInSector(a);
                //写到扇区的最后一个块
                mfc.writeBlock(bIndex + bCount - 1, data);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                CrashReport.postCatchedException(e);
                return false;
            }
        }
        return false;
    }
    /**
     * 初始化卡
     *
     * @return
     */
    @Override
    public boolean initCard() {
        try {
            MifareClassic mfc = MifareClassic.get(tag);
@@ -278,4 +467,6 @@
        }
        return false;
    }
}