Nozioni di base su NFC

In questo documento vengono descritte le attività NFC di base che esegui in Android. Viene spiegato come inviare e Ricevere dati NFC sotto forma di messaggi NDEF e descrivere le API del framework Android che supportano queste funzionalità. Per argomenti più avanzati, inclusa una discussione sull'utilizzo di dati non NDEF, consulta la sezione NFC avanzata.

Esistono due casi d'uso principali quando si lavora con dati NDEF e Android:

  • Lettura dei dati NDEF da un tag NFC
  • Trasmettere messaggi NDEF da un dispositivo a un altro con Android BeamTM

La lettura dei dati NDEF da un tag NFC viene gestita con l'invio dei tag. , che analizza i tag NFC rilevati, classifica i dati in modo appropriato e inizia un'applicazione interessata ai dati categorizzati. un'applicazione che vuole gestire Il tag NFC scansionato può dichiarare un filtro per intent e una richiesta di gestione dei dati.

La funzione Android BeamTM consente a un dispositivo di inviare un messaggio NDEF a un altro dispositivo mettendo a contatto ciascun dispositivo. Questa interazione offre un modo più semplice di inviare dati rispetto ad altre tecnologie wireless come il Bluetooth, perché con NFC, nessun dispositivo manuale il rilevamento o l'accoppiamento è obbligatorio. La connessione viene avviata automaticamente quando si collegano due dispositivi nel raggio d'azione. Android Beam è disponibile tramite una serie di API NFC, che consentono a qualsiasi applicazione di trasmettere informazioni tra i dispositivi. Ad esempio, le applicazioni Contatti, Browser e YouTube utilizzano Android Beam per condividere contatti, pagine web e video con altri dispositivi.

Il sistema di invio tag

I dispositivi Android di solito cercano i tag NFC quando lo schermo è sbloccato, a meno che NFC non sia disattivata nel menu Impostazioni del dispositivo. Quando un dispositivo Android rileva un tag NFC, il comportamento desiderato è avere l'attività più appropriata per gestire l'intento senza chiedere all'utente quale applicazione per l'utilizzo. Dato che i dispositivi scansionano i tag NFC a un raggio molto breve, è probabile che gli utenti utilizzino manualmente la selezione di un'attività li costringe ad allontanare il dispositivo dal tag e a interrompere la connessione. Dovresti sviluppare la tua attività in modo da gestire solo i tag NFC che sono importanti per la tua attività. impediscono la visualizzazione del Selettore attività.

Per aiutarti a raggiungere questo obiettivo, Android offre uno speciale sistema di invio dei tag che analizza le scansioni i tag NFC, li analizza e prova a individuare le applicazioni interessate ai dati scansionati. it può farlo:

  1. Analisi del tag NFC e rilevamento del tipo MIME o di un URI che identifica il payload dei dati nel tag.
  2. Incapsulamento del tipo o dell'URI MIME e del payload in un intent. Queste due prime sono descritti in Come vengono mappati i tag NFC a tipi MIME e URI.
  3. Avvia un'attività in base all'intenzione. Questa operazione viene descritta Modalità di invio dei tag NFC alle applicazioni.

Come vengono mappati i tag NFC a tipi e URI MIME

Prima di iniziare a scrivere applicazioni NFC, è importante comprendere le diverse i tipi di tag NFC, la modalità di analisi dei tag NFC da parte del sistema di invio dei tag e il lavoro speciale svolto quando rileva un messaggio NDEF. I tag NFC sono disponibili un'ampia gamma di tecnologie e i dati possono essere scritti in molti modi diversi. Android offre il supporto maggiore per lo standard NDEF, definito dall'NFC Forum.

I dati NDEF sono incapsulati all'interno di un messaggio (NdefMessage) che contiene o più record (NdefRecord). Ogni record NDEF deve essere formulato in modo corretto secondo la specifica del tipo di record che vuoi creare. Android supporta anche altri tipi di tag che non contengono dati NDEF, che puoi utilizzare utilizzando le classi del pacchetto android.nfc.tech. Per scoprire di più su queste tecnologie, consulta l'argomento NFC avanzata. L'utilizzo di questi altri tipi di tag comporta scrivere il tuo stack di protocollo per comunicare con i tag, quindi consigliamo di usare NDEF quando possibile per una facilità di sviluppo e il massimo supporto dei dispositivi basati su Android.

Nota: Per scaricare le specifiche NDEF complete, vai alla pagina NFC Forum Specifications & Documenti d'applicazione e consultare il sito Creazione di tipi comuni di record NDEF per esempi su come creare record NDEF.

Ora che conosci le informazioni di base sui tag NFC, nelle sezioni seguenti vengono descritte in modo più dettagliato come Android gestisce i tag formattati NDEF. Quando un dispositivo Android analizza un tag NFC contenente NDEF dati formattati, analizza il messaggio e prova a individuare il tipo MIME dei dati o l'identificazione URI. Per farlo, il sistema legge il primo NdefRecord all'interno di NdefMessage per determinare come interpretare l'intero messaggio NDEF (un messaggio NDEF può avere 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 usi 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 lunghezza variabile
Un identificatore univoco del record. Questo campo non viene utilizzato spesso, ma se devi identificare un tag in modo univoco, puoi creare un ID.
Carico di lunghezza variabile
Il payload effettivo che vuoi leggere o scrivere. Un NDEF può contenere più record NDEF, quindi non dare per scontato che il payload completo sia nel primo NDEF record del messaggio NDEF.

Il sistema di invio dei tag utilizza i campi del tipo e del TNF per provare a mappare un URI o un tipo MIME alla messaggio NDEF. In caso di esito positivo, il modello incapsula queste informazioni all'interno di un intent ACTION_NDEF_DISCOVERED insieme al payload effettivo. Tuttavia, sono i casi in cui il sistema di invio dei tag non è in grado di determinare il tipo di dati in base al primo NDEF record. Questo accade quando i dati NDEF non possono essere mappati a un tipo o a un URI MIME o quando Il tag NFC non contiene dati NDEF con cui iniziare. In questi casi, un oggetto Tag che contiene informazioni sulle tecnologie del tag e sul payload vengono incapsulati invece in un intent ACTION_TECH_DISCOVERED.

La tabella 1 descrive in che modo il sistema di invio dei tag mappa il TNF e il tipo ai tipi MIME o agli URI. Descrive inoltre quali TNF non possono essere mappati a un tipo o a un URI MIME. In questi casi, il sistema di invio dei tag utilizza ACTION_TECH_DISCOVERED.

Ad esempio, se il sistema di invio dei tag rileva un record di tipo TNF_ABSOLUTE_URI, mappa il campo del tipo di lunghezza variabile di quel record in un URI. Il sistema di invio dei tag incapsula l'URI nel campo dei dati di un intent ACTION_NDEF_DISCOVERED insieme ad altre informazioni relative al tag. come il payload. Se invece rileva un record di tipo TNF_UNKNOWN, crea un intent che incapsula le tecnologie del tag .

Tabella 1. TNF supportati e relative mappature

Formato nome tipo (TNF) Mappatura
TNF_ABSOLUTE_URI URI in base al campo del tipo.
TNF_EMPTY Torna a ACTION_TECH_DISCOVERED.
TNF_EXTERNAL_TYPE URI basato sull'URN nel campo del tipo. L'URN è codificato nel campo di tipo NDEF in un formato abbreviato: <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 in base al campo del tipo.
TNF_UNCHANGED Non valido nel primo record, quindi torna a ACTION_TECH_DISCOVERED.
TNF_UNKNOWN Torna a ACTION_TECH_DISCOVERED.
TNF_WELL_KNOWN tipo MIME o URI a seconda del Record Type Definition (RTD), impostato nel . Consulta la Tabella 2 per ulteriori informazioni su gli RTD disponibili e le relative mappature.

Tabella 2. RTD supportati per TNF_WELL_KNOWN e relativi mappature

Record Type Definition (RTD) Mappatura
RTD_ALTERNATIVE_CARRIER Torna a ACTION_TECH_DISCOVERED.
RTD_HANDOVER_CARRIER Torna a ACTION_TECH_DISCOVERED.
RTD_HANDOVER_REQUEST Torna a ACTION_TECH_DISCOVERED.
RTD_HANDOVER_SELECT Torna 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 invio tag ha terminato di creare un intent che incapsula il tag NFC e i relativi identificare le informazioni, invia l'intento a un'applicazione interessata filtri per l'intent. Se più applicazioni sono in grado di gestire l'intent, il Selettore attività così che l'utente possa selezionare l'attività. Il sistema di invio dei tag definisce tre intent, elencati in ordine di priorità, dalla più alta alla più bassa:

  1. ACTION_NDEF_DISCOVERED: questo intent viene utilizzato per avviare un Attività quando un tag che contiene un payload NDEF viene analizzato ed è di un tipo riconosciuto. Questo è l'intent con la priorità più alta e il sistema di invio dei tag prova ad avviare un'attività con l'intenzione prima di qualsiasi altro intento, quando possibile.
  2. ACTION_TECH_DISCOVERED: se non viene registrata alcuna attività gestire ACTION_NDEF_DISCOVERED , il sistema di invio dei tag prova ad avviare un'applicazione con questo intent. Questo anche l'intent viene avviato direttamente (senza iniziare prima ACTION_NDEF_DISCOVERED) se il tag viene analizzato Contiene dati NDEF che non possono essere mappati a un URI o un tipo MIME oppure il tag non contiene NDEF dati, ma fa parte di una tecnologia di tag nota.
  3. ACTION_TAG_DISCOVERED: questo intent è stato avviato se nessuna attività gestisce ACTION_NDEF_DISCOVERED o ACTION_TECH_DISCOVERED intent.

Il funzionamento del sistema di invio 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 (ad esempio ACTION_NDEF_DISCOVERED o ACTION_TECH_DISCOVERED).
  2. Se nessuna attività filtra per quell'intent, prova ad avviare un'attività con la per intent con priorità più bassa (ACTION_TECH_DISCOVERED o ACTION_TAG_DISCOVERED) finché un'applicazione non filtra per o fino a quando il sistema di invio dei tag non prova tutti gli intent possibili.
  3. Se nessuna applicazione filtra in base agli intent, non fare nulla.
di Gemini Advanced.
Figura 1. Sistema di invio dei tag

Se possibile, lavora con i messaggi NDEF e l'intent ACTION_NDEF_DISCOVERED, perché è il più specifico i tre. Questo intent ti consente di presentare la tua domanda in un momento più appropriato rispetto a altri due intent, offrendo all'utente un'esperienza migliore.

Richiedere l'accesso NFC nel file 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:

  • Elemento NFC <uses-permission> per accedere all'hardware NFC:
    <uses-permission android:name="android.permission.NFC" />
    
  • La versione minima dell'SDK che la tua applicazione può supportare. Il livello API 9 supporta solo un numero limitato di tag tramite ACTION_TAG_DISCOVERED e restituisce solo accesso ai messaggi NDEF tramite l'ulteriore EXTRA_NDEF_MESSAGES. No altre proprietà del tag o operazioni di I/O. Livello API 10 include un supporto completo per lettori/autore, nonché push NDEF in primo piano e livello API. 14 offre un modo più semplice per inviare messaggi NDEF ad altri dispositivi con Android Beam e per creare record NDEF.
    <uses-sdk android:minSdkVersion="10"/>
    
  • L'elemento uses-feature in modo che la tua applicazione venga visualizzata in 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 il tuo puoi omettere l'elemento uses-feature e verificare la disponibilità della tecnologia NFC all'indirizzo di runtime controllando se getDefaultAdapter() è null.

Filtra intent NFC

Per avviare l'applicazione quando viene scansionato un tag NFC che desideri gestire, l'applicazione puoi filtrare per uno, due o tutti e tre gli intent NFC nel file manifest Android. Tuttavia, di solito vogliono filtrare in base all'intent ACTION_NDEF_DISCOVERED per hai il massimo controllo sull'avvio dell'applicazione. L'intent ACTION_TECH_DISCOVERED è un fallback per ACTION_NDEF_DISCOVERED quando nessun filtro delle applicazioni filtra per ACTION_NDEF_DISCOVERED o quando il payload non è NDEF. Il filtro per ACTION_TAG_DISCOVERED di solito è troppo generico per categoria in base alla quale applicare il filtro. Molte applicazioni filtreranno ACTION_NDEF_DISCOVERED o ACTION_TECH_DISCOVERED prima del giorno ACTION_TAG_DISCOVERED, quindi la tua applicazione ha una bassa probabilità di iniziare. ACTION_TAG_DISCOVERED è disponibile solo come ultima risorsa delle applicazioni da filtrare nei casi in cui non siano installate altre applicazioni per gestire Per intent ACTION_NDEF_DISCOVERED o ACTION_TECH_DISCOVERED.

Poiché le implementazioni dei tag NFC variano e molte volte non sono sotto il tuo controllo, non sempre ed è per questo che puoi ricorrere agli altri due intent se necessario. Se hai sui tipi di tag e dati scritti, è consigliabile utilizzare NDEF per formattare i tag. Le seguenti sezioni descrivono come filtrare in base a ciascun tipo di intent.

ACTION_NDEF_DISCOVERED

Per filtrare in base a ACTION_NDEF_DISCOVERED intent, dichiara il insieme al tipo di dati da filtrare. La i seguenti filtri di esempio per ACTION_NDEF_DISCOVERED intent 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 in base a un URI sotto forma di 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>

TECNOLOGIA_AZIONE_DISCOVERED

Se la tua attività filtra in base all'intent ACTION_TECH_DISCOVERED, devi creare un file di risorse XML che specifichi le tecnologie supportate dalla tua attività in un insieme di tech-list. La tua attività è viene considerata una corrispondenza se un insieme di tech-list è un sottoinsieme delle tecnologie che supportata dal tag, che puoi ottenere chiamando getTechList().

Ad esempio, se il tag analizzato supporta MifareClassic, NdefFormatable e NfcA, il tuo Il set di tech-list deve specificare tutte e tre le tecnologie, oppure una sola delle tecnologie (e nulla altro) per far sì che la tua attività venga abbinata.

Il seguente esempio definisce tutte le tecnologie. Devi rimuovere quelle che non sono supportata dal tag NFC. Salva il file (puoi assegnargli il nome che desideri) nella <project-root>/res/xml cartella.

<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 tech-list di set di dati viene considerata indipendente e la tua attività viene considerata una corrispondenza se Il set tech-list è un sottoinsieme delle tecnologie restituite da getTechList(). In questo modo ottieni AND e OR la semantica per le tecnologie di corrispondenza. L'esempio seguente corrisponde a tag che possono supportare tecnologie NfcA e Ndef o possono supportare 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 di <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 ulteriori informazioni sull'utilizzo delle tecnologie di tag e dell'intent ACTION_TECH_DISCOVERED, consulta Utilizzo dei tag supportati tecnologie nel documento NFC avanzata.

ACTION_TAG_DISCOVERED

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

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

Ottenere informazioni dagli intent

Se un'attività inizia per un intent NFC, puoi ottenere informazioni sull'NFC scansionato dell'intent. Gli intent possono contenere i seguenti extra a seconda del tag analizzato:

Per ottenere questi extra, controlla se la tua attività è stata avviata con uno di gli intent NFC per garantire che un tag sia stato scansionato, quindi ricavarne gli extra dalla l'intento. L'esempio seguente verifica la presenza di ACTION_NDEF_DISCOVERED e ottiene i messaggi NDEF da un intent aggiuntivo.

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 contengono il payload e consentono di enumerare le tecnologie del tag:

Kotlin

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

Java

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

Creazione di tipi comuni di record NDEF

Questa sezione descrive come creare tipi comuni di record NDEF per semplificare la scrittura Tag NFC o invio di dati con Android Beam. A partire da Android 4.0 (livello API 14), la Il metodo createUri() è disponibile per aiutarti a creare record URI automaticamente. A partire da Android 4.1 (livello API 16), createExternal() e createMime() sono disponibili per aiutarti a creare Record MIME e NDEF di tipo esterno. Se possibile, usa questi metodi di supporto per evitare errori durante la creazione manuale di record NDEF.

Questa sezione descrive inoltre come creare il modello filtro per intent. Tutti questi esempi di record NDEF devono essere nel primo NDEF record del messaggio NDEF che stai scrivendo su un tag o tramite trasmissione.

TNF_ABSOLUTE_URI

Nota: ti consigliamo di utilizzare lo RTD_URI digita di 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:

Se utilizzi il 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:

Se utilizzi il metodo createUri(String):

Kotlin

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

Java

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

Se utilizzi il 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>

TIPO_ESTERNO_TNF

Puoi creare un record NDEF TNF_EXTERNAL_TYPE nel seguente modi:

Se utilizzi il 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 implementazioni più generiche di tag NFC in modo da supportare meglio entrambi Dispositivi con e non Android.

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

Record delle app Android

Introdotto in Android 4.0 (livello API 14), un Android Application Record (AAR) offre un la certezza che l'applicazione viene avviata quando viene scansionato un tag NFC. Un AAR ha il nome del pacchetto di un'applicazione incorporata in un record NDEF. Puoi aggiungere un AAR a qualsiasi record NDEF del tuo NDEF poiché Android cerca gli AAR in tutto il messaggio NDEF. Se trova un AAR, inizia l'applicazione in base al nome del pacchetto all'interno dell'AAR. Se l'applicazione non è presente nel dispositivo, viene avviato Google Play per scaricare l'applicazione.

Gli AAR sono utili se vuoi impedire ad altre applicazioni di filtrare in base allo stesso intento potenzialmente gestire tag specifici di cui hai eseguito il deployment. I rivenditori autorizzati sono supportati solo a livello di applicazione, a causa del vincolo di nome del pacchetto, e non al livello di attività, come e 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 invio dei tag effettua l'invio nel seguente modo:

  1. Prova ad avviare un'attività utilizzando un filtro per intent, come di consueto. Se l'attività corrispondente anche l'intent corrisponde all'AAR, avvia l'attività.
  2. Se l'attività che filtra per l'intent non corrisponde alla AAR, se più attività possono gestire l'intento, oppure se nessuna attività gestisce l'intent, dell'applicazione specificata dall'AAR.
  3. Se nessuna applicazione supporta l'AAR, accedi a Google Play per scaricare l'app un'applicazione basata sull'AAR.

Nota: puoi sostituire gli AAR e il sistema di invio dell'intent con il in primo piano di tracciamento delle spedizioni, che consente a un'attività in primo piano di avere la priorità quando un tag NFC viene sono state rilevate. Con questo metodo, l'attività deve essere in primo piano per eseguire l'override di AAR e di invio per intenzione.

Se vuoi comunque filtrare i tag scansionati che non contengono un AAR, puoi dichiarare filtri per intent come di consueto. È utile se la tua applicazione è interessata ad altri tag che non contengono un AAR. Ad esempio, potresti voler garantire che la tua applicazione gestisca così come i tag generici implementati da terze parti. Aspetti da tenere presenti che i AAR siano specifici per i dispositivi con Android 4.0 o versioni successive. Pertanto, quando implementi i tag, una combinazione di AAR e tipi MIME/URI in modo da supportare la più ampia gamma di dispositivi. Nella Inoltre, quando implementi i tag NFC, pensa a come desideri scriverli per abilitare il supporto per la maggior parte dei dispositivi (dispositivi basati su Android e di altro tipo). A tale scopo, procedi nel seguente modo: la definizione di un URI o un tipo MIME relativamente univoco per facilitare la distinzione da parte delle applicazioni.

Android offre una semplice API per creare un AAR, createApplicationRecord(). Tutto ciò che ti serve incorpora l'AAR in qualsiasi punto di NdefMessage. Non vuoi per utilizzare il primo record di NdefMessage, a meno che l'AAR non sia l'unico record in NdefMessage. Questo perché Android controlla il primo record di un NdefMessage per determinare il tipo MIME o URI del tag, utilizzato per creare un intent che le applicazioni filtrano. 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")}
        );
)

Trasmetti messaggi NDEF ad altri dispositivi

Android Beam consente un semplice scambio di dati peer-to-peer tra due dispositivi Android. La l'applicazione che desidera trasmettere dati a un altro dispositivo deve essere in primo piano e il dispositivo la ricezione dei dati non deve essere bloccata. Quando il dispositivo raggiante entra in contatto abbastanza vicino con una dispositivo ricevente, il dispositivo di trasmissione visualizza il messaggio "Tocca per trasmettere" nell'interfaccia utente. L'utente può quindi scegliere se trasmettere o meno il messaggio al dispositivo ricevente.

Nota: il push NDEF in primo piano era disponibile a livello API 10, che offre funzionalità simili ad Android Beam. Queste API sono state ritirate, ma per supportare i dispositivi meno recenti. Leggi i enableForegroundNdefPush() per avere ulteriori informazioni.

Puoi attivare Android Beam per la tua applicazione chiamando uno dei due metodi:

  • setNdefPushMessage(): accetta un NdefMessage da impostare come messaggio da trasmettere. Trasmette automaticamente il messaggio quando due dispositivi sono abbastanza vicini.
  • setNdefPushMessageCallback(): Accetta un callback che contiene un createNdefMessage() che viene chiamato quando un dispositivo è nel raggio d'azione per trasmettere dati. Il callback ti consente di creare il messaggio NDEF solo quando necessario.

Un'attività può eseguire il push di un solo messaggio NDEF alla volta, quindi setNdefPushMessageCallback() ha la precedenza maggiore di setNdefPushMessage() se sono impostati entrambi. Per utilizzare Android Beam, devono essere rispettate le seguenti linee guida generali:

  • L'attività che trasmette i dati deve essere in primo piano. Entrambi i dispositivi devono avere si sbloccavano gli schermi.
  • Devi incapsulare i dati che stai trasmettendo in un NdefMessage .
  • Il dispositivo NFC che riceve i dati trasmessi deve supportare la Protocollo push NDEF com.android.npp o SNEP (Simple NDEF Exchange) del forum NFC del protocollo). Per i dispositivi con livello API 9 (Android), è richiesto il protocollo com.android.npp 2.3) al livello API 13 (Android 3.2). com.android.npp e SNEP sono entrambi obbligatori Livello API 14 (Android 4.0) e versioni successive.

Nota. Se per la tua attività è attivo Android Beam ed è in primo piano, il sistema di invio per intent standard è disattivato. Tuttavia, se anche la tua attività attiva l'invio in primo piano, può comunque analizzare i tag che corrispondono ai filtri di intent impostati l'invio in primo piano.

Per attivare Android Beam:

  1. Crea un NdefMessage che contenga i NdefRecord che vuoi inviare all'altro dispositivo.
  2. Chiama setNdefPushMessage() con NdefMessage o setNdefPushMessageCallback che passa in un oggetto NfcAdapter.CreateNdefMessageCallback nel metodo onCreate() di la tua attività. Questi metodi richiedono almeno un'attività che vuoi attivare con Android Beam, insieme a un elenco facoltativo di altre attività da attivare.

    In generale, solitamente usi setNdefPushMessage() se la tua Attività ha bisogno solo di invia sempre lo stesso messaggio NDEF quando due dispositivi sono nel raggio d'azione per comunicare. Utilizzi setNdefPushMessageCallback quando l'applicazione si preoccupa del contesto corrente dell'applicazione e vuole eseguire il push di un messaggio NDEF a seconda di ciò che fa l'utente nella tua applicazione.

L'esempio seguente mostra come un'attività semplice chiama NfcAdapter.CreateNdefMessageCallback nel metodo onCreate() di un attività (vedi AndroidBeamDemo) per l'esempio completo). Questo esempio include anche dei metodi per aiutarti a creare un record MIME:

Kotlin

package com.example.android.beam

import android.app.Activity
import android.content.Intent
import android.nfc.NdefMessage
import android.nfc.NdefRecord
import android.nfc.NfcAdapter
import android.nfc.NfcAdapter.CreateNdefMessageCallback
import android.nfc.NfcEvent
import android.os.Bundle
import android.os.Parcelable
import android.widget.TextView
import android.widget.Toast
import java.nio.charset.Charset

class Beam : Activity(), NfcAdapter.CreateNdefMessageCallback {
    
    private var nfcAdapter: NfcAdapter? = null
    private lateinit var textView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)
        textView = findViewById(R.id.textView)
        // Check for available NFC Adapter
        nfcAdapter = NfcAdapter.getDefaultAdapter(this)
        if (nfcAdapter == null) {
            Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show()
            finish()
            return
        }
        // Register callback
        nfcAdapter?.setNdefPushMessageCallback(this, this)
    }

    override fun createNdefMessage(event: NfcEvent): NdefMessage {
        val text = "Beam me up, Android!\n\n" +
                "Beam Time: " + System.currentTimeMillis()
        return NdefMessage(
                arrayOf(
                        createMime("application/vnd.com.example.android.beam", text.toByteArray())
                )
                /**
                 * The Android Application Record (AAR) is commented out. When a device
                 * receives a push with an AAR in it, the application specified in the AAR
                 * is guaranteed to run. The AAR overrides the tag dispatch system.
                 * You can add it back in to guarantee that this
                 * activity starts when receiving a beamed message. For now, this code
                 * uses the tag dispatch system.
                 *///,NdefRecord.createApplicationRecord("com.example.android.beam")
        )
    }

    override fun onResume() {
        super.onResume()
        // Check to see that the Activity started due to an Android Beam
        if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action) {
            processIntent(intent)
        }
    }

    override fun onNewIntent(intent: Intent) {
        // onResume gets called after this to handle the intent
        setIntent(intent)
    }

    /**
     * Parses the NDEF Message from the intent and prints to the TextView
     */
    private fun processIntent(intent: Intent) {
        textView = findViewById(R.id.textView)
        // only one message sent during the beam
        intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)?.also { rawMsgs ->
            (rawMsgs[0] as NdefMessage).apply {
                // record 0 contains the MIME type, record 1 is the AAR, if present
                textView.text = String(records[0].payload)
            }
        }
    }
}

Java

package com.example.android.beam;

import android.app.Activity;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Parcelable;
import android.widget.TextView;
import android.widget.Toast;
import java.nio.charset.Charset;


public class Beam extends Activity implements CreateNdefMessageCallback {
    NfcAdapter nfcAdapter;
    TextView textView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView textView = (TextView) findViewById(R.id.textView);
        // Check for available NFC Adapter
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (nfcAdapter == null) {
            Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();
            finish();
            return;
        }
        // Register callback
        nfcAdapter.setNdefPushMessageCallback(this, this);
    }

    @Override
    public NdefMessage createNdefMessage(NfcEvent event) {
        String text = ("Beam me up, Android!\n\n" +
                "Beam Time: " + System.currentTimeMillis());
        NdefMessage msg = new NdefMessage(
                new NdefRecord[] { createMime(
                        "application/vnd.com.example.android.beam", text.getBytes())
         /**
          * The Android Application Record (AAR) is commented out. When a device
          * receives a push with an AAR in it, the application specified in the AAR
          * is guaranteed to run. The AAR overrides the tag dispatch system.
          * You can add it back in to guarantee that this
          * activity starts when receiving a beamed message. For now, this code
          * uses the tag dispatch system.
          */
          //,NdefRecord.createApplicationRecord("com.example.android.beam")
        });
        return msg;
    }

    @Override
    public void onResume() {
        super.onResume();
        // Check to see that the Activity started due to an Android Beam
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
            processIntent(getIntent());
        }
    }

    @Override
    public void onNewIntent(Intent intent) {
        // onResume gets called after this to handle the intent
        setIntent(intent);
    }

    /**
     * Parses the NDEF Message from the intent and prints to the TextView
     */
    void processIntent(Intent intent) {
        textView = (TextView) findViewById(R.id.textView);
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
                NfcAdapter.EXTRA_NDEF_MESSAGES);
        // only one message sent during the beam
        NdefMessage msg = (NdefMessage) rawMsgs[0];
        // record 0 contains the MIME type, record 1 is the AAR, if present
        textView.setText(new String(msg.getRecords()[0].getPayload()));
    }
}

Tieni presente che questo codice commenta un AAR, che puoi rimuovere. Se attivi l'AAR, specificata nell'AAR riceve sempre il messaggio Android Beam. Se l'applicazione non è presente, Google Play inizia a scaricare l'applicazione. Pertanto, il seguente intento tecnicamente non è necessario per i dispositivi Android 4.0 o versioni successive se si utilizza l'AAR:

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

Con questo filtro per intent, ora è possibile avviare l'applicazione com.example.android.beam quando scansiona un tag NFC o riceve un Android Beam con un AAR di tipo com.example.android.beam o quando un messaggio in formato NDEF contiene un record MIME di tipo application/vnd.com.example.android.beam.

Anche se gli AAR garantiscono che un'applicazione venga avviata o scaricata, i filtri per intent vengono consigliata, perché ti consente di avviare un'attività a tua scelta nei dell'applicazione invece di avviare sempre l'attività principale all'interno del pacchetto specificato da un AAR. I rivenditori autorizzati non dispongono di granularità del livello di attività. Inoltre, poiché alcuni dispositivi Android non supportano supportare gli AAR, dovresti anche incorporare le informazioni identificative nel primo record NDEF del tuo NDEF messaggi e filtrarli, per sicurezza. Consulta la sezione Creare Tipi di record NDEF per ulteriori informazioni su come creare i record.