代码之家  ›  专栏  ›  技术社区  ›  Noname Noferstname

如何避免从NFC标签类型A读取数据时出现异常“收发器失败”?

  •  0
  • Noname Noferstname  · 技术社区  · 8 年前

    我正在开发一款应用程序,它应该能够模拟任何类型的复制NFC标签。从零块和页面标记读取数据后,使用以下方法键入“NFC type A”和“MIFARE Ultralight”(我还拥有标签类型):

    nfcA.transceive()
    

    mifareUltralight.readPages()
    

    其余数据无法读取,但引发异常“Transceive failed”。

    以下是相应方法的代码。对于NfcA:

    private static ArrayList<IdNameValue> readeNfcADataset(final Tag tag, final Context cxt) {
    
        String excMsg = "";
        ArrayList<IdNameValue> dataSet = new ArrayList<>();
        NfcA nfcA = NfcA.get(tag);
    
        if (nfcA != null) {
    
            dataSet.add(new IdNameValue(cxt.getString(R.string.atqa) + " ",
                    "0x" + byteArrayToHexString(nfcA.getAtqa())));
            dataSet.add(new IdNameValue(cxt.getString(R.string.sak) + " ",
                    "0x" + shortToHexString(nfcA.getSak())));
    
            byte blockNumber = 0x00;
            int bytesNumber = 1, pagesNumber = 16, counter = 0;
            byte[][] bytes = new byte[pagesNumber][bytesNumber];
    
            excMsg = "_________________________________________________\n" +
                    cxt.getString(R.string.picc_compliant_with_iso_iec_14443_3A_fnca) + ":";
            Log.i(TAG, excMsg);
    
            for (int i = 0; i < pagesNumber; i++) {
    
                excMsg = "";
                while (!nfcA.isConnected()) {
                    try {
                        nfcA.connect();
                        excMsg = cxt.getString(R.string.connecting_to_tag_has_been_created);
                        Log.i(TAG, 109 + ": " + excMsg);
    
                        bytes[i] = nfcA.transceive(new byte[]{
                                (byte) 0x30,  // READ
                                (byte) (blockNumber & 0x0FF)
                        });
                        excMsg = cxt.getString(R.string.made_to_read_data_from_a_block)
                                + Integer.toHexString(blockNumber);
                        Log.i(TAG, 117 + ": " + excMsg);
                        if (nfcA.isConnected()) nfcA.close();
                        excMsg += cxt.getString(R.string.tag_has_been_closed);
                        break;
                    } catch (IOException e) {
                        counter++;
                        excMsg = e.getMessage() + ":> " + (excMsg.equals("") ?
                                cxt.getString(R.string.the_connection_tag_is_not_created) :
                                (excMsg.contains(cxt.getString(R.string.connecting_to_tag_has_been_created)) ||
                                        excMsg.contains(cxt.getString(R.string.made_to_read_data_from_a_page))) ?
                                        "Failed to read data from a tag block: "
                                                + Integer.toHexString(blockNumber) :
                                        cxt.getString(R.string.error_closing_tag));
                        Log.e(TAG, 130 + ": " + excMsg);
                    }
    
                    if (nfcA.isConnected()) try {
                        nfcA.close();
                    } catch (IOException e1) {
                        excMsg += (":> " + e1.getMessage());
                        Log.e(TAG, 137 + ": " + excMsg);
                    }
    
                    if (counter > 9) {
                        excMsg = cxt.getString(R.string.the_number_of_connection_attempts_exceeded_the_number_of_ten);
    
                        Log.e(TAG, 143 + ": " + excMsg);
                        break;
                    }
                }
                counter = 0;
                blockNumber += (byte) bytes[i].length;
            }
    
            if (excMsg.equals(cxt.getString(R.string.the_number_of_connection_attempts_has_exceeded_one_hundred))) {
                dataSet.add(new IdNameValue("Error", " reading the data tag"));
                return dataSet;
            }
    
            dataSet.add(new IdNameValue("Page", "    0    1    2    3"));
    
            String name = "";
            String value = "";
            for (int i = 0; i < pagesNumber; i++) {
                if (!value.equals("")) dataSet.add(new IdNameValue(name, value));
                name = (i > 9 ? " " : "    ") + String.valueOf(i) + "   ";
                value = "";
                for (int j = 0; j < bytes[i].length; j++) {
                    value += ("  " + byteToHexString(bytes[i][j]));
                }
            }
            dataSet.add(new IdNameValue(name, value));
            return dataSet;
        }
        return dataSet;
    }
    

    对于MifareUltraligh:

    private static ArrayList<IdNameValue> readeMifareUltralightDataset(final Tag tag, final Context cxt) {
    
        MifareUltralight mifareUltralight = MifareUltralight.get(tag);
        String excMsg = "";
        int bytesNumber = 1, pagesNumber = 4, counter = 0, startBlock;
        byte[][] bytes = new byte[pagesNumber][bytesNumber];
        startBlock = 0x00;
    
        excMsg = "_________________________________________________\n" +
                cxt.getString(R.string.mifare_ultralight_or_ultralight_c) + ":";
        Log.i(TAG, excMsg);
    
        for (int i = 0; i < pagesNumber; i++) {
    
            while (!mifareUltralight.isConnected()) {
                excMsg = "";
                try {
                    mifareUltralight.connect();
                    excMsg = cxt.getString(R.string.connecting_to_tag_has_been_created);
                    Log.i(TAG, 201 + ": " + excMsg);
    
                    bytes[i] = mifareUltralight.readPages(startBlock);
                    excMsg = cxt.getString(R.string.done_reading_pages_twice_blocks)
                            + Integer.toHexString(startBlock) + " - "
                            + Integer.toHexString((startBlock + bytes[i].length) - 1);
                    Log.i(TAG, 207 + ": " + excMsg);
                    if (mifareUltralight.isConnected()) mifareUltralight.close();
                    excMsg = cxt.getString(R.string.tag_has_been_closed);
                    Log.i(TAG, 210 + ": " + excMsg);
                    break;
                } catch (IOException e) {
                    counter++;
                    excMsg = e.getMessage() + ":> " + (excMsg.equals("") ?
                            cxt.getString(R.string.the_connection_tag_is_not_created) :
                            (excMsg.contains(cxt.getString(R.string.connecting_to_tag_has_been_created)) ||
                                    excMsg.contains(cxt.getString(R.string.done_reading_pages_twice_blocks)) ?
                                    "Failed to read page from tag blocks: "
                                            + Integer.toHexString(startBlock) + " - "
                                            + Integer.toHexString(startBlock + bytes[i].length - 1) :
                                    cxt.getString(R.string.error_closing_tag)));
                    Log.e(TAG, 222 + ": " + excMsg);
                }
    
                if (mifareUltralight.isConnected()) try {
                    mifareUltralight.close();
                    break;
                } catch (IOException e) {
                    excMsg = (":> " + e.getMessage());
                    Log.e(TAG, 230 + ": " + excMsg);
                }
    
                if (counter > 9) {
                    excMsg = cxt.getString(R.string.the_number_of_connection_attempts_exceeded_the_number_of_ten);
                    Log.e(TAG, 236 + ": " + excMsg);
                    break;
                }
            }
            counter = 0;
            startBlock += bytes[i].length;
        }
    
        ArrayList<IdNameValue> dataSet = new ArrayList<>();
        if (excMsg.equals(cxt.getString(R.string.the_number_of_connection_attempts_has_exceeded_one_hundred))) {
            dataSet.add(new IdNameValue("Error", " reading the data tag"));
            return dataSet;
        }
    
        dataSet.add(new IdNameValue("Page", "    0    1    2    3"));
    
        int n = -1;
        String name = "";
        String value = "";
        for (int i = 0; i < pagesNumber; i++) {
            for (int j = 0; j < bytes[i].length; j++) {
                if (j % 4 == 0) {
                    n++;
                    if (!value.equals("")) dataSet.add(new IdNameValue(name, value));
                    name = (n > 9 ? " " : "    ") + String.valueOf(n) + "   ";
                    value = "";
                }
                value += ("  " + byteToHexString(bytes[i][j]));
            }
        }
        dataSet.add(new IdNameValue(name, value));
        return dataSet;
    }
    

    它会将生成的日志分段:

    ...cardreader I/TagController: _________________________________________________
                                   PICC compliant with ISO/IEC 14443-3A (NFCA):
    ...cardreader I/TagController: 109: The connecting to tag has been created
    ...cardreader I/TagController: 117: Made to read data from a block: 0
    ...cardreader I/TagController: 109: The connecting to tag has been created
    ...cardreader E/TagController: 130: Transceive failed:> Failed to read data from a tag block: 10
    ...cardreader I/TagController: 109: The connecting to tag has been created
    ...cardreader E/TagController: 130: Transceive failed:> Failed to read data from a tag block: 10
    ...........................................................
    ...cardreader I/TagController: 109: The connecting to tag has been created
    ...cardreader E/TagController: 130: Transceive failed:> Failed to read data from a tag block: 1e
    ...cardreader E/TagController: 143: The number of connection attempts exceeded the number of ten.
    ...cardreader I/TagController: _________________________________________________
                                   MIFARE Ultralight or Ultralight C:
    ...cardreader I/TagController: 201: The connecting to tag has been created
    ...cardreader I/TagController: 207: Done reading pages twice blocks:0 - f
    ...cardreader I/TagController: 210: Tag has been closed
    ...cardreader I/TagController: 201: The connecting to tag has been created
    ...cardreader E/TagController: 222: Transceive failed:> Failed to read page from tag blocks: 10 - 10
    ...cardreader I/TagController: 201: The connecting to tag has been created
    ...cardreader E/TagController: 222: Transceive failed:> Failed to read page from tag blocks: 11 - 11
    ...cardreader I/TagController: 201: The connecting to tag has been created
    ...cardreader E/TagController: 222: Transceive failed:> Failed to read page from tag blocks: 12 - 12
    

    Card UID: 04 3A 31 02 54 2E 82
    Card SAK: 00
    PICC type: MIFARE Ultralight or Ultralight C
    Page  0  1  2  3
      0   04 3A 31 87
      1   02 54 2E 82
      2   FA 48 F0 00
      3   FF FF FF FC
      4   45 D9 B0 49
      5   9E 6A 2D 00
      6   1E 82 00 00
      7   1E 82 00 00
      8   1E 7E 05 00
      9   40 00 08 09
     10   B7 DD DB FF
     11   1E 7E 98 48
     12   1E 7E 05 00
     13   40 00 08 09
     14   B7 DD DB FF
     15   1E 7E 98 48
    

    在下面的屏幕截图中,应用程序演示了标签允许读取类型、技术和UID上的数据: The output data read from the label on its type, technology, and UID

    下面显示了从标记读取的输出,即前16个字节的数据。 对于NFC类型A: The output read from the data labels (for NFC type A)

    对于MIFARE Ultralight: The output read from the data labels (for MIFARE Ultralight) 可以看出,系统只读取前16个byt。可能有什么问题?请有任何想法。

    1 回复  |  直到 8 年前
        1
  •  0
  •   Noname Noferstname    8 年前

    仔细阅读文档,即 "MF0ICU1 MIFARE Ultralight contactless single-ticket IC" / Rev. 3.9 — 23 July 2014 #028639 "MF0ICU2 MIFARE Ultralight C" / Rev. 3.2 — 19 May 2009 #171432 led,并最终理解了问题:所有的盐在块寻址,这是提供给命令输入READE。类型标记NFCA的数字块计算应如下所示:

    blockNumber = (byte) (i * 4);
    

    对于标签类型Mifare Ultralight:

    startBlock = i * 4;
    

    然后一切都开始了。