Como gravar uma mensagem NDEF a partir de um aplicativo Android?
Abra Ndef numa tag formatada, ou NdefFormatable numa tag virgem, ligue fora da thread principal, confira que a tag é gravável e que a mensagem cabe, e grave a mensagem inteira numa única chamada. Tornar a tag somente leitura é uma chamada à parte, e a referência diz com todas as letras que ela não pode ser revertida.
Montar a mensagem
A classe NdefRecord monta os registros comuns por você: createUri a partir do nível de API 14, createMime a partir do nível 16 e createTextRecord a partir do nível 21. Juntar os bytes à mão é onde começam os erros de codificação, e os auxiliares tiram essa necessidade.
createMime passa o tipo MIME a minúsculas para seguir as regras do Android de filtragem de intent, então o tipo gravado na tag já corresponde a um filtro em minúsculas.
Ponha primeiro o registro que importa. O Android despacha pelo primeiro registro, e uma mensagem que começa com um registro de texto é despachada como text/plain, venha o que vier depois. O que os registros contêm está coberto na página da estrutura da mensagem.
O que conferir antes de gravar
Três valores vêm sem tocar no rádio. isWritable() diz se a tag é somente leitura, e getMaxSize() dá a maior mensagem NDEF que ela aceita, em bytes. A mensagem conhece o próprio tamanho: a referência de NdefMessage documenta getByteArrayLength() como o comprimento que ela vai ocupar depois de serializada.
Compare os dois últimos antes de chamar qualquer coisa que grave. Uma mensagem um byte longa demais falha na gravação, depois que o usuário segurou o celular parado à toa, e a comparação não custa nada.
getCachedNdefMessage() pode devolver null numa tag que está formatada mas ainda não guarda mensagem alguma, o que a referência chama de estado inicializado. Isso é uma tag pronta para gravar, não uma tag que falhou na leitura.
A gravação em si
connect(), depois writeNdefMessage(), depois close(), numa thread que não é a principal. A referência de Ndef marca a gravação como bloqueante e como algo que sobrescreve qualquer mensagem que a tag guardasse.
Uma tag virgem passa por NdefFormatable.format() em vez disso, que a formata e grava uma primeira mensagem numa chamada só. A referência descreve um processo de várias etapas que levanta IOException se qualquer etapa falhar, então uma exceção diz que o processo parou, não onde.
Quatro exceções pedem quatro respostas. FormatException quer dizer que a mensagem em si está malformada. TagLostException quer dizer que a tag saiu do campo. IOException cobre outras falhas e um cancelamento. SecurityException quer dizer que o objeto Tag está velho, usado depois que a tag dele saiu do campo.
Depois de uma TagLostException, não presuma nada. Leia a tag de novo antes de tentar outra vez, já que a gravação pode ter terminado, falhado ou parado no meio, o caso que a página da gravação interrompida cobre do lado do usuário.
Somente leitura é um caminho só de ida
makeReadOnly() põe o contêiner de capacidade em somente leitura e, onde a tag permite, fixa os bits de bloqueio de forma permanente. A referência a chama de um processo só de ida que não pode ser revertido.
Confira canMakeReadOnly() primeiro, e nunca ligue a chamada ao mesmo botão da gravação. NdefFormatable.formatReadOnly() faz as duas coisas numa chamada só, o que tira a última chance de conferir o conteúdo antes que ele seja congelado.
Bloqueie no fim de uma série conferida, se é que vai bloquear. Quando bloquear é a decisão certa está coberto na página do bloqueio.
Ler de volta
Confira com getNdefMessage(), que lê a tag, e nunca com a mensagem em cache, que ainda descreve a tag como ela era antes da gravação.
Depois leia a tag com outra coisa que não seja o seu código, e na outra plataforma. Um defeito que grava o tipo de registro errado o decodifica do mesmo jeito errado, e um iPhone consegue ignorar um registro que o seu analisador Android aceita.
Perguntas frequentes
Uma gravação pequena pode rodar na thread principal?
Não. A referência marca toda gravação como uma operação bloqueante que não deve rodar na thread principal, seja qual for o tamanho dela.
Por que writeNdefMessage levanta FormatException?
A referência a levanta quando a mensagem NDEF a gravar está malformada, então o conserto está na mensagem, e não na tag.
NdefFormatable funciona em toda tag virgem?
Não. Ela aparece só nas tags que o celular sabe formatar, e a referência diz que nenhum conjunto de tags é obrigatório entre aparelhos.
Uma tag somente leitura pode voltar a ser gravável?
Não. A referência descreve makeReadOnly como um processo só de ida que não pode ser revertido.