Ir para o conteúdo
Idioma: PT

Como gravar uma tag para que uma gravação interrompida não possa passar por válida?

Ponha o tamanho da mensagem em zero primeiro, grave a mensagem, e grave o tamanho real por último. Uma interrupção antes do último passo deixa uma tag que lê como vazia em vez de um tamanho que anuncia bytes que nunca chegaram. A pilha NFC de código aberto do Android grava NDEF nessa ordem nas tags Tipo 2, Tipo 4 e Tipo 5.

Uma gravação são muitos comandos

Uma tag Tipo 2 recebe quatro bytes por comando. A referência do MifareUltralight documenta writePage() como gravando uma página e diz que o protocolo sempre grava uma página de cada vez, então uma mensagem de cem bytes leva uns vinte e cinco comandos. Uma tag que sai entre dois deles fica com as páginas já gravadas ao lado das páginas que ela guardava antes.

O que decide o resultado é o campo de tamanho. Gravado primeiro com o valor novo, ele anuncia a mensagem nova enquanto as páginas posteriores ainda guardam a antiga, e um leitor interpreta a mistura como uma mensagem: a página da gravação pela metade descreve a tag que então lê como corrompida ou para no meio do caminho. Gravado por último, ele não dá a um leitor nada para interpretar até a mensagem estar completa.

A ordem, tipo por tipo

A pilha NFC de código aberto do Android aplica os mesmos três passos a cada tipo, e o código fonte dela os mostra:

Como a pilha NFC do Android ordena uma gravação NDEF
TipoCampo de tamanhoPassos na pilha
Tipo 2O tamanho do bloco TLV do NDEFGrava o bloco que o guarda com um tamanho zero, depois a mensagem, depois o bloco de novo com o tamanho real, em rw_t2t_ndef.cc
Tipo 4NLEN, no começo do arquivo NDEFPõe NLEN em 0000, grava a mensagem depois dele, depois grava NLEN, em rw_t4t.cc
Tipo 5O tamanho do bloco TLV do NDEFPõe o tamanho em zero, grava a mensagem e o bloco Terminator, depois põe o tamanho, em rw_i93.cc

Uma interrupção depois do primeiro passo deixa uma mensagem NDEF de tamanho zero. Os leitores informam uma tag vazia, e o aplicativo que a gravou consegue saber que a gravação dele não terminou.

A ordem protege a mensagem, não a página que está sendo gravada quando a interrupção chega. O que um chip guarda numa página cuja gravação foi cortada é uma propriedade do chip, e a ordem estreita esse risco à gravação final, aquela que põe o tamanho.

Quando a plataforma grava por você

No Android, Ndef.writeNdefMessage() entrega a mensagem à pilha NFC, que a grava na ordem acima, e o código que o usa não tem nada a acrescentar além de ler a tag de volta. Um fabricante de celulares pode entregar uma pilha modificada, então ler de volta é a conferência que vale em todo celular.

No iOS, a referência da Apple para writeNDEF não descreve a ordem que o gravador dela usa. Um aplicativo fica sabendo de uma atualização fracassada por ndefReaderSessionErrorTagUpdateFailure ou por uma conexão perdida, como explica a página da gravação no iOS, e relê a tag para saber o que ela guarda agora.

Quando o seu código grava as páginas

O código que grava páginas brutas, para gravar uma tag protegida depois de se autenticar ou para guardar dados que não são NDEF, assume o trabalho da pilha. Para o NDEF, ele segue a tabela: zerar o tamanho, gravar a mensagem, gravar o tamanho. A página que guarda o tamanho em geral guarda também os primeiros bytes da mensagem, então a última gravação regrava essa página com os dois, como a pilha do Android faz.

Para dados que não são NDEF, a mesma ideia precisa de um campo próprio do aplicativo, um tamanho, uma versão ou uma soma de verificação gravada depois dos dados, que o código de leitura confere antes de confiar em qualquer coisa. Sem isso, uma gravação cortada se parece exatamente com dados.

Depois releia e compare. Uma gravação cujo último comando terminou numa exceção tem um resultado desconhecido, e a página da gravação pela metade explica por que ler vem antes de qualquer nova tentativa.

Perguntas frequentes

Ndef.writeNdefMessage já grava nessa ordem?

Na pilha NFC de código aberto do Android, sim, nas tags Tipo 2, Tipo 4 e Tipo 5. Releia a tag mesmo assim, já que um fabricante de celulares pode modificar a pilha.

O que um leitor vê depois de uma gravação interrompida?

Uma mensagem NDEF de tamanho zero, quando a interrupção chegou entre o primeiro e o último passo. Os aplicativos a informam como uma tag vazia.

A gravação final do tamanho pode ser interrompida?

Pode, e nenhuma ordem protege esse único comando. A ordem estreita o risco a uma gravação só, e o que uma página cortada durante a própria gravação guarda depende do chip.

O iOS grava NDEF na mesma ordem?

A referência da Apple não diz. Confira o resultado relendo a tag depois de gravar.