| | |
| | | |
| | | 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 |
| | |
| | | private Tag tag; |
| | | |
| | | private static NativeNfcWriteHelper helper; |
| | | |
| | | public NativeNfcWriteHelper(Intent intent, Activity activity) { |
| | | } |
| | | |
| | | public void setIntent(Intent intent) { |
| | | this.tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); |
| | |
| | | */ |
| | | public static NativeNfcWriteHelper getInstence(Intent intent, Activity activity) { |
| | | if (helper == null) { |
| | | helper = new NativeNfcWriteHelper(intent, activity); |
| | | helper = new NativeNfcWriteHelper(); |
| | | } |
| | | helper.setIntent(intent); |
| | | return helper; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 写卡 |
| | |
| | | MifareClassic mfc = MifareClassic.get(tag); |
| | | if (null != mfc) { |
| | | try { |
| | | //连接NFC |
| | | // 连接NFC |
| | | mfc.connect(); |
| | | //验证扇区密码 |
| | | // 验证扇区密码 |
| | | boolean isOpen = false; |
| | | for (int i = 0; i < listKeyA.size(); i++) { |
| | | if (mfc.authenticateSectorWithKeyA(a, listKeyA.get(i))) { |
| | | isOpen = true; |
| | | if (listKeyA.get(i).equals(defauleKey)) { |
| | | //当前为默认白卡密码时写卡时修改密码 |
| | | // 当前为默认白卡密码时写卡时修改密码 |
| | | changePasword(a, mfc); |
| | | } |
| | | break; |
| | |
| | | data = userCard.getTwoBytes(); |
| | | } |
| | | int bIndex = mfc.sectorToBlock(a); |
| | | //写卡 |
| | | // 写卡 |
| | | mfc.writeBlock(bIndex + b, data); |
| | | } |
| | | return true; |
| | |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * 写卡(带回调) |
| | | * |
| | | * @param userCard 用户卡内容 |
| | | * @param sector 扇区 |
| | | * @param callBack 回调接口 |
| | | */ |
| | | public boolean writeUserData(BaseUserCardCard userCard, int sector, NFCCallBack callBack) { |
| | | if (userCard != null) { |
| | | int a = sector; |
| | | try { |
| | | MifareClassic mfc = MifareClassic.get(tag); |
| | | if (null != mfc) { |
| | | try { |
| | | // 连接NFC |
| | | mfc.connect(); |
| | | // 验证扇区密码 |
| | | boolean isOpen = false; |
| | | |
| | | if (listKeyA.size() != 0) { |
| | | for (int i = 0; i < listKeyA.size(); i++) { |
| | | if (mfc.authenticateSectorWithKeyA(a, listKeyA.get(i))) { |
| | | isOpen = true; |
| | | if (listKeyA.get(i).equals(defauleKey)) { |
| | | // 当前为默认白卡密码时写卡时修改密码 |
| | | changePasword(a, mfc); |
| | | } |
| | | 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) { |
| | | for (int b = 0; b < 3; b++) { |
| | | byte[] data; |
| | | if (b == 0) { |
| | | data = userCard.getZeroBytes(); |
| | | } else if (b == 1) { |
| | | data = userCard.getOneBytes(); |
| | | } else { |
| | | data = userCard.getTwoBytes(); |
| | | } |
| | | int bIndex = mfc.sectorToBlock(a); |
| | | // 写卡 |
| | | mfc.writeBlock(bIndex + b, data); |
| | | } |
| | | if (callBack != null) { |
| | | callBack.isSusses(true, "用户数据写入成功"); |
| | | } |
| | | return true; |
| | | } |
| | | 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 { |
| | | mfc.close(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | if (callBack != null) { |
| | | callBack.isSusses(false, "写卡异常: " + e.getMessage()); |
| | | } |
| | | return false; |
| | | } |
| | | } else { |
| | | if (callBack != null) { |
| | | callBack.isSusses(false, "用户卡数据为空"); |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * 写卡 |
| | |
| | | |
| | | @Override |
| | | public boolean writeData(byte[] str, int a, int b, NFCCallBack callBack) { |
| | | return writeData(str, a, b, true,null); |
| | | return writeData(str, a, b, true, null); |
| | | } |
| | | |
| | | @Override |
| | |
| | | MifareClassic mfc = MifareClassic.get(tag); |
| | | if (null != mfc) { |
| | | try { |
| | | //连接NFC |
| | | if (isConnect){ |
| | | // 连接NFC |
| | | 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; |
| | | if (listKeyA.size() != 0) { |
| | | for (int i = 0; i < listKeyA.size(); i++) { |
| | | if (mfc.authenticateSectorWithKeyA(0, listKeyA.get(i))) { |
| | | if (mfc.authenticateSectorWithKeyA(a, listKeyA.get(i))) { |
| | | isOpen = true; |
| | | if (listKeyA.get(i).equals(defauleKey)) { |
| | | //当前为默认白卡密码时写卡时修改密码 |
| | | // 当前为默认白卡密码时写卡时修改密码 |
| | | changePasword(a, mfc); |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | } else if (listA_PS.size() != 0 && listA_PS.size() > a) { |
| | | if (mfc.authenticateSectorWithKeyA(a, defauleKey)){ |
| | | changePasword(a, mfc); |
| | | if (mfc.authenticateSectorWithKeyA(a, defauleKey)) { |
| | | isOpen = true; |
| | | |
| | | }else if (mfc.authenticateSectorWithKeyA(a, listA_PS.get(a))) { |
| | | } else if (mfc.authenticateSectorWithKeyA(a, listA_PS.get(a))) { |
| | | isOpen = true; |
| | | } |
| | | } |
| | | if (isOpen) { |
| | | int bIndex = mfc.sectorToBlock(a); |
| | | //写卡 |
| | | // 写卡 |
| | | mfc.writeBlock(bIndex + b, str); |
| | | // 校验写入数据是否正确 |
| | | boolean isVerified = true; |
| | |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * 修改密码 |
| | | * |
| | | * @param passWord 密码 |
| | | * @return |
| | | */ |
| | | 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 callback 返回监听 |
| | | * @param a 扇区 |
| | | * @param mfc MifareClassic实例 |
| | | * @return |
| | | */ |
| | | @Override |
| | | public boolean changePasword(int a, MifareClassic mfc) { |
| | | |
| | | byte[] data = new byte[16]; |
| | | if (null != mfc) { |
| | | try { |
| | | //将密码转换为keyA |
| | | // 将密码转换为keyA |
| | | byte[] dataA = HexUtil.hexToByteArray(companyKeyA); |
| | | for (int i = 0; i < dataA.length; i++) { |
| | | data[i] = dataA[i]; |
| | | } |
| | | //输入控制位 |
| | | // 输入控制位 |
| | | data[6] = (byte) 0xFF; |
| | | data[7] = (byte) 0x07; |
| | | data[8] = (byte) 0x80; |
| | | data[9] = (byte) 0x69; |
| | | byte[] dataB = HexUtil.hexToByteArray(companyKeyB); |
| | | //将密码转换为KeyB |
| | | // 将密码转换为KeyB |
| | | for (int i = 0; i < dataB.length; i++) { |
| | | data[i + 10] = dataB[i]; |
| | | } |
| | | int bIndex = mfc.sectorToBlock(a); |
| | | 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; |
| | | } |
| | | |
| | |
| | | MifareClassic mfc = MifareClassic.get(tag); |
| | | if (null != mfc) { |
| | | try { |
| | | //连接NFC |
| | | // 连接NFC |
| | | mfc.connect(); |
| | | //获取扇区数量 |
| | | // 获取扇区数量 |
| | | int count = mfc.getSectorCount(); |
| | | byte[] data = new byte[16]; |
| | | String initData = "FFFFFFFFFFFFFF078069FFFFFFFFFFFF"; |
| | | byte[] initDataBytes = HexUtil.hexToByteArray(initData); |
| | | for (int sector = 0; sector < count; sector++) { |
| | | //验证扇区密码 |
| | | // 验证扇区密码 |
| | | boolean isOpen = false; |
| | | for (int i = 0; i < listKeyA.size(); i++) { |
| | | if (mfc.authenticateSectorWithKeyA(sector, listKeyA.get(i))) { |
| | |
| | | } |
| | | } |
| | | if (isOpen) { |
| | | //获取写的扇区的块的数量 |
| | | // 获取写的扇区的块的数量 |
| | | int blockCount = mfc.getBlockCountInSector(sector); |
| | | int blockIndex = mfc.sectorToBlock(sector); |
| | | for (int block = 0; block < blockCount; block++) { |
| | |
| | | } else { |
| | | mfc.writeBlock(blockIndex, initDataBytes); |
| | | } |
| | | //写卡 |
| | | // 写卡 |
| | | blockIndex++; |
| | | } |
| | | } |
| | |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | |
| | | } |