Search code examples
androidformatnfcmifarendef

Formatting a Mifare Ultralight to NDEF throw IO Exception


I want to format a never-used MIFARE Ultralight card using the code below:

NdefFormatable formatable = NdefFormatable.get(tag);
if (formatable != null) {
    String result = "Afifly";
    try {
        formatable.connect();

        try {
            formatable.format(new NdefMessage(new NdefRecord(NdefRecord.TNF_EMPTY, null, null, null)));
        } catch (Exception e) {
            // let the user know the tag refused to format
            System.out.println("error ");//+getStackTrace(e));
            result = "Fail 1";
        }
    } catch (Exception e) {
        // let the user know the tag refused to connect
        System.out.println("eeeerrror 2"+e);
        result = "Fail 2";
    } finally {
        try {
            formatable.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return;
}

But it always throws an IOException (without any meaningful message) when calling the method formatable.format(...).

I tried with several other cards, all with the same result. However, these cards can be formatted using NXP TagWriter for example.

I already found the question/answer "Formatting a Mifare Ultralight C to NDEF", but this solution does not work for me. I still get the same IOException.

The first four pages (pages 0-3) of the tag contain the following bytes:

04 F1 E9 94
42 AB 4A 80
23 48 00 00  (all lock-bits cleared)
00 00 00 00  (no capability container)

Thus, the tag is empty and not locked.


Solution

  • The most likely reason for getting an IOException when calling NdefFormatable.format() on an empty MIFARE Ultralight tag is that your device does not support "formatting" (i.e. initializing as NFC Forum Type 2 tag) that type of tag. If that's the case, it is clearly a bug that you even see the NdefFormatable technology.

    The only option that you have in that case, is that you manually perform the formatting procedure (see the NFC Forum Type 2 Tag Operation specification for details). That is also what various tag writing apps (e.g. NXP TagWriter) do. For a MIFARE Ultralight (MF0ICU1) tag (don't try to use this for larger tags!), something like this would work:

    NfcA nfcA = NfcA.get(tag);
    if (nfcA != null) {
        try {
            nfcA.connect();
            nfcA.transceive(new byte[] {
                (byte)0xA2,  // WRITE
                (byte)0x03,  // page = 3
                (byte)0xE1, (byte)0x10, (byte)0x06, (byte)0x00  // capability container (mapping version 1.0, 48 bytes for data available, read/write allowed)
            });
            nfcA.transceive(new byte[] {
                (byte)0xA2,  // WRITE
                (byte)0x04,  // page = 4
                (byte)0x03, (byte)0x00, (byte)0xFE, (byte)0x00  // empty NDEF TLV, Terminator TLV
            });
        } catch (Exception e) {
        } finally {
            try {
                nfcA.close();
            } catch (Exception e) {
            }
        }
    }