Questo documento descrive gli argomenti NFC avanzati, ad esempio l'utilizzo di varie tecnologie di tag, la scrittura nei tag NFC e l'invio in primo piano, consentendo a un'applicazione in primo piano di gestire gli intent anche quando altre applicazioni filtrano in base agli stessi criteri.
Utilizzare le tecnologie di tag supportate
Quando lavori con tag NFC e dispositivi Android, il formato principale utilizzato per leggere
e scrivere dati sui tag è NDEF. Quando un dispositivo scansiona un tag con dati NDEF, Android fornisce assistenza.
durante l'analisi del messaggio e la sua consegna in un NdefMessage
quando
possibile. Esistono casi, tuttavia, che quando esegui la scansione di un tag che non contiene
Dati NDEF o quando non è stato possibile mappare i dati NDEF a un tipo o a un URI MIME.
In questi casi, devi aprire la comunicazione direttamente con il tag, leggere e scrivere utilizzando
il tuo protocollo (in byte non elaborati). Android fornisce assistenza generica per questi casi d'uso con
android.nfc.tech
, come descritto nella Tabella 1. Puoi
usano il metodo getTechList()
per determinare le tecnologie
supportato dal tag e crea il valore TagTechnology
corrispondente
con una delle classi fornite da android.nfc.tech
Classe | Descrizione |
---|---|
TagTechnology |
L'interfaccia che tutte le classi di tecnologia dei tag devono implementare. |
NfcA |
Fornisce l'accesso alle proprietà NFC-A (ISO 14443-3A) e alle operazioni di I/O. |
NfcB |
Fornisce l'accesso alle proprietà NFC-B (ISO 14443-3B) e alle operazioni di I/O. |
NfcF |
Fornisce l'accesso alle proprietà NFC-F (JIS 6319-4) e alle operazioni di I/O. |
NfcV |
Fornisce l'accesso alle proprietà NFC-V (ISO 15693) e alle operazioni di I/O. |
IsoDep |
Fornisce l'accesso alle proprietà ISO-DEP (ISO 14443-4) e alle operazioni di I/O. |
Ndef |
Fornisce l'accesso ai dati e alle operazioni NDEF sui tag NFC che sono stati formattati come NDEF. |
NdefFormatable |
Fornisce operazioni di formattazione per i tag che possono essere formattabili NDEF. |
Le seguenti tecnologie di tag non devono essere supportate dai dispositivi Android.
Classe | Descrizione |
---|---|
MifareClassic |
Fornisce l'accesso alle proprietà MIFARE Classic e alle operazioni di I/O, se questo dispositivo Android supporta MIFARE. |
MifareUltralight |
Fornisce l'accesso alle proprietà MIFARE Ultralight e alle operazioni di I/O, se questo Android supporta MIFARE. |
Utilizzare le tecnologie di tag e l'intent ACTION_TECH_DISCOVERED
Quando un dispositivo analizza un tag che contiene dati NDEF, ma che non è stato possibile mappare a un MIME o un URI,
il sistema di invio dei tag prova ad avviare un'attività con ACTION_TECH_DISCOVERED
l'intento. ACTION_TECH_DISCOVERED
viene utilizzato anche quando un tag
con dati non NDEF. Questa opzione di riserva ti consente di lavorare con i dati sul tag
direttamente se il sistema di invio dei tag non è riuscito ad analizzarli. I passaggi di base quando si utilizza
tecnologie di tag sono le seguenti:
- Filtra in base a un intent
ACTION_TECH_DISCOVERED
che specifica le tecnologie di tag che vuoi gestire. Consulta la sezione Filtri per NFC intent per ulteriori informazioni. In generale, il sistema di invio dei tag prova ad avviare un intentACTION_TECH_DISCOVERED
quando un messaggio NDEF non può essere mappato a un URI o un tipo MIME oppure se il tag analizzato non conteneva dati NDEF. Per Per ulteriori informazioni su come determinare questo comportamento, consulta la sezione The Tag Dispatch System. - Quando l'applicazione riceve l'intent, ottieni l'oggetto
Tag
da l'intento:Kotlin
var tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
Java
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
- Recupera l'istanza di un
TagTechnology
, chiamando uno deiget
metodi di fabbrica delle classi nel pacchettoandroid.nfc.tech
. Puoi enumera le tecnologie supportate del tag chiamandogetTechList()
prima di chiamare un metodo di fabbricaget
. Ad esempio, per ottenere un'istanza diMifareUltralight
da unTag
: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 implicano il recupero del tag dall'intent e la comunicazione con il tag. Devi definire il tuo stack di protocollo per leggere e scrivere dati al tag. Tieni presente, tuttavia, che puoi comunque leggere e scrivere dati NDEF quando lavori direttamente con un tag. Sta a te decidere come strutturare le cose. La nell'esempio seguente viene illustrato 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; } }
Utilizzare il sistema di invio in primo piano
Il sistema di invio in primo piano consente a un'attività di intercettare un intento e una rivendicazione la priorità su altre attività che gestiscono lo stesso intento. L'utilizzo di questo sistema comporta creando alcune strutture di dati affinché il sistema Android sia in grado di inviare intent alla tua applicazione. Per attivare il sistema di invio 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 compilarlo 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 di intent per gestire gli intent da intercettare. In primo piano
il sistema di invio controlla i filtri per intent specificati con l'intent che viene ricevuto quando
il dispositivo scansiona un tag. Se corrisponde, la tua applicazione gestisce l'intent. In caso affermativo
non corrisponde, il sistema di invio in primo piano utilizza il sistema di invio per intent.
Se specifichi un array
null
di filtri per intent e filtri di tecnologia, che vuoi filtrare in base a tutti i tag di riservaTAG_DISCOVERED
l'intento. Lo snippet di codice riportato di seguito gestisce tutti i tipi MIME perNDEF_DISCOVERED
. Tu 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 la tua applicazione vuole gestire. Chiama il
Object.class.getName()
per ottenere la classe della tecnologia con cui che vuoi sostenere.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
invio in primo piano quando l'attività perde (
onPause()
) e recupera (onResume()
) l'attenzione.enableForegroundDispatch()
deve essere chiamato da nel thread principale e solo quando l'attività è in primo piano (la chiamata inonResume()
lo garantisce). Devi anche implementare il callbackonNewIntent
per elaborare i dati dell'NFC scansionato del 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 }