Nozioni di base su NFC

Questo documento descrive le attività NFC di base che esegui in Android. Spiega come inviare e ricevere dati NFC sotto forma di messaggi NDEF e descrive le API del framework Android che supportano queste funzionalità. Per argomenti più avanzati, tra cui una discussione sull'utilizzo di dati non NDEF, vedi NFC avanzato.

La lettura dei dati NDEF da un tag NFC viene gestita con il sistema di invio dei tag, che analizza i tag NFC rilevati, classifica i dati in modo appropriato e avvia un'applicazione interessata ai dati classificati. Un'applicazione che vuole gestire il tag NFC scansionato può dichiarare un filtro per intent e richiedere di gestire i dati.

Il sistema di distribuzione dei tag

I dispositivi basati su Android di solito cercano i tag NFC quando lo schermo è sbloccato, a meno che l'NFC non sia disattivato nel menu Impostazioni del dispositivo. Quando un dispositivo basato su Android rileva un tag NFC, il comportamento desiderato è che l'attività più appropriata gestisca l'intent senza chiedere all'utente quale applicazione utilizzare. Poiché i dispositivi scansionano i tag NFC a una distanza molto breve, è probabile che se gli utenti dovessero selezionare manualmente un'attività, dovrebbero allontanare il dispositivo dal tag e interrompere la connessione. Devi sviluppare la tua attività in modo che gestisca solo i tag NFC che ti interessano per impedire la visualizzazione della finestra di selezione delle attività.

Per aiutarti a raggiungere questo obiettivo, Android fornisce un sistema di distribuzione di tag speciale che analizza i tag NFC scansionati, li analizza e tenta di individuare le applicazioni interessate ai dati scansionati. Per farlo:

  1. Analisi del tag NFC e determinazione del tipo MIME o di un URI che identifica il payload dei dati nel tag.
  2. Incapsulamento del tipo MIME o dell'URI e del payload in un intent. Questi primi due passaggi sono descritti in Come vengono mappati i tag NFC ai tipi MIME e agli URI.
  3. Avvia un'attività in base all'intent. Come descritto in Come vengono inviati i tag NFC alle applicazioni.

Come vengono mappati i tag NFC ai tipi MIME e agli URI

Prima di iniziare a scrivere le applicazioni NFC, è importante comprendere i diversi tipi di tag NFC, come il sistema di distribuzione dei tag analizza i tag NFC e il lavoro speciale che il sistema di distribuzione dei tag svolge quando rileva un messaggio NDEF. I tag NFC sono disponibili in un'ampia gamma di tecnologie e possono anche essere scritti in molti modi diversi. Android supporta maggiormente lo standard NDEF, definito dal NFC Forum.

I dati NDEF sono incapsulati all'interno di un messaggio (NdefMessage) che contiene uno o più record (NdefRecord). Ogni record NDEF deve essere ben formato in base alla specifica del tipo di record che vuoi creare. Android supporta anche altri tipi di tag che non contengono dati NDEF, che puoi utilizzare con le classi nel pacchetto android.nfc.tech. Per saperne di più su queste tecnologie, consulta l'argomento NFC avanzato. L'utilizzo di questi altri tipi di tag comporta la scrittura di uno stack di protocolli personalizzato per comunicare con i tag, pertanto consigliamo di utilizzare NDEF quando possibile per semplificare lo sviluppo e garantire il massimo supporto per i dispositivi Android.

Nota:Per scaricare le specifiche NDEF complete, vai al sito NFC Forum Specifications & Application Documents e consulta la sezione Creating common types of NDEF records per esempi su come costruire record NDEF.

Ora che hai acquisito alcune informazioni di base sui tag NFC, le sezioni seguenti descrivono in modo più dettagliato come Android gestisce i tag formattati NDEF. Quando un dispositivo basato su Android esegue la scansione di un tag NFC contenente dati formattati NDEF, analizza il messaggio e tenta di determinare il tipo MIME o l'URI identificativo dei dati. A questo scopo, il sistema legge il primo NdefRecord all'interno di NdefMessage per determinare come interpretare l'intero messaggio NDEF (un messaggio NDEF può contenere più record NDEF). In un messaggio NDEF ben formato, il primo NdefRecord contiene i seguenti campi:

TNF (Type Name Format) a 3 bit
Indica come interpretare il campo del tipo di lunghezza variabile. I valori validi sono descritti nella tabella 1.
Tipo di lunghezza variabile
Descrive il tipo di record. Se utilizzi TNF_WELL_KNOWN, usa questo campo per specificare la definizione del tipo di record (RTD). I valori RTD validi sono descritti nella tabella 2.
ID a lunghezza variabile
Un identificatore univoco per il record. Questo campo non viene utilizzato spesso, ma se devi identificare in modo univoco un tag, puoi creare un ID.
Payload di lunghezza variabile
Il payload di dati effettivi che vuoi leggere o scrivere. Un messaggio NDEF può contenere più record NDEF, quindi non dare per scontato che l'intero payload si trovi nel primo record NDEF del messaggio NDEF.

Il sistema di distribuzione dei tag utilizza i campi TNF e tipo per tentare di mappare un tipo MIME o un URI al messaggio NDEF. In caso di esito positivo, incapsula queste informazioni all'interno di un intent ACTION_NDEF_DISCOVERED insieme al payload effettivo. Tuttavia, ci sono casi in cui il sistema di invio dei tag non può determinare il tipo di dati in base al primo record NDEF. Ciò accade quando i dati NDEF non possono essere mappati a un tipo MIME o a un URI oppure quando il tag NFC non contiene dati NDEF. In questi casi, un oggetto Tag contenente informazioni sulle tecnologie del tag e sul payload viene incapsulato all'interno di un intent ACTION_TECH_DISCOVERED.

La tabella 1 descrive come il sistema di distribuzione dei tag mappa i campi TNF e tipo ai tipi MIME o agli URI. Descrive inoltre quali TNL non possono essere mappati a un tipo MIME o a un URI. In questi casi, il sistema di attivazione dei tag torna a ACTION_TECH_DISCOVERED.

Ad esempio, se il sistema di distribuzione dei tag rileva un record di tipo TNF_ABSOLUTE_URI, mappa il campo del tipo di lunghezza variabile di questo record in un URI. Il sistema di distribuzione dei tag incapsula questo URI nel campo dati di un intent ACTION_NDEF_DISCOVERED insieme ad altre informazioni sul tag, ad esempio il payload. D'altra parte, se rileva un record di tipo TNF_UNKNOWN, crea un intent che incapsula le tecnologie del tag.

Tabella 1. Tipi di notifica supportati e relative mappature

Formato del nome del tipo (TNF) Mappatura
TNF_ABSOLUTE_URI URI basato sul campo Tipo.
TNF_EMPTY Esegue il fallback a ACTION_TECH_DISCOVERED.
TNF_EXTERNAL_TYPE URI basato sull'URN nel campo Tipo. L'URN è codificato nel campo del tipo NDEF in una forma abbreviata: <domain_name>:<service_name>. Android lo mappa a un URI nel formato: vnd.android.nfc://ext/<domain_name>:<service_name>.
TNF_MIME_MEDIA Tipo MIME basato sul campo Tipo.
TNF_UNCHANGED Non valido nel primo record, quindi viene eseguito il fallback a ACTION_TECH_DISCOVERED.
TNF_UNKNOWN Esegue il fallback a ACTION_TECH_DISCOVERED.
TNF_WELL_KNOWN Tipo MIME o URI a seconda della definizione del tipo di record (RTD), che imposti nel campo Tipo. Per saperne di più sugli RTD disponibili e sui relativi mapping, consulta la Tabella 2.

Tabella 2. RTD supportati per TNF_WELL_KNOWN e le relative mappature

Definizione del tipo di record (RTD) Mappatura
RTD_ALTERNATIVE_CARRIER Esegue il fallback a ACTION_TECH_DISCOVERED.
RTD_HANDOVER_CARRIER Esegue il fallback a ACTION_TECH_DISCOVERED.
RTD_HANDOVER_REQUEST Esegue il fallback a ACTION_TECH_DISCOVERED.
RTD_HANDOVER_SELECT Esegue il fallback a ACTION_TECH_DISCOVERED.
RTD_SMART_POSTER URI basato sull'analisi del payload.
RTD_TEXT Tipo MIME di text/plain.
RTD_URI URI basato sul payload.

Come vengono inviati i tag NFC alle applicazioni

Quando il sistema di distribuzione dei tag ha creato un intent che incapsula il tag NFC e le relative informazioni identificative, invia l'intent a un'applicazione interessata che lo filtra. Se più di un'applicazione può gestire l'intent, viene visualizzato il selettore di attività in modo che l'utente possa selezionare l'attività. Il sistema di distribuzione dei tag definisce tre intent, elencati in ordine di priorità decrescente:

  1. ACTION_NDEF_DISCOVERED: questo intent viene utilizzato per avviare un'attività quando viene scansionato un tag che contiene un payload NDEF ed è di un tipo riconosciuto. Questo è l'intent con la priorità più alta e il sistema di distribuzione dei tag tenta di avviare un'attività con questo intent prima di qualsiasi altro intent, quando possibile.

    Nota:a partire da Android 16, la scansione dei tag NFC che memorizzano link URL (ovvero lo schema URI è "https://" o "http://") attiverà l'intent ACTION_VIEW anziché l'intent ACTION_NDEF_DISCOVERED.

  2. ACTION_TECH_DISCOVERED: se nessuna attività viene registrata per gestire l'intent ACTION_NDEF_DISCOVERED, il sistema di invio dei tag tenta di avviare un'applicazione con questo intent. Questo intent viene avviato anche direttamente (senza avviare prima ACTION_NDEF_DISCOVERED) se il tag scansionato contiene dati NDEF che non possono essere mappati a un tipo MIME o a un URI oppure se il tag non contiene dati NDEF ma è di una tecnologia di tag nota.
  3. ACTION_TAG_DISCOVERED: questo intent viene avviato se nessuna attività gestisce gli intent ACTION_NDEF_DISCOVERED o ACTION_TECH_DISCOVERED.

Il funzionamento di base del sistema di distribuzione dei tag è il seguente:

  1. Prova ad avviare un'attività con l'intent creato dal sistema di invio dei tag durante l'analisi del tag NFC (ACTION_NDEF_DISCOVERED o ACTION_TECH_DISCOVERED).
  2. Se non viene trovato alcun filtro per le attività per quell'intent, prova ad avviare un'attività con l'intent con priorità più bassa successiva (ACTION_TECH_DISCOVERED o ACTION_TAG_DISCOVERED) finché un'applicazione non filtra l'intent o finché il sistema di invio dei tag non prova tutti gli intent possibili.
  3. Se non viene applicato alcun filtro per nessuna delle intenzioni, non fare nulla.
Figura 1. Sistema di distribuzione dei tag

Se possibile, utilizza i messaggi NDEF e l'intent ACTION_NDEF_DISCOVERED, perché è il più specifico tra i tre. Questo intent ti consente di avviare l'applicazione in un momento più appropriato rispetto agli altri due intent, offrendo all'utente un'esperienza migliore.

Richiedere l'accesso NFC nel manifest Android

Prima di poter accedere all'hardware NFC di un dispositivo e gestire correttamente gli intent NFC, dichiara questi elementi nel file AndroidManifest.xml:

  • L'elemento NFC <uses-permission> per accedere all'hardware NFC:
    <uses-permission android:name="android.permission.NFC" />
  • La versione minima dell'SDK supportata dalla tua applicazione. Il livello API 9 supporta solo l'invio limitato di tag tramite ACTION_TAG_DISCOVERED e consente l'accesso ai messaggi NDEF solo tramite l'extra EXTRA_NDEF_MESSAGES. Nessun'altra proprietà del tag o operazione di I/O è accessibile. Il livello API 10 include il supporto completo per la lettura/scrittura, nonché il push NDEF in primo piano, mentre il livello API 14 fornisce metodi di convenienza aggiuntivi per creare record NDEF.
    <uses-sdk android:minSdkVersion="10"/>
  • L'elemento uses-feature in modo che la tua applicazione venga visualizzata su Google Play solo per i dispositivi dotati di hardware NFC:
    <uses-feature android:name="android.hardware.nfc" android:required="true" />

    Se la tua applicazione utilizza la funzionalità NFC, ma questa non è fondamentale per la tua applicazione, puoi omettere l'elemento uses-feature e verificare la disponibilità di NFC in runtime controllando se getDefaultAdapter() è null.

Filtrare per intent NFC

Per avviare l'applicazione quando viene scansionato un tag NFC che vuoi gestire, l'applicazione può filtrare uno, due o tutti e tre gli intent NFC nel manifest Android. Tuttavia, in genere vuoi filtrare in base all'intent ACTION_NDEF_DISCOVERED per avere il massimo controllo sull'avvio dell'applicazione. L'intent ACTION_TECH_DISCOVERED è un fallback per ACTION_NDEF_DISCOVERED quando non viene applicato alcun filtro per ACTION_NDEF_DISCOVERED o quando il payload non è NDEF. Il filtro per ACTION_TAG_DISCOVERED è in genere una categoria troppo generica per essere filtrata. Molte applicazioni filtrano ACTION_NDEF_DISCOVERED o ACTION_TECH_DISCOVERED prima di ACTION_TAG_DISCOVERED, quindi la tua applicazione ha una bassa probabilità di avvio. ACTION_TAG_DISCOVERED è disponibile solo come ultima risorsa per le applicazioni da filtrare nei casi in cui non sono installate altre applicazioni per gestire l'intent ACTION_NDEF_DISCOVERED o ACTION_TECH_DISCOVERED.

Poiché le implementazioni dei tag NFC variano e spesso non sono sotto il tuo controllo, questa operazione non è sempre possibile, motivo per cui puoi ricorrere agli altri due intent quando necessario. Quando hai il controllo sui tipi di tag e dati scritti, ti consigliamo di utilizzare NDEF per formattare i tag. Le sezioni seguenti descrivono come filtrare in base a ogni tipo di intento.

ACTION_NDEF_DISCOVERED

Per filtrare le finalità ACTION_NDEF_DISCOVERED, dichiara il filtro per intent insieme al tipo di dati da filtrare. Il seguente esempio filtra le intent ACTION_NDEF_DISCOVERED con un tipo MIME 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>

L'esempio seguente filtra un URI nel formato 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 i filtri attività per l'intent ACTION_TECH_DISCOVERED, devi creare un file di risorse XML che specifichi le tecnologie supportate dalla tua attività all'interno di un insieme tech-list. La tua attività è considerata una corrispondenza se un insieme tech-list è un sottoinsieme delle tecnologie supportate dal tag, che puoi ottenere chiamando getTechList().

Ad esempio, se il tag scansionato supporta MifareClassic, NdefFormatable e NfcA, il tuo set tech-list deve specificare tutte e tre, due o una delle tecnologie (e nient'altro) affinché la tua attività venga abbinata.

L'esempio seguente definisce tutte le tecnologie. Devi rimuovere quelli non supportati dal tag NFC. Salva questo file (puoi assegnargli il nome che preferisci) nella cartella <project-root>/res/xml.

<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>

Puoi anche specificare più set di tech-list. Ciascuno dei set tech-list viene considerato in modo indipendente e la tua attività viene considerata una corrispondenza se un singolo set tech-list è un sottoinsieme delle tecnologie restituite da getTechList(). Questo fornisce la semantica di AND e OR per le tecnologie di corrispondenza. Il seguente esempio corrisponde ai tag che possono supportare le tecnologie NfcA e Ndef oppure le tecnologie 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>

Nel file AndroidManifest.xml, specifica il file di risorse che hai appena creato nell'elemento <meta-data> all'interno dell'elemento <activity> come nell'esempio seguente:

<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>

Per saperne di più sull'utilizzo delle tecnologie di tagging e sull'intent ACTION_TECH_DISCOVERED, consulta la sezione Utilizzo delle tecnologie di tagging supportate nel documento NFC avanzato.

ACTION_TAG_DISCOVERED

Per filtrare in base a ACTION_TAG_DISCOVERED, utilizza il seguente filtro per intent:

<intent-filter>
    <action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>

ACTION_VIEW

A partire da Android 16, la scansione dei tag NFC che memorizzano i link URL attiverà l'intent ACTION_VIEW. Per filtrare in base a ACTION_VIEW, consulta this. Usa Android app links per aprire l'app per l'URL.

Ottenere informazioni dagli intent

Se un'attività viene avviata a causa di un intent NFC, puoi ottenere informazioni sul tag NFC scansionato dall'intent. Gli intent possono contenere i seguenti extra a seconda del tag scansionato:

Per ottenere questi extra, verifica se la tua attività è stata avviata con uno degli intent NFC per assicurarti che sia stato scansionato un tag, quindi ottieni gli extra dall'intent. L'esempio seguente verifica l'intent ACTION_NDEF_DISCOVERED e recupera i messaggi NDEF da un extra dell'intent.

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.
            ...
        }
    }
}

In alternativa, puoi ottenere un oggetto Tag dall'intent, che contiene il payload e ti consente di enumerare le tecnologie del tag:

Kotlin

val tag: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)

Java

Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

Crea tipi comuni di record NDEF

Questa sezione descrive come creare tipi comuni di record NDEF per aiutarti a scrivere sui tag NFC. A partire da Android 4.0 (livello API 14), il metodo createUri() è disponibile per aiutarti a creare automaticamente record URI. A partire da Android 4.1 (livello API 16), createExternal() e createMime() sono disponibili per aiutarti a creare record NDEF di tipo MIME ed esterno. Utilizza questi metodi helper quando possibile per evitare errori durante la creazione manuale dei record NDEF.

Questa sezione descrive anche come creare il filtro per intent corrispondente per il record. Tutti questi esempi di record NDEF devono trovarsi nel primo record NDEF del messaggio NDEF che stai scrivendo in un tag.

TNF_ABSOLUTE_URI

Nota:ti consigliamo di utilizzare il tipo RTD_URI anziché TNF_ABSOLUTE_URI, perché è più efficiente.

Puoi creare un record NDEF TNF_ABSOLUTE_URI nel seguente modo:

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]);

Il filtro per intent per il record NDEF precedente avrebbe il seguente aspetto:

<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

Puoi creare un record NDEF TNF_MIME_MEDIA nei seguenti modi:

Utilizzo del metodo 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")));

Creazione manuale di NdefRecord:

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")));

Il filtro per intent per il record NDEF precedente avrebbe il seguente aspetto:

<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 con RTD_TEXT

Puoi creare un record NDEF TNF_WELL_KNOWN nel seguente modo:

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;
}

Il filtro per intent per il record NDEF precedente avrebbe il seguente aspetto:

<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 con RTD_URI

Puoi creare un record NDEF TNF_WELL_KNOWN nei seguenti modi:

Utilizzo del metodo createUri(String):

Kotlin

val rtdUriRecord1 = NdefRecord.createUri("https://example.com")

Java

NdefRecord rtdUriRecord1 = NdefRecord.createUri("https://example.com");

Utilizzo del metodo 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);

Creazione manuale di NdefRecord:

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);

Il filtro per intent per il record NDEF precedente avrebbe il seguente aspetto:

<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

Puoi creare un record NDEF TNF_EXTERNAL_TYPE nei seguenti modi:

Utilizzo del metodo 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);

Creazione manuale di NdefRecord:

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);

Il filtro per intent per il record NDEF precedente avrebbe il seguente aspetto:

<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>

Utilizza TNF_EXTERNAL_TYPE per deployment di tag NFC più generici per supportare meglio sia i dispositivi Android che non Android.

Nota: gli URN per TNF_EXTERNAL_TYPE hanno un formato canonico di: urn:nfc:ext:example.com:externalType, tuttavia la specifica RTD del forum NFC dichiara che la parte urn:nfc:ext: dell'URN deve essere omessa dal record NDEF. Quindi, tutto ciò che devi fornire è il dominio (example.com nell'esempio) e il tipo (externalType nell'esempio) separati da due punti. Quando invia TNF_EXTERNAL_TYPE, Android converte l'URN urn:nfc:ext:example.com:externalType in un URI vnd.android.nfc://ext/example.com:externalType, che è ciò che dichiara il filtro per intent nell'esempio.

Record delle applicazioni Android

Introdotto in Android 4.0 (livello API 14), un record dell'applicazione Android (AAR) offre una maggiore certezza che l'applicazione venga avviata quando viene scansionato un tag NFC. Un AAR ha il nome del pacchetto di un'applicazione incorporato in un record NDEF. Puoi aggiungere un AAR a qualsiasi record NDEF del messaggio NDEF, perché Android cerca gli AAR nell'intero messaggio NDEF. Se trova un AAR, avvia l'applicazione in base al nome del pacchetto all'interno dell'AAR. Se l'applicazione non è presente sul dispositivo, viene avviato Google Play per scaricarla.

Gli AAR sono utili se vuoi impedire ad altre applicazioni di filtrare in base allo stesso intent e potenzialmente gestire tag specifici che hai implementato. Gli AAR sono supportati solo a livello di applicazione, a causa del vincolo del nome del pacchetto, e non a livello di attività come con il filtro per intent. Se vuoi gestire un intent a livello di attività, utilizza i filtri per intent.

Se un tag contiene un AAR, il sistema di distribuzione dei tag lo distribuisce nel seguente modo:

  1. Prova ad avviare un'attività utilizzando un filtro per intent come di consueto. Se l'attività che corrisponde all'intent corrisponde anche all'AAR, avvia l'attività.
  2. Se l'attività che filtra l'intent non corrisponde all'AAR, se più attività possono gestire l'intent o se nessuna attività gestisce l'intent, avvia l'applicazione specificata dall'AAR.
  3. Se nessuna applicazione può essere avviata con l'AAR, vai su Google Play per scaricare l'applicazione in base all'AAR.

Nota:puoi ignorare le AAR e il sistema di distribuzione degli intent con il sistema di distribuzione in primo piano, che consente a un'attività in primo piano di avere la priorità quando viene rilevato un tag NFC. Con questo metodo, l'attività deve essere in primo piano per ignorare gli AAR e il sistema di distribuzione degli intent.

Se vuoi comunque filtrare i tag scansionati che non contengono un AAR, puoi dichiarare i filtri per intent come di consueto. Questa funzionalità è utile se la tua applicazione è interessata ad altri tag che non contengono un AAR. Ad esempio, potresti voler garantire che la tua applicazione gestisca i tag proprietari che implementi, nonché i tag generali implementati da terze parti. Tieni presente che gli AAR sono specifici per i dispositivi Android 4.0 o versioni successive, quindi quando esegui il deployment dei tag, molto probabilmente vorrai utilizzare una combinazione di AAR e tipi/URI MIME per supportare la più ampia gamma di dispositivi. Inoltre, quando implementi i tag NFC, pensa a come vuoi scriverli per consentire il supporto per la maggior parte dei dispositivi (Android e altri dispositivi). Puoi farlo definendo un tipo MIME o un URI relativamente univoco per facilitare la distinzione da parte delle applicazioni.

Android fornisce una semplice API per creare un AAR, createApplicationRecord(). Tutto ciò che devi fare è incorporare l'AAR in un punto qualsiasi del tuo NdefMessage. Non vuoi utilizzare il primo record del tuo NdefMessage, a meno che l'AAR non sia l'unico record nel NdefMessage. Questo perché il sistema Android controlla il primo record di un NdefMessage per determinare il tipo MIME o l'URI del tag, che viene utilizzato per creare un intent per le applicazioni da filtrare. Il seguente codice mostra come creare un 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")}
        );
)

Elenco consentito di app per la scansione di tag NFC

A partire da Android 16, gli utenti ricevono una notifica quando un'app riceve il primo intent NFC per scansionare i tag NFC. Nella notifica, l'utente ha la possibilità di impedire all'app di eseguire ulteriori scansioni di tag NFC.

Nota:l'elenco consentito delle app di scansione dei tag NFC è accessibile in Settings > Apps > Special app access > Launch via NFC.

Questo meccanismo è stato aggiunto per rispondere alle preoccupazioni sollevate dagli utenti in merito ad alcune app che avevano registrato filtri di intent per gli intent dei tag NFC e che venivano portate ripetutamente in primo piano quando posizionavano lo smartphone vicino a un tag NFC (carta di credito, un altro smartphone/smartwatch e così via).