Este documento descreve as tarefas básicas de NFC que são realizadas no Android. O documento explica como enviar e receber dados NFC no formato de mensagens NDEF e descreve as APIs do framework do Android compatíveis com esses recursos. Para tópicos mais avançados, incluindo uma discussão sobre como trabalhar com dados que não são NDEF, consulte NFC avançada.
A leitura de dados NDEF de uma tag NFC é processada com o sistema de expedição de etiquetas, que analisa tags NFC descobertas, categoriza os dados de forma adequada e inicia um aplicativo interessado nos dados categorizados. Um aplicativo que queira processar a tag NFC lida pode declarar um filtro de intent e solicitar o processamento dos dados.
O sistema de expedição de etiquetas
Dispositivos com tecnologia Android geralmente procuram etiquetas NFC quando a tela está desbloqueada, a não ser que a NFC esteja desativada no menu "Configurações" do dispositivo. Quando um dispositivo com tecnologia Android descobre uma tag NFC, o comportamento esperado é fazer com que a atividade mais apropriada processe o intent sem perguntar ao usuário qual aplicativo usar. Como os dispositivos fazem a leitura das etiquetas NFC em alcances muito curtos, pedir aos usuários que selecionem manualmente uma atividade pode fazer com que afastem o dispositivo da etiqueta, interrompendo a conexão. A atividade precisa ser desenvolvida para processar somente as etiquetas NFC relevantes para sua atividade para impedir que o seletor de atividades seja exibido.
Para ajudar com esse objetivo, o Android fornece um sistema de expedição de etiquetas especial que analisa etiquetas NFC lidas, categoriza-as e tenta localizar aplicativos que têm interesse nos dados digitalizados. Para isso, ele:
- Analisa a tag NFC e descobre o tipo MIME ou um URI que identifica o payload de dados na tag.
- Encapsula o tipo MIME ou o URI e o payload em um intent. Estas duas primeiras etapas são descritas em Como as etiquetas NFC são mapeadas em tipos MIME e URIs.
- Inicia uma atividade com base no intent. Isso é descrito em Como as tags NFC são enviadas para aplicativos.
Como etiquetas NFC são mapeadas em tipos MIME e URIs
Antes de começar a escrever aplicativos NFC, é importante entender os diferentes tipos de etiquetas NFC, a análise de etiquetas NFC feita pelo sistema de expedição de etiquetas e o trabalho especial que o sistema de expedição de etiquetas executa quando detecta uma mensagem NDEF. As tags NFC são compatíveis com uma vasta gama de tecnologias, e é possível gravar dados nelas de diversas maneiras. O Android tem mais compatibilidade com o padrão NDEF, que é definido pelo NFC Forum (link em inglês).
Os dados NDEF são encapsulados em uma mensagem (NdefMessage) que contém um
ou mais registros (NdefRecord). Cada registro NDEF precisa ser formatado corretamente de acordo com
a especificação do tipo de registro que você quer criar. O Android
também oferece suporte a outros tipos de tags que não contêm dados NDEF, e você pode trabalhar com eles usando
as classes no pacote android.nfc.tech. Para saber mais
sobre essas tecnologias, consulte o tópico NFC avançada. Trabalhar com esses outros tipos de tags envolve
criar uma pilha de protocolo própria para se comunicar com as etiquetas. Por isso, recomendamos o uso do NDEF, quando
possível, para facilitar o desenvolvimento e oferecer compatibilidade máxima para dispositivos com tecnologia Android.
Observação:para fazer o download das especificações completas de NDEF, acesse o site Documentos de especificações e aplicações do NFC Forum (link em inglês) e consulte Como criar tipos comuns de registros NDEF para ver exemplos de como construir esses registros.
Agora que você tem alguma experiência com etiquetas NFC, as seções a seguir descrevem mais detalhadamente como
o Android processa etiquetas formatadas em NDEF. Quando um dispositivo Android faz a leitura de uma tag NFC com dados formatados como NDEF, ele analisa a mensagem e tenta descobrir o tipo MIME dos dados ou identificar o URI. Para fazer isso, o sistema lê o primeiro NdefRecord dentro do NdefMessage para determinar como interpretar toda a mensagem NDEF, já que uma mensagem NDEF pode
ter vários registros NDEF. Em uma mensagem NDEF formatada corretamente, o primeiro NdefRecord
contém os seguintes campos:
- Formato de nome de tipo (TNF, na sigla em inglês) de 3 bits
- Indica como interpretar o campo de tipo de comprimento variável. Os valores válidos são descritos na Tabela 1.
- Tipo de comprimento variável
- Descreve o tipo do registro. Se você estiver usando
TNF_WELL_KNOWN, use este campo para especificar a definição de tipo de registro (RTD, na sigla em inglês). Os valores de RTD válidos são descritos na Tabela 2. - ID de comprimento variável
- Um identificador exclusivo para o registro. Esse campo não é usado com frequência, mas, se você precisar identificar uma tag de forma exclusiva, crie um ID para ela.
- Payload de comprimento variável
- O payload real que você quer ler ou gravar. Uma mensagem NDEF pode conter vários registros NDEF. Portanto, não presuma que o payload completo esteja no primeiro registro da mensagem NDEF.
O sistema de expedição de etiquetas usa os campos TNF e de tipo para tentar mapear um tipo MIME ou URI para a
mensagem NDEF. Se bem-sucedido, ele encapsula essas informações dentro de um intent ACTION_NDEF_DISCOVERED com o payload real. No entanto, há casos em que o sistema de expedição de tags não pode determinar o tipo de dados com base no primeiro registro NDEF. Isso acontece quando os dados NDEF não podem ser mapeados para um tipo MIME ou URI ou quando a
tag NFC não contém dados NDEF. Nesses casos, um objeto Tag com informações sobre as tecnologias e o payload da tag é
encapsulado dentro de uma intent ACTION_TECH_DISCOVERED.
A Tabela 1 descreve como o sistema de expedição de etiquetas mapeia campos TNF e de tipo para tipos MIME ou URIs. Ela também descreve quais TNFs não podem ser mapeados para um tipo MIME ou URI.
Nesses casos, o sistema de expedição de tags volta para
ACTION_TECH_DISCOVERED.
Por exemplo, se o sistema de expedição de etiquetas encontrar um registro do tipo TNF_ABSOLUTE_URI, ele mapeará o campo de tipo de comprimento variável desse registro
em um URI. O sistema de expedição de tags encapsula esse URI no campo de dados de uma intent ACTION_NDEF_DISCOVERED com outras informações sobre a tag, como o payload. Por outro lado, se encontrar um registro do tipo TNF_UNKNOWN, ele criará um intent que encapsula as tecnologias da tag.
Tabela 1. TNFs compatíveis e seus mapeamentos
| Formato de nome de tipo (TNF) | Mapeamento |
|---|---|
TNF_ABSOLUTE_URI |
URI com base no campo de tipo. |
TNF_EMPTY |
Volta para ACTION_TECH_DISCOVERED. |
TNF_EXTERNAL_TYPE |
URI com base no URN no campo de tipo. O URN é codificado no campo de tipo NDEF em
uma forma abreviada: <domain_name>:<service_name>.
O Android mapeia isso para um URI no formato:
vnd.android.nfc://ext/<domain_name>:<service_name>. |
TNF_MIME_MEDIA |
Tipo MIME com base no campo de tipo. |
TNF_UNCHANGED |
Quando inválido no primeiro registro, volta para
ACTION_TECH_DISCOVERED. |
TNF_UNKNOWN |
Volta para ACTION_TECH_DISCOVERED. |
TNF_WELL_KNOWN |
Tipo MIME ou URI, dependendo da definição de tipo de registro (RTD, na sigla em inglês), que você define no campo de tipo. Consulte a Tabela 2 para mais informações sobre RDTs disponíveis e seus mapeamentos. |
Tabela 2. RTDs compatíveis com TNF_WELL_KNOWN e seus mapeamentos
| Definição de tipo de registro (RTD) | Mapeamento |
|---|---|
RTD_ALTERNATIVE_CARRIER |
Volta para ACTION_TECH_DISCOVERED. |
RTD_HANDOVER_CARRIER |
Volta para ACTION_TECH_DISCOVERED. |
RTD_HANDOVER_REQUEST |
Volta para ACTION_TECH_DISCOVERED. |
RTD_HANDOVER_SELECT |
Volta para ACTION_TECH_DISCOVERED. |
RTD_SMART_POSTER |
URI com base na análise do payload. |
RTD_TEXT |
Tipo MIME de text/plain. |
RTD_URI |
URI com base no payload. |
Como etiquetas NFC são expedidas para aplicativos
Quando o sistema de expedição de etiquetas termina de criar um intent que encapsula a tag NFC e as informações de identificação dela, ele o envia para um aplicativo interessado que filtra para esse intent. Se mais de um aplicativo puder processar a intent, o seletor de atividades será apresentado para que o usuário possa selecionar a atividade. O sistema de expedição de tags define três intents, que estão listados em ordem de prioridade, da maior para a menor:
-
ACTION_NDEF_DISCOVERED: esse intent é usado para iniciar uma atividade quando uma tag que contém um payload NDEF é lida e é de um tipo reconhecido. Esse é o intent de prioridade mais alta, e o sistema de expedição de tags tenta iniciar uma atividade com ele antes de qualquer outro, sempre que possível.Observação:a partir do Android 16, a leitura de tags NFC que armazenam links de URL (ou seja, o esquema de URI é "htttps://" ou "http://") vai acionar a intent
ACTION_VIEWem vez da intentACTION_NDEF_DISCOVERED. ACTION_TECH_DISCOVERED: se nenhuma atividade estiver registrada para processar o intentACTION_NDEF_DISCOVERED, o sistema de expedição de tags tentará iniciar um aplicativo com este intent. Esse intent também será iniciado diretamente (sem ter que iniciarACTION_NDEF_DISCOVEREDprimeiro) se a etiqueta lida contiver dados NDEF que não podem ser mapeados para um tipo MIME ou URI ou se não contiver dados NDEF, mas tiver uma tecnologia de etiqueta conhecida.ACTION_TAG_DISCOVERED: este intent será iniciado se nenhuma atividade processar os intentsACTION_NDEF_DISCOVEREDouACTION_TECH_DISCOVERED.
O funcionamento básico do sistema de expedição de etiquetas é o seguinte:
- Ele tenta iniciar uma atividade com a intent que foi criada pelo sistema de expedição de tags
ao analisar a tag NFC (
ACTION_NDEF_DISCOVEREDouACTION_TECH_DISCOVERED). - Se nenhuma atividade aplicar um filtro para esse intent, o sistema tentará iniciar uma atividade com o próximo
intent de prioridade mais baixa (
ACTION_TECH_DISCOVEREDouACTION_TAG_DISCOVERED) até que um aplicativo aplique o filtro ou até que o sistema de expedição de tags tente todos os intents possíveis. - Se nenhum aplicativo aplicar um filtro para nenhum dos intents, nada acontecerá.
Sempre que possível, trabalhe com mensagens NDEF e o intent ACTION_NDEF_DISCOVERED, porque ele é o mais específico dos
três. Esse intent permite que o aplicativo seja iniciado em um momento mais oportuno que os outros dois intents, proporcionando uma experiência melhor ao usuário.
Solicitar acesso a NFC no manifesto do Android
Antes de acessar o hardware NFC de um dispositivo e processar corretamente os intents NFC, declare estes
itens no arquivo AndroidManifest.xml:
- O elemento NFC
<uses-permission>para acessar o hardware NFC:<uses-permission android:name="android.permission.NFC" />
- A versão mínima do SDK compatível com o aplicativo. A API de nível 9 só oferece suporte a
expedição limitada de tags por
ACTION_TAG_DISCOVEREDe só dá acesso a mensagens NDEF pelo item extraEXTRA_NDEF_MESSAGES. Nenhuma outra propriedade da tag ou operação de E/S é acessível. A API de nível 10 inclui suporte abrangente de leitura/gravação, além de envio de NDEF em primeiro plano. E a API de nível 14 fornece métodos adicionais de conveniência para criar registros NDEF.<uses-sdk android:minSdkVersion="10"/> - O elemento
uses-featurepara que o aplicativo seja exibido no Google Play apenas para dispositivos com hardware NFC:<uses-feature android:name="android.hardware.nfc" android:required="true" />
Se o aplicativo usa a funcionalidade NFC, mas essa funcionalidade não é crucial, o elemento
uses-featurepode ser omitido e a disponibilidade NFC pode ser verificada no ambiente de execução, verificando segetDefaultAdapter()énull.
Filtro para intents NFC
Para iniciar o aplicativo quando uma tag NFC que você quer processar for lida, o aplicativo
pode filtrar uma, duas ou as três intents NFC no manifesto do Android. No entanto, o recomendado é aplicar um filtro para o intent ACTION_NDEF_DISCOVERED para ter mais controle de quando o aplicativo é iniciado. A intent ACTION_TECH_DISCOVERED é um substituto para ACTION_NDEF_DISCOVERED quando nenhum aplicativo aplica um filtro para
ACTION_NDEF_DISCOVERED ou para quando o payload não é
NDEF. Geralmente, um filtro para ACTION_TAG_DISCOVERED é uma categoria muito genérica de filtro. Muitos aplicativos filtram ACTION_NDEF_DISCOVERED ou ACTION_TECH_DISCOVERED antes de ACTION_TAG_DISCOVERED, de modo que seu aplicativo tem uma baixa probabilidade de
ser iniciado. ACTION_TAG_DISCOVERED está disponível apenas como último recurso
para que os aplicativos filtrem nos casos em que não há outros aplicativos instalados para processar a
intent ACTION_NDEF_DISCOVERED ou ACTION_TECH_DISCOVERED.
Como as implantações de tags NFC variam e muitas vezes não estão sob seu controle, isso nem sempre é possível. Por isso, é possível substituí-lo pelos outros dois intents quando necessário. Quando você tem controle sobre os tipos de tags e dados gravados, é recomendável usar o NDEF para formatar as etiquetas. As seções a seguir descrevem como aplicar um filtro para cada tipo de intent.
ACTION_NDEF_DISCOVERED
Para filtrar intents ACTION_NDEF_DISCOVERED, declare o
filtro de intent com o tipo de dados que você quer filtrar. O
exemplo a seguir aplica um filtro para intents ACTION_NDEF_DISCOVERED
com um tipo MIME de text/plain:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain" /> </intent-filter>
O exemplo a seguir aplica filtro para um URI na forma de
https://developer.android.com/index.html.
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> <data android:scheme="https" android:host="developer.android.com" android:pathPrefix="/index.html" /> </intent-filter>
ACTION_TECH_DISCOVERED
Se a atividade aplicar filtro para o intent ACTION_TECH_DISCOVERED,
é preciso criar um arquivo de recurso XML que especifique as tecnologias compatíveis com a atividade
em um conjunto tech-list. A atividade será
considerada uma correspondência se um conjunto tech-list for um subconjunto das tecnologias que são
compatíveis com a tag, que pode ser obtida chamando getTechList().
Por exemplo, se a tag lida for compatível com MifareClassic, NdefFormatable e NfcA, o conjunto tech-list precisará especificar todas as três, duas ou uma das tecnologias (e nada mais) para que a atividade seja correspondida.
O exemplo a seguir define todas as tecnologias. Remova os que não são
compatíveis com a tag NFC. Salve este arquivo na pasta <project-root>/res/xml. O arquivo pode ser nomeado da maneira que você quiser.
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.IsoDep</tech> <tech>android.nfc.tech.NfcA</tech> <tech>android.nfc.tech.NfcB</tech> <tech>android.nfc.tech.NfcF</tech> <tech>android.nfc.tech.NfcV</tech> <tech>android.nfc.tech.Ndef</tech> <tech>android.nfc.tech.NdefFormatable</tech> <tech>android.nfc.tech.MifareClassic</tech> <tech>android.nfc.tech.MifareUltralight</tech> </tech-list> </resources>
Também é possível especificar vários conjuntos tech-list. Cada um dos conjuntos tech-list
é considerado de forma independente, e a atividade é considerada uma correspondência se qualquer conjunto
tech-list for um subconjunto das tecnologias retornadas por getTechList(). Isso fornece semânticas AND e OR
para tecnologias correspondentes. O exemplo a seguir combina etiquetas que podem ser compatíveis com as tecnologias NfcA e Ndef ou com as tecnologias NfcB e Ndef:
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.NfcA</tech> <tech>android.nfc.tech.Ndef</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcB</tech> <tech>android.nfc.tech.Ndef</tech> </tech-list> </resources>
No arquivo AndroidManifest.xml, especifique o arquivo de recurso que você acabou de criar
no elemento <meta-data> dentro do elemento
<activity>, como no exemplo a seguir:
<activity> ... <intent-filter> <action android:name="android.nfc.action.TECH_DISCOVERED"/> </intent-filter> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" /> ... </activity>
Para mais informações sobre como trabalhar com tecnologias de tag e o intent ACTION_TECH_DISCOVERED, consulte Trabalhar com tecnologias de tag
compatíveis no documento de NFC avançada.
ACTION_TAG_DISCOVERED
Para filtrar ACTION_TAG_DISCOVERED, use o seguinte filtro de
intent:
<intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED"/> </intent-filter>
ACTION_VIEW
A partir do Android 16, a leitura de tags NFC que armazenam links de URL vai acionar a intent ACTION_VIEW. Para filtrar ACTION_VIEW,
consulte this. Use Android app links para abrir o app para o URL.
Receber informações de intents
Se uma atividade iniciar devido a um intent NFC, é possível receber informações sobre a tag NFC lida pelo intent. Os intents podem conter os seguintes extras, dependendo da etiqueta que for lida:
EXTRA_TAG(obrigatório): um objetoTagque representa a tag lida.EXTRA_NDEF_MESSAGES(opcional): uma matriz de mensagens NDEF analisadas a partir da tag. Este extra é obrigatório em intentsACTION_NDEF_DISCOVERED.EXTRA_ID(opcional): o ID de nível inferior da etiqueta.
Para ter esses extras, verifique se a atividade foi iniciada com um dos
intents NFC para garantir que uma tag foi lida e, em seguida, pegue os extras a partir do
intent. O exemplo a seguir verifica a intent ACTION_NDEF_DISCOVERED
e recebe as mensagens NDEF de um intent extra.
Kotlin
override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) ... if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action) { intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)?.also { rawMessages -> val messages: List<NdefMessage> = rawMessages.map { it as NdefMessage } // Process the messages array. ... } } }
Java
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); ... if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) { Parcelable[] rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if (rawMessages != null) { NdefMessage[] messages = new NdefMessage[rawMessages.length]; for (int i = 0; i < rawMessages.length; i++) { messages[i] = (NdefMessage) rawMessages[i]; } // Process the messages array. ... } } }
Como alternativa, é possível receber um objeto Tag do intent, que
conterá o payload e permitirá a enumeração das tecnologias da tag:
Kotlin
val tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
Java
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Criar tipos comuns de registros NDEF
Esta seção descreve como criar tipos comuns de registros NDEF para ajudar você a gravar em
etiquetas NFC. A partir do Android 4.0 (nível 14 da API), o
método createUri() está disponível para ajudar você a criar
registros de URI automaticamente. A partir do Android 4.1 (nível 16 da API),
createExternal()
e createMime() estão disponíveis para ajudar você a criar
registros NDEF de tipo MIME e externo. Use esses métodos auxiliares sempre que possível para evitar erros
ao criar registros NDEF manualmente.
Esta seção também descreve como criar o filtro de intent correspondente para o registro. Todos esses exemplos de registro NDEF precisam estar no primeiro registro da mensagem NDEF que você está gravando em uma tag.
TNF_ABSOLUTE_URI
Observação:recomendamos o uso do
tipo RTD_URI em vez
de TNF_ABSOLUTE_URI, porque ele é mais eficiente.
Um registro NDEF TNF_ABSOLUTE_URI pode ser criado da seguinte maneira:
Kotlin
val uriRecord = ByteArray(0).let { emptyByteArray -> NdefRecord( TNF_ABSOLUTE_URI, "https://developer.android.com/index.html".toByteArray(Charset.forName("US-ASCII")), emptyByteArray, emptyByteArray ) }
Java
NdefRecord uriRecord = new NdefRecord( NdefRecord.TNF_ABSOLUTE_URI , "https://developer.android.com/index.html".getBytes(Charset.forName("US-ASCII")), new byte[0], new byte[0]);
O filtro de intent do registro NDEF anterior ficaria assim:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="https" android:host="developer.android.com" android:pathPrefix="/index.html" /> </intent-filter>
TNF_MIME_MEDIA
Um registro NDEF TNF_MIME_MEDIA pode ser criado das seguintes maneiras:
Usando o método createMime():
Kotlin
val mimeRecord = NdefRecord.createMime( "application/vnd.com.example.android.beam", "Beam me up, Android".toByteArray(Charset.forName("US-ASCII")) )
Java
NdefRecord mimeRecord = NdefRecord.createMime("application/vnd.com.example.android.beam", "Beam me up, Android".getBytes(Charset.forName("US-ASCII")));
Criando o NdefRecord manualmente:
Kotlin
val mimeRecord = Charset.forName("US-ASCII").let { usAscii -> NdefRecord( NdefRecord.TNF_MIME_MEDIA, "application/vnd.com.example.android.beam".toByteArray(usAscii), ByteArray(0), "Beam me up, Android!".toByteArray(usAscii) ) }
Java
NdefRecord mimeRecord = new NdefRecord( NdefRecord.TNF_MIME_MEDIA , "application/vnd.com.example.android.beam".getBytes(Charset.forName("US-ASCII")), new byte[0], "Beam me up, Android!".getBytes(Charset.forName("US-ASCII")));
O filtro de intent do registro NDEF anterior ficaria assim:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="application/vnd.com.example.android.beam" /> </intent-filter>
TNF_WELL_KNOWN com RTD_TEXT
Um registro NDEF TNF_WELL_KNOWN pode ser criado da seguinte maneira:
Kotlin
fun createTextRecord(payload: String, locale: Locale, encodeInUtf8: Boolean): NdefRecord { val langBytes = locale.language.toByteArray(Charset.forName("US-ASCII")) val utfEncoding = if (encodeInUtf8) Charset.forName("UTF-8") else Charset.forName("UTF-16") val textBytes = payload.toByteArray(utfEncoding) val utfBit: Int = if (encodeInUtf8) 0 else 1 shl 7 val status = (utfBit + langBytes.size).toChar() val data = ByteArray(1 + langBytes.size + textBytes.size) data[0] = status.toByte() System.arraycopy(langBytes, 0, data, 1, langBytes.size) System.arraycopy(textBytes, 0, data, 1 + langBytes.size, textBytes.size) return NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, ByteArray(0), data) }
Java
public NdefRecord createTextRecord(String payload, Locale locale, boolean encodeInUtf8) { byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII")); Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16"); byte[] textBytes = payload.getBytes(utfEncoding); int utfBit = encodeInUtf8 ? 0 : (1 << 7); char status = (char) (utfBit + langBytes.length); byte[] data = new byte[1 + langBytes.length + textBytes.length]; data[0] = (byte) status; System.arraycopy(langBytes, 0, data, 1, langBytes.length); System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length); NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data); return record; }
O filtro de intent do registro NDEF anterior ficaria assim:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter>
TNF_WELL_KNOWN com RTD_URI
Um registro NDEF TNF_WELL_KNOWN pode ser criado das seguintes maneiras:
Usando o método createUri(String):
Kotlin
val rtdUriRecord1 = NdefRecord.createUri("https://example.com")
Java
NdefRecord rtdUriRecord1 = NdefRecord.createUri("https://example.com");
Usando o método createUri(Uri):
Kotlin
val rtdUriRecord2 = Uri.parse("https://example.com").let { uri -> NdefRecord.createUri(uri) }
Java
Uri uri = Uri.parse("https://example.com"); NdefRecord rtdUriRecord2 = NdefRecord.createUri(uri);
Criando o NdefRecord manualmente:
Kotlin
val uriField = "example.com".toByteArray(Charset.forName("US-ASCII")) val payload = ByteArray(uriField.size + 1) //add 1 for the URI Prefix payload [0] = 0x01 //prefixes https://www. to the URI System.arraycopy(uriField, 0, payload, 1, uriField.size) //appends URI to payload val rtdUriRecord = NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, ByteArray(0), payload)
Java
byte[] uriField = "example.com".getBytes(Charset.forName("US-ASCII")); byte[] payload = new byte[uriField.length + 1]; //add 1 for the URI Prefix payload[0] = 0x01; //prefixes https://www. to the URI System.arraycopy(uriField, 0, payload, 1, uriField.length); //appends URI to payload NdefRecord rtdUriRecord = new NdefRecord( NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], payload);
O filtro de intent do registro NDEF anterior ficaria assim:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="https" android:host="example.com" android:pathPrefix="" /> </intent-filter>
TNF_EXTERNAL_TYPE
É possível criar um registro NDEF TNF_EXTERNAL_TYPE das seguintes
maneiras:
Usando o método createExternal():
Kotlin
var payload: ByteArray //assign to your data val domain = "com.example" //usually your app's package name val type = "externalType" val extRecord = NdefRecord.createExternal(domain, type, payload)
Java
byte[] payload; //assign to your data String domain = "com.example"; //usually your app's package name String type = "externalType"; NdefRecord extRecord = NdefRecord.createExternal(domain, type, payload);
Criando o NdefRecord manualmente:
Kotlin
var payload: ByteArray ... val extRecord = NdefRecord( NdefRecord.TNF_EXTERNAL_TYPE, "com.example:externalType".toByteArray(Charset.forName("US-ASCII")), ByteArray(0), payload )
Java
byte[] payload; ... NdefRecord extRecord = new NdefRecord( NdefRecord.TNF_EXTERNAL_TYPE, "com.example:externalType".getBytes(Charset.forName("US-ASCII")), new byte[0], payload);
O filtro de intent do registro NDEF anterior ficaria assim:
<intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="vnd.android.nfc" android:host="ext" android:pathPrefix="/com.example:externalType"/> </intent-filter>
Use TNF_EXTERNAL_TYPE para implantações mais genéricas de tags NFC para oferecer melhor compatibilidade para dispositivos com tecnologia Android e sem.
Observação: as URNs para TNF_EXTERNAL_TYPE têm um formato canônico de urn:nfc:ext:example.com:externalType, mas a especificação RTD do NFC Forum declara que a parte urn:nfc:ext: da URN precisa ser omitida do registro NDEF. Portanto, tudo o que é preciso fornecer é o domínio (example.com no exemplo)
e o tipo (externalType no exemplo), separados por dois pontos.
Ao enviar TNF_EXTERNAL_TYPE, o Android converte o URN urn:nfc:ext:example.com:externalType
em um URI vnd.android.nfc://ext/example.com:externalType, que é o que o
filtro de intent no exemplo declara.
Registros do aplicativo para Android
Introduzido no Android 4.0 (nível 14 da API), um Android Application Record (AAR) fornece uma garantia maior de que o aplicativo será iniciado quando uma tag NFC for lida. Um AAR tem o nome do pacote de um aplicativo incorporado em um registro NDEF. É possível adicionar um AAR a qualquer registro NDEF da sua mensagem NDEF porque o Android procura AARs por toda a mensagem. Se encontrar um AAR, ele vai iniciar o aplicativo com base no nome do pacote dentro do AAR. Se o aplicativo não estiver presente no dispositivo, o Google Play será iniciado para fazer o download do aplicativo.
Os AARs são úteis se você quiser impedir que outros aplicativos filtrem a mesma intent e possivelmente processem tags específicas que você implantou. Os AARs são suportados apenas no nível do aplicativo (por causa da restrição do nome do pacote) e não no nível da atividade como filtros de intents. Se quiser processar um intent no nível da atividade, use os filtros de intent.
Se uma etiqueta contiver um AAR, o sistema de expedição de etiquetas fará a expedição da seguinte maneira:
- Ele tentará iniciar uma atividade usando um filtro de intent normalmente. Se a atividade que corresponde à intent também corresponder ao AAR, inicie a atividade.
- Se a atividade que aplica o filtro para o intent não corresponder ao AAR, se várias atividades puderem processar o intent ou se nenhuma atividade processar o intent, ele vai iniciar o aplicativo especificado pelo AAR.
- Se nenhum aplicativo for iniciado com o AAR, ele acessará o Google Play para fazer o download do aplicativo com base no AAR.
Observação:você pode substituir os AARs e o sistema de expedição de intents pelo sistema de expedição em primeiro plano, que permite que uma atividade em primeiro plano tenha prioridade quando uma tag NFC é descoberta. Com esse método, a atividade precisa estar em primeiro plano para modificar os AARs e o sistema de expedição de intents.
Se ainda quiser filtrar as tags lidas que não contêm um AAR, declare os filtros de intent normalmente. Isso é útil se o aplicativo estiver interessado em outras tags que não contêm um AAR. Por exemplo, talvez você queira garantir que o aplicativo processe etiquetas reservadas implantadas por você, além de etiquetas gerais implantadas por terceiros. Os AARs são específicos para dispositivos Android 4.0 ou mais recentes. Portanto, ao implantar tags, é recomendável usar uma combinação de AARs e tipos MIME/URI para garantir a compatibilidade com uma maior gama de dispositivos. Além disso, ao implantar etiquetas NFC, pense em como você quer gravar as etiquetas para oferecer suporte à maioria dos dispositivos (com tecnologia Android e outros dispositivos). Para isso, defina um tipo MIME ou URI relativamente único para facilitar a diferenciação pelos aplicativos.
O Android fornece uma API simples para criar um AAR,
createApplicationRecord(). Tudo o que você precisa
fazer é incorporar o AAR em qualquer lugar no NdefMessage. Não use
o primeiro registro do NdefMessage, a menos que o AAR seja o único
registro no NdefMessage. Isso ocorre porque o sistema
Android verifica o primeiro registro de um NdefMessage para determinar o tipo MIME ou
URI da tag, que é usado para criar um intent para que os aplicativos filtrem. O código abaixo
mostra como criar um AAR:
Kotlin
val msg = NdefMessage( arrayOf( ..., NdefRecord.createApplicationRecord("com.example.android.beam") ) )
Java
NdefMessage msg = new NdefMessage( new NdefRecord[] { ..., NdefRecord.createApplicationRecord("com.example.android.beam")} ); )
Lista de permissões de apps para leitura de tags NFC
A partir do Android 16, os usuários são notificados quando um app recebe a primeira intent NFC para ler tags NFC. O usuário tem a opção de impedir que o app leia tags NFC na notificação.
- Os apps podem verificar se
o usuário permitiu que o app leia tags NFC usando
NfcAdapter.isTagIntentAllowed(). - Os apps podem pedir ao usuário para permitir a leitura de tags NFC novamente enviando a intent
ACTION_CHANGE_TAG_INTENT_PREFERENCE.
Observação:a lista de permissões do app de leitura de tags NFC pode ser acessada em Settings > Apps > Special app access > Launch via NFC.