Java 如何从RFID标签读取数据?

Java 如何从RFID标签读取数据?,java,android-studio,nfc,rfid,Java,Android Studio,Nfc,Rfid,我想从NFCv标签读取数据,我尝试了这个方法,但没有得到数据。我在互联网上搜索,但没有找到任何读取数据的线索,我使用了另一个play store应用程序,它告诉我有128个块,每个块有4个字节,总共有512个字节 try { int offset = 0; // offset of first block to read int blocks = 128; // number of blocks

我想从NFCv标签读取数据,我尝试了这个方法,但没有得到数据。我在互联网上搜索,但没有找到任何读取数据的线索,我使用了另一个play store应用程序,它告诉我有128个块,每个块有4个字节,总共有512个字节

try {
                        int offset = 0;  // offset of first block to read
                        int blocks = 128;  // number of blocks to read
                        byte[] cmd = new byte[]{
                                (byte)0x60,                  // flags: addressed (= UID field present)
                                (byte)0x23,                  // command: READ MULTIPLE BLOCKS
                                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,  // placeholder for tag UID
                                (byte)(offset & 0x0ff),      // first block number
                                (byte)((blocks - 1) & 0x0ff) // number of blocks (-1 as 0x00 means one block)
                        };

                        System.arraycopy(id, 0, cmd, 2, 8);
                        byte[] userdata = nfcvTag.transceive(cmd);

                        userdata = Arrays.copyOfRange(userdata, 0, 32);
                        tagData.setText("DATA:" + bytesToHex(userdata));
这是从NFCV标记接收的原始字符串

303330363036422031343530323030383034ffff
ffffffffffffffffffffffff3333303030204120
2046542031353033203030303030393433ffffff
ffffffff32322f30312f323031352d2d31343136
3037ffffffffffffffffffffffffffff752a307c
20dd0aeaffffffffffffffff089cffffffffffff
ffffffffffffffff0000093dffffffffffffffff
ffffffff27130fb60af1ffffffffffffffffffff
8000ffffffffffffffffffffffffffff00fd7d74
ffffffffffffffffffffffff2dcf6030ab0ee1ad
2db36004aadbe17c089f121b20362a7e089d1217
202f2a75ffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffff30303032
3030303600ac9b5300000aca00ac9bb700ac9bc4
00000000fffffffc02dd02de02de02de02dd02dd
02dd02db0000861300000a9c00ac9bff00acb829
00acb82a00acb8330000020dffffffeb03a0039e
039c039d039a039a0397039600008ad300000a51
00002a0800acb83d000000000000000000000000
00009ed500000000000000000000000000007ef9
ffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffff
ffffffffffffffff0000391effffffffffffffff
ffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffff
ffffffff000136ce2e656e64

Android NFC堆栈默认支持NfcV,因此使用类来抽象所有这些,而不是处理
byte[]
,这可能是您不理解的(否则您不会问)

bytesToHex()
可能对日志记录有用,但要将
byte[]
解码为
String
则是:

new String(bytes, StandardCharsets.UTF_8)

NfcV Android类没有任何高级访问方法,它只有一个方法,因此您使用的是正确的方法,必须处理字节数组

注意:添加标记的make/model或链接到其数据表将有助于理解如何正确读取标记

但是您没有考虑到这可能比您试图一次性读取的数据量要小

数据表还会告诉您最大收发器长度

我不知道这个标签/NfcV的最大值,但对于我使用的卡,MaxTransceiveLength是253字节,所以我猜您可能试图一次读取太多的块,而卡返回的是它所能返回的最大值

因此,我对NfcA标记使用类似的代码(快速读取)
我无法给出NfcV示例,因为我没有数据表来了解确切的命令格式,但用于说明如何考虑最大收发器长度,这与此无关。
更新以更易于理解的格式添加日志记录

//计算出我们可以进行多大的快速读取(CRC为2字节)
int maxtranceivebytes=mNfcA.getmaxtrancevelength()-2;
//计算出有多少页可以快速阅读
int maxTranscievePages=maxTranscieveBytes/4;
//算出我想读多少页
int numOfPages=endPage-startPage+1
而(numOfPages>0){
//计算出这次要阅读的页数
如果(numOfPages>maxTranscievePages){
readPages=maxTranscievePages;
//向左调整页数
numOfPages-=maxTranscievePages;
}否则{
//最后一读
readPages=numOfPages;
numOfPages=0;
}
//我们可以阅读正确的页数
字节[]结果=mNfcA.transceive(新字节[]){
(字节)0x3A,//快速读取
(字节)(起始页和0x0ff),
(字节)((起始页+读取页-1)和0x0ff),
});
//调整startpage以获得下次阅读的页数
起始页+=可读页;
//做一些结果检查
//以更易于理解的格式记录数据(每行一块/页)
对于(int i=0;i<(result.length/4);i++){
String pageData=新字符串(结果,(i*4),4,
标准字符集(UTF_8);
Log.v(“NFC”,i+“=”+页面数据);
}
}

这是我附带的一个解决方案,依次读取每个块并将每个块添加到字符串中,最后我得到了完整的十六进制值和UTF-8字符串

if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
                || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action))
        {
            currentTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            byte[] id = currentTag.getId();
            StringBuffer buf = new StringBuffer();

            tagId.setText(bytesToHex(id));

            for (String tech : currentTag.getTechList()) {

                if (tech.equals(NfcV.class.getName())) {
                    NfcV nfcvTag = NfcV.get(currentTag);
                    int numberOfBlocks = 0;
                    fullData = new StringBuffer();
                    utf8String = new StringBuffer();
                    blocksData = new ArrayList<String>();
                    while(numberOfBlocks < 128)
                    {
                        try {
                            nfcvTag.connect();
//                        connectTag.setText("Hello NFC!");
                        } catch (IOException e) {
                            Toast.makeText(getApplicationContext(), "Could not open a connection!", Toast.LENGTH_SHORT).show();
                            return;
                        }
                        try {
//
                            byte[] tagUid = currentTag.getId();  // store tag UID for use in addressed commands
//
                            byte[] cmd = new byte[] {
                                    (byte)0x20,  // FLAGS
                                    (byte)0x20,  // READ_SINGLE_BLOCK
                                    0, 0, 0, 0, 0, 0, 0, 0,
                                    (byte)(numberOfBlocks & 0x0ff)
                            };
                            System.arraycopy(tagUid, 0, cmd, 2, 8);  // paste tag UID into command
                            byte[] response = nfcvTag.transceive(cmd);
                            String data =  bytesToHex(response).substring(2);
                            String utf8 = new String(response , "UTF-8");

                            blocksData.add(data.replaceAll(" " , ""));
                            fullData.append(data.replaceAll(" " , ""));
                            utf8String.append(utf8);
                            nfcvTag.close();
                            numberOfBlocks = numberOfBlocks + 1;

                        } catch (IOException e) {
                            Toast.makeText(getApplicationContext(), "An error occurred while reading! :" + e.toString() , Toast.LENGTH_SHORT).show();
                            return;
                        }
                    }
if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(ACTION)
||NfcAdapter.ACTION\u TECH\u DISCOVERED.equals(ACTION))
{
currentTag=intent.getParcelableExtra(NfcAdapter.EXTRA_标记);
字节[]id=currentTag.getId();
StringBuffer buf=新的StringBuffer();
tagId.setText(bytesToHex(id));
对于(字符串tech:currentTag.getTechList()){
if(tech.equals(NfcV.class.getName())){
NfcV nfcvTag=NfcV.get(currentTag);
int numberOfBlocks=0;
fullData=新的StringBuffer();
utf8String=新的StringBuffer();
blocksData=newarraylist();
while(块数<128)
{
试一试{
nfcvTag.connect();
//setText(“你好,NFC!”);
}捕获(IOE异常){
Toast.makeText(getApplicationContext(),“无法打开连接!”,Toast.LENGTH\u SHORT.show();
返回;
}
试一试{
//
byte[]tagUid=currentTag.getId();//存储标记UID以用于寻址命令
//
字节[]cmd=新字节[]{
(字节)0x20,//标志
(字节)0x20,//读取单个块
0, 0, 0, 0, 0, 0, 0, 0,
(字节)(块数和0x0ff)
};
System.arraycopy(tagUid,0,cmd,2,8);//将标记UID粘贴到命令中
字节[]响应=nfcvTag.transceive(cmd);
字符串数据=bytesToHex(响应)。子字符串(2);
字符串utf8=新字符串(响应“UTF-8”);
blocksData.add(data.replaceAll(“,”);
append(data.replaceAll(“,”);
utf8String.append(utf8);
nfcvTag.close();
numberOfBlocks=numberOfBlocks+1;
}捕获(IOE异常){
Toast.makeText(getApplicationContext(),“读取时出错:”+e.toString(),Toast.LENGTH_SHORT).show();
返回;
}
}

我已经发布了答案,请检查一下