Ir para o conteúdo
Idioma: PT

Modo leitor ou despacho em primeiro plano: qual um aplicativo Android deve usar?

O modo leitor, para uma tela cujo objetivo é ler tags. Ele entrega cada tag direto a um retorno de chamada, consegue pular a conferência de NDEF e o som do sistema, e suspende a emulação de cartão. O despacho em primeiro plano serve a um aplicativo que encontra tags de vez em quando e as quer como intents.

O que os dois fazem

Os dois dão à atividade que está na tela o primeiro direito sobre a próxima tag, na frente de todo aplicativo que se registrou para tags no manifesto dele. A referência de NfcAdapter descreve o despacho em primeiro plano como algo que dá prioridade à atividade em primeiro plano, e o modo leitor como algo que limita o controlador enquanto a atividade está em primeiro plano.

Nenhum dos dois sobrevive à atividade sair da tela. O despacho em primeiro plano tem de ser ativado enquanto a atividade está retomada e desativado antes que o onPause dela termine, e chamá-lo enquanto a atividade não está em primeiro plano levanta IllegalStateException.

E nenhum dos dois muda o que acontece quando o aplicativo está fechado. Uma tag que deve abrir o aplicativo passa pelo manifesto, coberto na página do manifesto.

O que o modo leitor muda

O modo leitor transforma o controlador num leitor e em nada mais. A referência afirma que ele desativa o ponto a ponto e a emulação de cartão enquanto estiver rodando, então um usuário que abre a sua tela de leitura num caixa não consegue pagar com o celular até sair dela.

Ele sonda só as tecnologias que você nomeia, por sinalizadores como FLAG_READER_NFC_A ou FLAG_READER_NFC_V. Uma tela feita para rótulos ISO/IEC 15693 que sonda só NFC-V não reage a um cartão bancário mantido ao lado dela.

FLAG_READER_SKIP_NDEF_CHECK impede a plataforma de ler a tag em busca de NDEF antes que o seu retorno de chamada rode. A referência é explícita sobre o custo: a classe Ndef deixa então de ser enumerada na tag, e o despacho baseado em NDEF não funciona. É o sinalizador de uma tela que envia os próprios comandos, e o sinalizador errado para uma tela que lê mensagens.

FLAG_READER_NO_PLATFORM_SOUNDS silencia o som de descoberta do sistema, o que deixa o seu aplicativo responsável por dizer ao usuário que alguma coisa aconteceu. O extra EXTRA_READER_PRESENCE_CHECK_DELAY define o intervalo que a plataforma usa para conferir que a tag continua ali.

As tags chegam por onTagDiscovered em vez de chegar como intents. A partir do nível de API 37 o retorno de chamada também tem onTagLost, chamado quando a tag sai; antes desse nível, uma saída aparece como uma exceção na troca seguinte.

Para um celular que emula um cartão pela emulação de cartão pelo host, a referência recomenda FLAG_READER_NFC_A junto com FLAG_READER_SKIP_NDEF_CHECK.

O que o despacho em primeiro plano mantém

O despacho em primeiro plano muda quem recebe a tag e pouco mais. A plataforma continua lendo a tag em busca de NDEF e continua tocando o som de descoberta dela, o sinalizador que o silencia pertencendo ao modo leitor, e nada na referência suspende a emulação de cartão enquanto ele está ativado.

A tag chega como uma intent, pelo PendingIntent que você passa. O guia de NFC avançado o monta com FLAG_MUTABLE, porque o sistema tem de acrescentar a tag à intent, e desde o Android 12 a referência de PendingIntent exige que todo PendingIntent declare a mutabilidade dele. O mesmo exemplo acrescenta FLAG_ACTIVITY_SINGLE_TOP, para que a tag chegue à atividade aberta em onNewIntent em vez de abrir uma segunda cópia.

Os filtros e as listas de tecnologia estreitam o que a atividade recebe, com as mesmas regras do manifesto. Passar null nos dois faz a atividade receber toda tag por ACTION_TAG_DISCOVERED, uma ação que a referência marca como descontinuada a partir do nível de API 37.

A entrega cai em onNewIntent, e o guia de processos e threads diz que os retornos de chamada do ciclo de vida rodam sempre na thread principal. Toda troca com a tag tem de sair dali, já que a referência de TagTechnology proíbe entrada e saída nessa thread.

Escolher entre os dois

Modo leitor e despacho em primeiro plano, ponto a ponto
PerguntaModo leitorDespacho em primeiro plano
Como a tag chegaUm retorno de chamada, onTagDiscoveredUma intent, em onNewIntent
Emulação de cartão enquanto ativoSuspensaInalterada
Tecnologias sondadasSó as nomeadas por sinalizadoresTodas
Conferência de NDEF e som do sistemaDá para pularSempre feitas
Disponível a partir deNível de API 19Nível de API 10

Escolha o modo leitor quando a tela existe para ler tags: uma conferência de estoque, uma ferramenta de configuração, um leitor para um cartão proprietário. A tag vai direto para o seu código e nada mais no celular compete por ela.

Escolha o despacho em primeiro plano quando as tags são uma entrada entre outras, e o celular deve continuar pagando e se comportando normalmente enquanto a sua atividade está aberta.

Perguntas frequentes

Por que o celular para de pagar enquanto o meu aplicativo está aberto?

O modo leitor está ativado. A referência afirma que ele desativa a emulação de cartão enquanto a atividade está em primeiro plano, então reserve-o para telas cujo objetivo é ler.

Que sinalizadores usar para ler outro celular?

Para um celular que emula um cartão pela emulação de cartão pelo host, a referência recomenda FLAG_READER_NFC_A junto com FLAG_READER_SKIP_NDEF_CHECK.

Ainda preciso de filtros de intent no manifesto?

Só para as tags que devem abrir o aplicativo quando ele não está aberto. Nem o modo leitor nem o despacho em primeiro plano valem antes de uma atividade estar na tela.

Por que enableForegroundDispatch levanta IllegalStateException?

Ele foi chamado enquanto a atividade não estava em primeiro plano, por exemplo a partir de onCreate. Ative-o em onResume e desative-o em onPause.