package com.dayu.baselibrary.tools.nfc; 
 | 
  
 | 
import android.app.Activity; 
 | 
import android.content.Intent; 
 | 
import android.nfc.NfcAdapter; 
 | 
import android.nfc.Tag; 
 | 
import android.nfc.tech.MifareClassic; 
 | 
import android.util.Log; 
 | 
  
 | 
import com.dayu.baselibrary.bean.BaseUserCardCard; 
 | 
import com.dayu.baselibrary.tools.HexUtil; 
 | 
  
 | 
import java.io.IOException; 
 | 
  
 | 
/** 
 | 
 * author: zuo 
 | 
 * Date: 2024-09-25 
 | 
 * Time: 11:26 
 | 
 * 备注: 
 | 
 */ 
 | 
public class NativeNfcWriteHelper extends BaseNfcWriteHelper { 
 | 
    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); 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * 单例初始化 
 | 
     * 
 | 
     * @param intent 
 | 
     * @return 
 | 
     */ 
 | 
    public static NativeNfcWriteHelper getInstence(Intent intent, Activity activity) { 
 | 
        if (helper == null) { 
 | 
            helper = new NativeNfcWriteHelper(intent, activity); 
 | 
        } 
 | 
        helper.setIntent(intent); 
 | 
        return helper; 
 | 
    } 
 | 
  
 | 
  
 | 
    /** 
 | 
     * 写卡 
 | 
     * 
 | 
     * @param userCard 用户卡内容 
 | 
     * @param 
 | 
     */ 
 | 
    @Override 
 | 
    public boolean writeUserData(BaseUserCardCard userCard, int sector) { 
 | 
        if (userCard != null) { 
 | 
            int a = sector; 
 | 
            try { 
 | 
                MifareClassic mfc = MifareClassic.get(tag); 
 | 
                if (null != mfc) { 
 | 
                    try { 
 | 
                        //连接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; 
 | 
                            } 
 | 
                        } 
 | 
                        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); 
 | 
                            } 
 | 
                            return true; 
 | 
                        } 
 | 
                        return false; 
 | 
                    } catch (Exception e) { 
 | 
                        e.printStackTrace(); 
 | 
                        return false; 
 | 
                    } finally { 
 | 
                        try { 
 | 
                            mfc.close(); 
 | 
                        } catch (IOException e) { 
 | 
                            e.printStackTrace(); 
 | 
                        } 
 | 
                    } 
 | 
                } 
 | 
            } catch (Exception e) { 
 | 
                e.printStackTrace(); 
 | 
                return false; 
 | 
            } 
 | 
        } 
 | 
        return false; 
 | 
    } 
 | 
  
 | 
  
 | 
    /** 
 | 
     * 写卡 
 | 
     * 
 | 
     * @param str 书写内容,16个字节 
 | 
     * @param a   书写的扇区 (从0开始数) 
 | 
     * @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) { 
 | 
            try { 
 | 
                MifareClassic mfc = MifareClassic.get(tag); 
 | 
                if (null != mfc) { 
 | 
                    try { 
 | 
                        //连接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))) { 
 | 
                                    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); 
 | 
                                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); 
 | 
                            // 校验写入数据是否正确 
 | 
                            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 { 
 | 
                            mfc.close(); 
 | 
                        } catch (IOException e) { 
 | 
                            e.printStackTrace(); 
 | 
                        } 
 | 
                    } 
 | 
                } 
 | 
            } 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; 
 | 
    } 
 | 
  
 | 
  
 | 
    /** 
 | 
     * 修改密码 
 | 
     * 
 | 
     * @param a 书写的扇区 
 | 
     *          //     * @param callback 返回监听 
 | 
     */ 
 | 
    @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++) { 
 | 
                    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 
 | 
                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(); 
 | 
                return false; 
 | 
            } 
 | 
        } 
 | 
        return false; 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * 初始化卡 
 | 
     * 
 | 
     * @return 
 | 
     */ 
 | 
    @Override 
 | 
    public boolean initCard() { 
 | 
        try { 
 | 
            MifareClassic mfc = MifareClassic.get(tag); 
 | 
            if (null != mfc) { 
 | 
                try { 
 | 
                    //连接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))) { 
 | 
                                isOpen = true; 
 | 
                                break; 
 | 
                            } 
 | 
                        } 
 | 
                        if (isOpen) { 
 | 
                            //获取写的扇区的块的数量 
 | 
                            int blockCount = mfc.getBlockCountInSector(sector); 
 | 
                            int blockIndex = mfc.sectorToBlock(sector); 
 | 
                            for (int block = 0; block < blockCount; block++) { 
 | 
                                // 跳过第 0 扇区的第 0 块 
 | 
                                if (sector == 0 && block == 0) { 
 | 
                                    blockIndex++; 
 | 
                                    continue; 
 | 
                                } 
 | 
  
 | 
                                if (block < 3) { 
 | 
                                    mfc.writeBlock(blockIndex, data); 
 | 
                                } else { 
 | 
                                    mfc.writeBlock(blockIndex, initDataBytes); 
 | 
                                } 
 | 
                                //写卡 
 | 
                                blockIndex++; 
 | 
                            } 
 | 
                        } 
 | 
                    } 
 | 
                    return true; 
 | 
                } catch (Exception e) { 
 | 
                    e.printStackTrace(); 
 | 
                    return false; 
 | 
                } finally { 
 | 
                    try { 
 | 
                        mfc.close(); 
 | 
                    } catch (IOException e) { 
 | 
                        e.printStackTrace(); 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
        } catch (Exception e) { 
 | 
            e.printStackTrace(); 
 | 
            return false; 
 | 
        } 
 | 
        return false; 
 | 
    } 
 | 
  
 | 
  
 | 
} 
 |