Search code examples
androidformaturinfcndef

Unexpected prefix is added to URL/URI when writing to NFC tag


I am trying to write a URI/URL to an NFC tag. I am able to do that successfully but there is a prefix that gets automatically added to the URI that I write.

For example: If the URL that I want to write is "https://indies.net.in", then the URL that is actually written on the tag is "https://www.enindies.net.in".

Can someone please tell me what am I'm doing wrong here?

Creating message:

private NdefMessage createNdefMessage(String content){
    NdefRecord ndefRecord= createTextRecord(content);
    NdefMessage ndefMessage=new NdefMessage(new NdefRecord[]{ndefRecord});
    return ndefMessage;
}

Creating the URL record:

private NdefRecord createUrlRecord(String content) {
    try{
        byte[] language;
        language= Locale.getDefault().getLanguage().getBytes();
        final byte[] text=content.getBytes("UTF-8");
        final int languageSize=language.length;
        final int textLength=text.length;
        final ByteArrayOutputStream payload= new ByteArrayOutputStream(1+languageSize+textLength);

        payload.write((byte) (languageSize & 0x1F));
        payload.write(language,0,languageSize);
        payload.write(text,0,textLength);

        return new NdefRecord(NdefRecord.TNF_WELL_KNOWN,NdefRecord.RTD_URI,new byte[0],payload.toByteArray());
    }catch (Exception e){
        Log.e("createTextRecord",e.getMessage());
    }
    return  null;
}

Writing message:

private void writeNdefMessage(Tag tag, NdefMessage ndefMessage){
    try {
        if (tag== null){
            Toast.makeText(this," Tag object cannot be null",Toast.LENGTH_SHORT).show();
            return;
        }

        Ndef ndef=Ndef.get(tag);
        if (ndef==null){
            formatTag(tag,ndefMessage);
        } else {
            ndef.connect();
            if (!ndef.isWritable()){
                Toast.makeText(this," Tag cannot be Written",Toast.LENGTH_SHORT).show();
                ndef.close();
                return;
            }
            ndef.writeNdefMessage(ndefMessage);
            ndef.close();
            Toast.makeText(this," Tag Written!",Toast.LENGTH_SHORT).show();
        }

Solution

  • The problem with your method of writing the URL to the NFC tag is that you seem to have copied that from code that was originally intended to write NFC Forum Text records. This is also suggested by the fact that your method seems to have originally been called "createTextRecord" (at least that's what you call in createNdefMessage).

    Now the problem with this is that Text records and URI records have a completely different format. Hence, if you put the payload of a Text record into a URI record you will get an unexpected outcome. In your case, the status byte (first byte of the Text record, containing the size of the language field) was mapped to the Identifier code of the URI record. As the value of that field was 0x02, this was translated to the URI prefix "https://www.". Moreover, the language field itself (containing the language code "en") was added to the URI.

    In general, you would want to use the method NdefRecord.createUri() to create a proper URI record for your URL. This will automatically take care of normalizing and compressing the URI according to the compression scheme of the NFC Forum URI record type definition.

    NdefRecord ndefRecord= NdefRecord.createUri("https://indies.net.in");
    

    However, if you need to support platforms before API 14 (where this method was introduced) you could also create the URI record manually. For example, if you don't care about compression, you could use:

    private NdefRecord createUrlRecord(String url) {
        byte[] uriBytes = content.getBytes("UTF-8");
    
        byte[] payload = new byte[uriBytes.length + 1];
        payload[0] = (byte)0x00;
        System.arraycopy(uriBytes, 0, payload, 1, uriBytes.length);
    
        return new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
                              NdefRecord.RTD_URI,
                              null,
                              payload);
    }
    
    NdefRecord ndefRecord= createUrlRecord("https://indies.net.in");