Este documento descreve tópicos avançados de NFC, como trabalhar com várias tecnologias de etiqueta, gravação em etiquetas NFC e envio em primeiro plano, o que permite que um aplicativo em primeiro plano processar intents mesmo quando outros aplicativos filtram as mesmas.
Trabalhar com tecnologias de etiqueta compatíveis
Ao trabalhar com etiquetas NFC e dispositivos com tecnologia Android, o principal formato usado para leitura
e gravar dados nas tags é NDEF. Quando um dispositivo lê uma etiqueta com dados NDEF, o Android oferece suporte
na análise da mensagem e na entrega dela em uma NdefMessage
quando
sempre que possível. No entanto, há casos em que você verifica uma tag que não contém
Dados NDEF ou quando não foi possível mapear os dados NDEF para um tipo MIME ou URI.
Nesses casos, você precisa abrir a comunicação diretamente com a tag e ler e gravar nela usando o
seu próprio protocolo (em bytes brutos). O Android oferece suporte genérico para esses casos de uso com as
android.nfc.tech
, descrito na Tabela 1. Você pode
usar o método getTechList()
para determinar as tecnologias
compatíveis com a tag e crie o parâmetro TagTechnology
objeto com uma das classes fornecidas pelo android.nfc.tech
Classe | Descrição |
---|---|
TagTechnology |
A interface que todas as classes de tecnologia de etiquetas precisam implementar. |
NfcA |
Fornece acesso às propriedades NFC-A (ISO 14443-3A) e operações de E/S. |
NfcB |
Fornece acesso às propriedades NFC-B (ISO 14443-3B) e operações de E/S. |
NfcF |
Fornece acesso às propriedades da NFC-F (JIS 6319-4) e operações de E/S. |
NfcV |
Fornece acesso às propriedades NFC-V (ISO 15693) e operações de E/S. |
IsoDep |
Fornece acesso às propriedades ISO-DEP (ISO 14443-4) e operações de E/S. |
Ndef |
Fornece acesso a dados e operações NDEF em etiquetas NFC que foram formatadas como NDEF |
NdefFormatable |
Fornece operações de formato para etiquetas que podem ser formatadas como NDEF. |
As seguintes tecnologias de tag não precisam ser compatíveis com dispositivos Android.
Classe | Descrição |
---|---|
MifareClassic |
Fornece acesso a propriedades MIFARE Classic e operações de E/S, se este dispositivo Android suporta MIFARE. |
MifareUltralight |
Fornece acesso a propriedades MIFARE Ultralight e operações de E/S, se este dispositivo dispositivo suporta MIFARE. |
Trabalhando com tecnologias de etiqueta e com o intent ACTION_TECH_DISCOVERED
Quando um dispositivo lê uma etiqueta que contém dados NDEF, mas que não pôde ser mapeada para um MIME ou URI,
o sistema de expedição de tags tenta iniciar uma atividade com o ACTION_TECH_DISCOVERED
.
intenção. O ACTION_TECH_DISCOVERED
também é usado quando uma tag
com dados não NDEF são lidos. Com esse substituto, você pode trabalhar com os dados na tag
diretamente se o sistema de expedição de etiquetas não puder analisá-lo para você. As etapas básicas para trabalhar com
de tags são as seguintes:
- Filtre por uma intent
ACTION_TECH_DISCOVERED
especificando o tecnologias de tags que você quer usar. Consulte Como filtrar para NFC intents para mais informações. Em geral, o sistema de expedição de etiquetas tenta iniciar um intentACTION_TECH_DISCOVERED
quando uma mensagem NDEF não pode ser mapeada para um tipo MIME ou URI ou se a etiqueta lida não contiver dados NDEF. Para mais informações sobre como isso é determinado, consulte Sistema de expedição de etiquetas. - Quando o app receber a intent, extraia o objeto
Tag
do a intent:Kotlin
var tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
Java
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
- Consiga uma instância de um
TagTechnology
chamando um dos Métodos de fábricaget
das classes no pacoteandroid.nfc.tech
. Você pode Enumerar as tecnologias com suporte da tag chamandogetTechList()
antes de chamar um método de fábricaget
. Por exemplo, para receber uma instância deMifareUltralight
em umTag
, faça o seguinte:Kotlin
MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG))
Java
MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
Ler e gravar em etiquetas
Ler e gravar em uma tag NFC envolve obter a etiqueta da intenção e abrindo a comunicação com a tag. Você precisa definir sua própria pilha de protocolos para ler e gravar dados à tag. No entanto, lembre-se de que ainda é possível ler e gravar dados NDEF ao trabalhar com diretamente com uma tag. Cabe a você decidir como quer estruturar as coisas. A exemplo a seguir mostra como trabalhar com uma etiqueta MIFARE Ultralight.
Kotlin
package com.example.android.nfc import android.nfc.Tag import android.nfc.tech.MifareUltralight import java.io.IOException import java.nio.charset.Charset class MifareUltralightTagTester { fun writeTag(tag: Tag, tagText: String) { MifareUltralight.get(tag)?.use { ultralight -> ultralight.connect() Charset.forName("US-ASCII").also { usAscii -> ultralight.writePage(4, "abcd".toByteArray(usAscii)) ultralight.writePage(5, "efgh".toByteArray(usAscii)) ultralight.writePage(6, "ijkl".toByteArray(usAscii)) ultralight.writePage(7, "mnop".toByteArray(usAscii)) } } } fun readTag(tag: Tag): String? { return MifareUltralight.get(tag)?.use { mifare -> mifare.connect() val payload = mifare.readPages(4) String(payload, Charset.forName("US-ASCII")) } } }
Java
package com.example.android.nfc; import android.nfc.Tag; import android.nfc.tech.MifareUltralight; import android.util.Log; import java.io.IOException; import java.nio.charset.Charset; public class MifareUltralightTagTester { private static final String TAG = MifareUltralightTagTester.class.getSimpleName(); public void writeTag(Tag tag, String tagText) { MifareUltralight ultralight = MifareUltralight.get(tag); try { ultralight.connect(); ultralight.writePage(4, "abcd".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(5, "efgh".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(6, "ijkl".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(7, "mnop".getBytes(Charset.forName("US-ASCII"))); } catch (IOException e) { Log.e(TAG, "IOException while writing MifareUltralight...", e); } finally { try { ultralight.close(); } catch (IOException e) { Log.e(TAG, "IOException while closing MifareUltralight...", e); } } } public String readTag(Tag tag) { MifareUltralight mifare = MifareUltralight.get(tag); try { mifare.connect(); byte[] payload = mifare.readPages(4); return new String(payload, Charset.forName("US-ASCII")); } catch (IOException e) { Log.e(TAG, "IOException while reading MifareUltralight message...", e); } finally { if (mifare != null) { try { mifare.close(); } catch (IOException e) { Log.e(TAG, "Error closing tag...", e); } } } return null; } }
Usar o sistema de expedição em primeiro plano
O sistema de expedição em primeiro plano permite que uma atividade intercepte uma intent e uma reivindicação prioridade sobre outras atividades que processam a mesma intent. O uso desse sistema envolve construir algumas estruturas de dados para que o sistema Android seja capaz de enviar as mensagens intents ao seu aplicativo. Para ativar o sistema de expedição em primeiro plano:
- Adicione o código abaixo ao método
onCreate()
da sua atividade:- Criar um objeto
PendingIntent
mutável para que o sistema Android possa preenchê-lo com os detalhes da etiqueta quando ela for lida.Kotlin
val intent = Intent(this, javaClass).apply { addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) } var pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE)
Java
PendingIntent pendingIntent = PendingIntent.getActivity( this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE);
- Declare os filtros de intent para processar os intents que você quer interceptar. Em primeiro plano
o sistema de expedição verifica os filtros de intents especificados com a intenção recebida quando
o dispositivo verifica a tag. Se corresponderem, o aplicativo processará o intent. Se isso acontecer,
não correspondem, o sistema de expedição em primeiro plano volta para o sistema de expedição de intents.
Especificar uma matriz
null
de filtros de intent e de tecnologia. que você quer filtrar para todas as tags substitutas paraTAG_DISCOVERED
intenção. O snippet de código abaixo processa todos os tipos MIME paraNDEF_DISCOVERED
. Você deve processar apenas aqueles de que você precisa.Kotlin
val ndef = IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply { try { addDataType("*/*") /* Handles all MIME based dispatches. You should specify only the ones that you need. */ } catch (e: IntentFilter.MalformedMimeTypeException) { throw RuntimeException("fail", e) } } intentFiltersArray = arrayOf(ndef)
Java
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); try { ndef.addDataType("*/*"); /* Handles all MIME based dispatches. You should specify only the ones that you need. */ } catch (MalformedMimeTypeException e) { throw new RuntimeException("fail", e); } intentFiltersArray = new IntentFilter[] {ndef, };
- Configurar uma matriz de tecnologias de etiqueta que o aplicativo quer processar. Chame o método
Object.class.getName()
para extrair a classe da tecnologia que você que queremos apoiar.Kotlin
techListsArray = arrayOf(arrayOf<String>(NfcF::class.java.name))
Java
techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
- Criar um objeto
- Substitua os seguintes callbacks do ciclo de vida da atividade e adicione lógica para ativar e desativar os
envio em primeiro plano quando a atividade perde (
onPause()
) e recupera o foco (onResume()
).enableForegroundDispatch()
precisa ser chamado de na linha de execução principal e somente quando a atividade estiver em primeiro plano (chamaronResume()
garante isso). Também é necessário implementar o callbackonNewIntent
para processar os dados da NFC lida. tag.
Kotlin
public override fun onPause() { super.onPause() adapter.disableForegroundDispatch(this) } public override fun onResume() { super.onResume() adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray) } public override fun onNewIntent(intent: Intent) { val tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG) // do something with tagFromIntent }
Java
public void onPause() { super.onPause(); adapter.disableForegroundDispatch(this); } public void onResume() { super.onResume(); adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray); } public void onNewIntent(Intent intent) { Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); // do something with tagFromIntent }