Questo documento descrive argomenti NFC avanzati, ad esempio l'utilizzo di varie tecnologie di tag, la scrittura in tag NFC e l'invio in primo piano, che consente a un'applicazione in primo piano di gestire gli intent anche quando altre applicazioni filtrano gli stessi.
Utilizzo delle tecnologie di tag supportate
Quando si utilizzano tag NFC e dispositivi Android, il formato principale utilizzato per leggere
e scrivere dati sui tag è NDEF. Quando un dispositivo analizza un tag con dati NDEF, Android supporta l'analisi del messaggio e la relativa consegna in un NdefMessage
, se possibile. Tuttavia, esistono casi in cui esegui la scansione di un tag che non contiene dati NDEF o non è stato possibile mappare i dati NDEF a un tipo o URI MIME.
In questi casi, devi aprire la comunicazione direttamente con il tag e leggere e scrivere usando il tuo protocollo (in byte non elaborati). Android fornisce un supporto generico per questi casi d'uso con il pacchetto android.nfc.tech
, descritto nella Tabella 1. Puoi
utilizzare il metodo getTechList()
per determinare le tecnologie
supportate dal tag e creare l'oggetto TagTechnology
corrispondente con una delle classi fornite da android.nfc.tech
Classe | Descrizione |
---|---|
TagTechnology |
L'interfaccia che tutte le classi di tecnologia tag devono implementare. |
NfcA |
Consente di accedere alle proprietà NFC-A (ISO 14443-3A) e alle operazioni di I/O. |
NfcB |
Consente di accedere alle proprietà NFC-B (ISO 14443-3B) e alle operazioni di I/O. |
NfcF |
Consente di accedere alle proprietà NFC-F (JIS 6319-4) e alle operazioni di I/O. |
NfcV |
Consente di accedere alle proprietà NFC-V (ISO 15693) e alle operazioni di I/O. |
IsoDep |
Consente di accedere alle proprietà ISO-DEP (ISO 14443-4) e alle operazioni di I/O. |
Ndef |
Consente di accedere ai dati NDEF e alle operazioni sui tag NFC formattati come NDEF. |
NdefFormatable |
Fornisce operazioni di formattazione per i tag che possono essere formattabili NDEF. |
I dispositivi con piattaforma Android non richiedono il supporto delle seguenti tecnologie di tag.
Classe | Descrizione |
---|---|
MifareClassic |
Fornisce l'accesso alle proprietà MIFARE Classic e alle operazioni di I/O, se questo dispositivo Android supporta MIFARE. |
MifareUltralight |
Consente di accedere alle proprietà MIFARE Ultralight e alle operazioni di I/O, se questo dispositivo Android supporta MIFARE. |
Utilizzare le tecnologie di tag e l'intent ACTION_TECH_DISCOVERED
Quando un dispositivo analizza un tag contenente dati NDEF, ma non è stato possibile mappare a un MIME o un URI, il sistema di invio dei tag tenta di avviare un'attività con l'intent ACTION_TECH_DISCOVERED
. ACTION_TECH_DISCOVERED
viene utilizzato anche quando viene scansionato un tag con dati non NDEF. Questo tipo di riserva ti consente di lavorare direttamente con i dati nel tag se il sistema di invio dei tag non è riuscito ad analizzarlo per te. I passaggi di base per l'utilizzo
delle tecnologie di tag sono i seguenti:
- Filtra per un intent
ACTION_TECH_DISCOVERED
che specifica le tecnologie di tag che vuoi gestire. Per ulteriori informazioni, consulta Filtro per intent NFC. In generale, il sistema di invio dei tag tenta di avviare un intentACTION_TECH_DISCOVERED
quando un messaggio NDEF non può essere mappato a un tipo o URI MIME o se il tag analizzato non conteneva dati NDEF. Per ulteriori informazioni su come questo viene determinato, consulta la sezione Il sistema di invio dei tag. - Quando l'applicazione riceve l'intent, recupera l'oggetto
Tag
dall'intent:Kotlin
var tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
Java
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
- Per ottenere un'istanza di
TagTechnology
, chiama uno dei metodi di fabbricaget
delle classi nel pacchettoandroid.nfc.tech
. Puoi enumerare le tecnologie supportate del tag chiamandogetTechList()
prima di chiamare un metodo di fabbricaget
. Ad esempio, per ottenere un'istanza diMifareUltralight
da unTag
, procedi nel seguente modo:Kotlin
MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG))
Java
MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
Lettura e scrittura nei tag
La lettura e la scrittura in un tag NFC implica l'ottenimento del tag dall'intent e l'apertura della comunicazione con il tag. Devi definire uno stack di protocollo personalizzato per leggere e scrivere dati nel tag. Tuttavia, tieni presente che puoi comunque leggere e scrivere dati NDEF quando lavori direttamente con un tag. Spetta a te decidere come strutturare le cose. L'esempio riportato di seguito mostra come utilizzare un tag 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; } }
Utilizza il sistema di tracciamento in primo piano
Il sistema di invio in primo piano consente a un'attività di intercettare un intent e rivendicare la priorità rispetto ad altre attività che gestiscono lo stesso intento. L'utilizzo di questo sistema comporta la creazione di alcune strutture di dati affinché il sistema Android possa inviare gli intent appropriati alla tua applicazione. Per attivare il sistema di tracciamento in primo piano:
- Aggiungi il seguente codice nel metodo
onCreate()
della tua attività:- Crea un oggetto
PendingIntent
modificabile in modo che il sistema Android possa completarlo con i dettagli del tag quando viene scansionato.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);
- Dichiara i filtri per intent per gestire gli intent che vuoi intercettare. Il sistema di invio in primo piano controlla i filtri per intent specificati con l'intent ricevuto quando il dispositivo analizza un tag. Se corrisponde, l'applicazione gestisce l'intent. Se non corrisponde, il sistema di invio in primo piano utilizza il sistema di invio degli intent.
Se specifichi un array
null
di filtri per intent e filtri tecnologici, specifichi che vuoi filtrare tutti i tag di riserva all'intentTAG_DISCOVERED
. Lo snippet di codice riportato di seguito gestisce tutti i tipi MIME perNDEF_DISCOVERED
. Dovresti gestire solo quelli di cui hai bisogno.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, };
- Configura una serie di tecnologie di tag che l'applicazione vuole gestire. Chiama il metodo
Object.class.getName()
per ottenere la classe della tecnologia che vuoi supportare.Kotlin
techListsArray = arrayOf(arrayOf<String>(NfcF::class.java.name))
Java
techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
- Crea un oggetto
- Esegui l'override dei seguenti callback del ciclo di vita delle attività e aggiungi la logica per abilitare e disabilitare l'invio in primo piano quando l'attività perde (
onPause()
) e riprende lo stato attivo (onResume()
).enableForegroundDispatch()
deve essere chiamato dal thread principale e solo quando l'attività è in primo piano (la chiamata inonResume()
lo garantisce). Devi inoltre implementare il callbackonNewIntent
per elaborare i dati provenienti dal tag NFC scansionato.
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 }