Principes de base de la technologie NFC

Ce document décrit les tâches NFC de base que vous effectuez dans Android. Il explique comment envoyer et recevoir des données NFC sous la forme de messages NDEF, et décrit les API du framework Android compatibles avec ces fonctionnalités. Pour en savoir plus sur des sujets plus avancés, y compris sur l'utilisation de données autres que NDEF, consultez NFC avancé.

La lecture des données NDEF à partir d'un tag NFC est gérée par le système de distribution des tags, qui analyse les tags NFC détectés, catégorise les données de manière appropriée et démarre une application intéressée par les données catégorisées. Une application qui souhaite gérer le tag NFC analysé peut déclarer un filtre d'intent et demander le traitement des données.

Le système de répartition des balises

Les appareils Android recherchent généralement des tags NFC lorsque l'écran est déverrouillé, sauf si le NFC est désactivé dans le menu des paramètres de l'appareil. Lorsqu'un appareil Android détecte un tag NFC, le comportement souhaité est que l'activité la plus appropriée gère l'intent sans demander à l'utilisateur quelle application utiliser. Étant donné que les appareils scannent les tags NFC à très courte portée, il est probable que si les utilisateurs devaient sélectionner manuellement une activité, ils seraient obligés d'éloigner l'appareil du tag et de rompre la connexion. Vous devez développer votre activité pour qu'elle ne gère que les tags NFC qui l'intéressent afin d'éviter que le sélecteur d'activités ne s'affiche.

Pour vous aider à atteindre cet objectif, Android fournit un système de distribution de tags spécial qui analyse les tags NFC scannés, les analyse et tente de localiser les applications intéressées par les données scannées. Pour ce faire, il:

  1. Analyser le tag NFC et déterminer le type MIME ou un URI qui identifie la charge utile de données dans le tag.
  2. Encapsulation du type MIME ou de l'URI et de la charge utile dans un intent. Ces deux premières étapes sont décrites dans la section Comment les tags NFC sont mappés aux types MIME et aux URI.
  3. Lance une activité en fonction de l'intent. Cela est décrit dans la section Comment les tags NFC sont distribués aux applications.

Comment les tags NFC sont mappés sur les types MIME et les URI

Avant de commencer à écrire vos applications NFC, il est important de comprendre les différents types de tags NFC, la façon dont le système de distribution des tags analyse les tags NFC et la tâche spéciale que le système de distribution des tags effectue lorsqu'il détecte un message NDEF. Les tags NFC sont disponibles dans un large éventail de technologies et peuvent également être écrits de différentes manières. Android est le système d'exploitation le plus compatible avec la norme NDEF, définie par le forum NFC.

Les données NDEF sont encapsulées dans un message (NdefMessage) contenant un ou plusieurs enregistrements (NdefRecord). Chaque enregistrement NDEF doit être correctement formé conformément à la spécification du type d'enregistrement que vous souhaitez créer. Android est également compatible avec d'autres types de tags qui ne contiennent pas de données NDEF, que vous pouvez utiliser à l'aide des classes du package android.nfc.tech. Pour en savoir plus sur ces technologies, consultez la section NFC avancé. L'utilisation de ces autres types de tags implique d'écrire votre propre pile de protocoles pour communiquer avec les tags. Nous vous recommandons donc d'utiliser NDEF dans la mesure du possible pour faciliter le développement et assurer une compatibilité maximale avec les appareils Android.

Remarque:Pour télécharger les spécifications NDEF complètes, accédez au site Spécifications et documents d'application du forum NFC et consultez la section Créer des types courants d'enregistrements NDEF pour obtenir des exemples de construction d'enregistrements NDEF.

Maintenant que vous avez quelques connaissances sur les tags NFC, les sections suivantes décrivent plus en détail comment Android gère les tags au format NDEF. Lorsqu'un appareil Android scanne une balise NFC contenant des données au format NDEF, il analyse le message et tente de déterminer le type MIME ou l'URI d'identification des données. Pour ce faire, le système lit le premier NdefRecord dans le NdefMessage pour déterminer comment interpréter l'intégralité du message NDEF (un message NDEF peut comporter plusieurs enregistrements NDEF). Dans un message NDEF bien formé, la première NdefRecord contient les champs suivants:

TNF (Type Name Format) 3 bits
Indique comment interpréter le champ de type de longueur variable. Les valeurs valides sont décrites dans le tableau 1.
Type de longueur variable
Décrit le type d'enregistrement. Si vous utilisez TNF_WELL_KNOWN, utilisez ce champ pour spécifier la définition du type d'enregistrement (RTD). Les valeurs RTD valides sont décrites dans le Tableau 2.
ID de longueur variable
Identifiant unique de l'enregistrement. Ce champ n'est pas souvent utilisé, mais si vous devez identifier un tag de manière unique, vous pouvez créer un ID pour celui-ci.
Charge utile à longueur variable
Charge utile de données réelle que vous souhaitez lire ou écrire. Un message NDEF peut contenir plusieurs enregistrements NDEF. Ne partez donc pas du principe que la charge utile complète se trouve dans le premier enregistrement NDEF du message NDEF.

Le système de distribution des tags utilise les champs TNF et type pour essayer de mapper un type MIME ou un URI sur le message NDEF. Si la requête aboutit, elle encapsule ces informations dans un intent ACTION_NDEF_DISCOVERED, ainsi que la charge utile réelle. Toutefois, dans certains cas, le système de distribution des tags ne peut pas déterminer le type de données en fonction du premier enregistrement NDEF. Cela se produit lorsque les données NDEF ne peuvent pas être mappées à un type MIME ou à un URI, ou lorsque la balise NFC ne contient pas de données NDEF au départ. Dans ce cas, un objet Tag contenant des informations sur les technologies de la balise et la charge utile est encapsulé dans un intent ACTION_TECH_DISCOVERED.

Le tableau 1 décrit comment le système de distribution des tags mappe le TNF et les champs de type aux types MIME ou aux URI. Il décrit également quels TNF ne peuvent pas être mappés à un type MIME ou à un URI. Dans ce cas, le système de distribution des balises revient à ACTION_TECH_DISCOVERED.

Par exemple, si le système de distribution des balises rencontre un enregistrement de type TNF_ABSOLUTE_URI, il mappe le champ de type à longueur variable de cet enregistrement sur un URI. Le système de distribution des balises encapsule cet URI dans le champ de données d'un intent ACTION_NDEF_DISCOVERED, ainsi que d'autres informations sur la balise, telles que la charge utile. D'autre part, s'il rencontre un enregistrement de type TNF_UNKNOWN, il crée un intent qui encapsule les technologies de la balise à la place.

Tableau 1. TNF compatibles et leurs mappages

Format de nom de type (TNF) Mappage
TNF_ABSOLUTE_URI URI basé sur le champ de type.
TNF_EMPTY Retour à ACTION_TECH_DISCOVERED.
TNF_EXTERNAL_TYPE URI basé sur l'URN dans le champ de type. L'URN est encodé dans le champ de type NDEF sous une forme abrégée: <domain_name>:<service_name>. Android le met en correspondance avec un URI au format suivant : vnd.android.nfc://ext/<domain_name>:<service_name>.
TNF_MIME_MEDIA Type MIME en fonction du champ de type.
TNF_UNCHANGED Non valide dans le premier enregistrement. La valeur ACTION_TECH_DISCOVERED est donc utilisée.
TNF_UNKNOWN Retour à ACTION_TECH_DISCOVERED.
TNF_WELL_KNOWN Type MIME ou URI, en fonction de la définition de type d'enregistrement (Record Type Definition, RTD), que vous définissez dans le champ "type". Pour en savoir plus sur les RTD disponibles et leurs mappages, consultez le tableau 2.

Tableau 2. RTD compatibles pour TNF_WELL_KNOWN et leurs mappages

Définition du type d'enregistrement (RTD) Mappage
RTD_ALTERNATIVE_CARRIER Retourne à ACTION_TECH_DISCOVERED.
RTD_HANDOVER_CARRIER Retourne à ACTION_TECH_DISCOVERED.
RTD_HANDOVER_REQUEST Retourne à ACTION_TECH_DISCOVERED.
RTD_HANDOVER_SELECT Retourne à ACTION_TECH_DISCOVERED.
RTD_SMART_POSTER URI basé sur l'analyse de la charge utile.
RTD_TEXT Type MIME de text/plain.
RTD_URI URI basé sur la charge utile.

Comment les tags NFC sont-ils envoyés aux applications ?

Lorsque le système de distribution des tags a terminé de créer un intent qui encapsule le tag NFC et ses informations d'identification, il envoie l'intent à l'application concernée qui filtre l'intent. Si plusieurs applications peuvent gérer l'intent, le sélecteur d'activités est présenté pour que l'utilisateur puisse sélectionner l'activité. Le système de distribution des balises définit trois intents, qui sont listés par ordre de priorité décroissante:

  1. ACTION_NDEF_DISCOVERED: cet intent permet de démarrer une activité lorsqu'une balise contenant une charge utile NDEF est lue et qu'elle est d'un type reconnu. Il s'agit de l'intent de priorité la plus élevée. Le système de distribution des balises tente de démarrer une activité avec cet intent avant tout autre intent, dans la mesure du possible.
  2. ACTION_TECH_DISCOVERED: si aucune activité n'est enregistrée pour gérer l'intent ACTION_NDEF_DISCOVERED, le système de distribution des balises tente de démarrer une application avec cet intent. Cet intent est également démarré directement (sans démarrer ACTION_NDEF_DISCOVERED au préalable) si le tag analysé contient des données NDEF qui ne peuvent pas être mappées à un type ou URI MIME, ou si le tag ne contient pas de données NDEF, mais utilise une technologie de tag connue.
  3. ACTION_TAG_DISCOVERED: cet intent est démarré si aucune activité ne gère les intents ACTION_NDEF_DISCOVERED ou ACTION_TECH_DISCOVERED.

Le système de répartition des balises fonctionne de manière basique comme suit:

  1. Essayez de démarrer une activité avec l'intent créé par le système de distribution des balises lors de l'analyse de la balise NFC (ACTION_NDEF_DISCOVERED ou ACTION_TECH_DISCOVERED).
  2. Si aucune activité ne filtre cet intent, essayez de démarrer une activité avec l'intent de priorité la plus basse suivante (ACTION_TECH_DISCOVERED ou ACTION_TAG_DISCOVERED) jusqu'à ce qu'une application filtre l'intent ou que le système de distribution des balises essaie tous les intents possibles.
  3. Si aucune application ne filtre les intents, ne faites rien.
Figure 1. Système de distribution des balises

Dans la mesure du possible, utilisez des messages NDEF et l'intent ACTION_NDEF_DISCOVERED, car il s'agit du plus spécifique des trois. Cet intent vous permet de démarrer votre application à un moment plus approprié que les deux autres intents, ce qui offre une meilleure expérience à l'utilisateur.

Demander un accès NFC dans le fichier manifeste Android

Pour pouvoir accéder au matériel NFC d'un appareil et gérer correctement les intents NFC, déclarez les éléments suivants dans votre fichier AndroidManifest.xml:

  • Élément <uses-permission> NFC pour accéder au matériel NFC :
    <uses-permission android:name="android.permission.NFC" />
    
  • Version minimale du SDK compatible avec votre application. Le niveau d'API 9 n'accepte que la distribution de tags limitée via ACTION_TAG_DISCOVERED et ne donne accès qu'aux messages NDEF via l'extra EXTRA_NDEF_MESSAGES. Aucune autre propriété de balise ni aucune autre opération d'E/S n'est accessible. Le niveau d'API 10 offre une compatibilité complète avec les lecteurs/rédacteurs, ainsi que le transfert NDEF au premier plan. Le niveau d'API 14 fournit des méthodes pratiques supplémentaires pour créer des enregistrements NDEF.
    <uses-sdk android:minSdkVersion="10"/>
    
  • L'élément uses-feature afin que votre application ne s'affiche dans Google Play que pour les appareils équipés de matériel NFC :
    <uses-feature android:name="android.hardware.nfc" android:required="true" />
    

    Si votre application utilise la fonctionnalité NFC, mais que cette fonctionnalité n'est pas essentielle, vous pouvez omettre l'élément uses-feature et vérifier la disponibilité du NFC au moment de l'exécution en vérifiant si getDefaultAdapter() est null.

Filtrer les intents NFC

Pour démarrer votre application lorsqu'un tag NFC que vous souhaitez gérer est scanné, votre application peut filtrer un, deux ou les trois intents NFC dans le fichier manifeste Android. Toutefois, vous devez généralement filtrer l'intent ACTION_NDEF_DISCOVERED pour contrôler au maximum le moment où votre application démarre. L'intent ACTION_TECH_DISCOVERED est un remplacement de ACTION_NDEF_DISCOVERED lorsqu'aucune application ne filtre ACTION_NDEF_DISCOVERED ou lorsque la charge utile n'est pas NDEF. Le filtrage pour ACTION_TAG_DISCOVERED est généralement trop général pour être utilisé. De nombreuses applications filtrent pour ACTION_NDEF_DISCOVERED ou ACTION_TECH_DISCOVERED avant ACTION_TAG_DISCOVERED. Par conséquent, votre application a peu de chances de démarrer. ACTION_TAG_DISCOVERED n'est disponible qu'en dernier recours pour les applications à filtrer dans les cas où aucune autre application n'est installée pour gérer l'intent ACTION_NDEF_DISCOVERED ou ACTION_TECH_DISCOVERED.

Étant donné que les déploiements de tags NFC varient et ne sont souvent pas sous votre contrôle, cela n'est pas toujours possible. C'est pourquoi vous pouvez utiliser les deux autres intents si nécessaire. Lorsque vous contrôlez les types de tags et les données écrites, il est recommandé d'utiliser NDEF pour mettre en forme vos tags. Les sections suivantes décrivent comment filtrer pour chaque type d'intent.

ACTION_NDEF_DISCOVERED

Pour filtrer les intents ACTION_NDEF_DISCOVERED, déclarez le filtre d'intent ainsi que le type de données que vous souhaitez filtrer. L'exemple suivant filtre les intents ACTION_NDEF_DISCOVERED avec un type MIME de text/plain:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data android:mimeType="text/plain" />
</intent-filter>

L'exemple suivant filtre un URI au format 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

Si votre activité filtre l'intent ACTION_TECH_DISCOVERED, vous devez créer un fichier de ressources XML qui spécifie les technologies compatibles avec votre activité dans un ensemble tech-list. Votre activité est considérée comme une correspondance si un ensemble tech-list est un sous-ensemble des technologies compatibles avec la balise, que vous pouvez obtenir en appelant getTechList().

Par exemple, si la balise lue est compatible avec MifareClassic, NdefFormatable et NfcA, votre ensemble tech-list doit spécifier les trois, deux ou une des technologies (et rien d'autre) pour que votre activité soit mise en correspondance.

L'exemple suivant définit toutes les technologies. Vous devez supprimer celles qui ne sont pas compatibles avec votre tag NFC. Enregistrez ce fichier (vous pouvez lui attribuer le nom de votre choix) dans le dossier <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>

Vous pouvez également spécifier plusieurs ensembles tech-list. Chacun des ensembles tech-list est considéré indépendamment, et votre activité est considérée comme une correspondance si un seul ensemble tech-list est un sous-ensemble des technologies renvoyées par getTechList(). Cela fournit une sémantique AND et OR pour les technologies correspondantes. L'exemple suivant correspond aux balises compatibles avec les technologies NfcA et Ndef, ou avec les technologies NfcB et 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>

Dans votre fichier AndroidManifest.xml, spécifiez le fichier de ressources que vous venez de créer dans l'élément <meta-data> dans l'élément <activity>, comme dans l'exemple suivant:

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

Pour en savoir plus sur l'utilisation des technologies de tags et de l'intent ACTION_TECH_DISCOVERED, consultez la section Utiliser les technologies de tags compatibles dans le document "NFC avancé".

ACTION_TAG_DISCOVERED

Pour filtrer sur ACTION_TAG_DISCOVERED, utilisez le filtre d'intent suivant:

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

Obtenir des informations à partir d'intents

Si une activité démarre en raison d'un intent NFC, vous pouvez obtenir des informations sur la balise NFC scannée à partir de l'intent. Les intents peuvent contenir les éléments supplémentaires suivants, en fonction de la balise lue:

Pour obtenir ces extras, vérifiez si votre activité a été lancée avec l'un des intents NFC pour vous assurer qu'une balise a été lue, puis obtenez les extras de l'intent. L'exemple suivant recherche l'intent ACTION_NDEF_DISCOVERED et récupère les messages NDEF à partir d'un intent supplémentaire.

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

Vous pouvez également obtenir un objet Tag à partir de l'intent, qui contiendra la charge utile et vous permettra d'énumérer les technologies du tag:

Kotlin

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

Java

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

Créer des types d'enregistrements NDEF courants

Cette section explique comment créer des types courants d'enregistrements NDEF pour faciliter l'écriture dans des tags NFC. À partir d'Android 4.0 (niveau d'API 14), la méthode createUri() est disponible pour vous aider à créer automatiquement des enregistrements URI. À partir d'Android 4.1 (niveau d'API 16), createExternal() et createMime() sont disponibles pour vous aider à créer des enregistrements MIME et des enregistrements NDEF de type externe. Utilisez ces méthodes d'assistance autant que possible pour éviter les erreurs lors de la création manuelle d'enregistrements NDEF.

Cette section explique également comment créer le filtre d'intent correspondant pour l'enregistrement. Tous ces exemples d'enregistrements NDEF doivent figurer dans le premier enregistrement NDEF du message NDEF que vous écrivez sur une balise.

TNF_ABSOLUTE_URI

Remarque:Nous vous recommandons d'utiliser le type RTD_URI plutôt que TNF_ABSOLUTE_URI, car il est plus efficace.

Vous pouvez créer un enregistrement NDEF TNF_ABSOLUTE_URI de la manière suivante :

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

Le filtre d'intent pour l'enregistrement NDEF précédent ressemblerait à ceci:

<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

Vous pouvez créer un enregistrement NDEF TNF_MIME_MEDIA de différentes manières:

Avec la méthode 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")));

Créer le NdefRecord manuellement:

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

Le filtre d'intent de l'enregistrement NDEF précédent se présente comme suit:

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

Vous pouvez créer un enregistrement NDEF TNF_WELL_KNOWN de la manière suivante:

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

Le filtre d'intent de l'enregistrement NDEF précédent se présente comme suit:

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

Vous pouvez créer un enregistrement NDEF TNF_WELL_KNOWN de différentes manières:

Avec la méthode createUri(String):

Kotlin

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

Java

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

Utilisez la méthode 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);

Créer le NdefRecord manuellement:

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

Le filtre d'intent pour l'enregistrement NDEF précédent ressemblerait à ceci:

<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

Vous pouvez créer un enregistrement NDEF TNF_EXTERNAL_TYPE de différentes manières:

Avec la méthode 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);

Créer le NdefRecord manuellement:

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

Le filtre d'intent de l'enregistrement NDEF précédent se présente comme suit:

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

Utilisez TNF_EXTERNAL_TYPE pour des déploiements de tags NFC plus génériques afin de mieux prendre en charge les appareils Android et non Android.

Remarque: Les URN pour TNF_EXTERNAL_TYPE ont un format canonique de : urn:nfc:ext:example.com:externalType. Toutefois, la spécification RTD du forum NFC déclare que la partie urn:nfc:ext: de l'URN doit être omise de l'enregistrement NDEF. Il vous suffit donc de fournir le domaine (example.com dans l'exemple) et le type (externalType dans l'exemple) séparés par le signe deux-points. Lors de l'envoi de TNF_EXTERNAL_TYPE, Android convertit l'URN urn:nfc:ext:example.com:externalType en URI vnd.android.nfc://ext/example.com:externalType, ce que déclare le filtre d'intent dans l'exemple.

Enregistrements des applications Android

Introduit dans Android 4.0 (niveau d'API 14), un enregistrement d'application Android (AAR) offre une certitude plus forte que votre application est démarrée lorsqu'un tag NFC est scanné. Un fichier AAR contient le nom de package d'une application intégré dans un enregistrement NDEF. Vous pouvez ajouter un AAR à n'importe quel enregistrement NDEF de votre message NDEF, car Android recherche des AAR dans l'intégralité du message NDEF. S'il trouve un AAR, il démarre l'application en fonction du nom du package dans l'AAR. Si l'application n'est pas présente sur l'appareil, Google Play est lancé pour la télécharger.

Les AAR sont utiles si vous souhaitez empêcher d'autres applications de filtrer pour le même intent et de gérer potentiellement des balises spécifiques que vous avez déployées. Les AAR ne sont compatibles qu'au niveau de l'application, en raison de la contrainte de nom de package, et non au niveau de l'activité comme avec le filtrage d'intent. Si vous souhaitez gérer un intent au niveau de l'activité, utilisez des filtres d'intent.

Si une balise contient un fichier AAR, le système de répartition des balises procède comme suit:

  1. Essayez de démarrer une activité à l'aide d'un filtre d'intent comme d'habitude. Si l'activité correspondant à l'intent correspond également à l'AAR, démarrez l'activité.
  2. Si l'activité qui filtre l'intent ne correspond pas à l'AAR, si plusieurs activités peuvent gérer l'intent ou si aucune activité ne le gère, démarrez l'application spécifiée par l'AAR.
  3. Si aucune application ne peut démarrer avec l'AAR, accédez à Google Play pour télécharger l'application basée sur l'AAR.

Remarque:Vous pouvez remplacer les AAR et le système de distribution d'intents par le système de distribution de premier plan, qui permet à une activité de premier plan d'avoir la priorité lorsqu'une balise NFC est détectée. Avec cette méthode, l'activité doit être au premier plan pour remplacer les AAR et le système de répartition des intents.

Si vous souhaitez toujours filtrer les balises numérisées qui ne contiennent pas d'AAR, vous pouvez déclarer des filtres d'intent comme d'habitude. Cela est utile si votre application s'intéresse à d'autres balises qui ne contiennent pas d'AAR. Par exemple, vous souhaitez peut-être vous assurer que votre application gère les balises propriétaires que vous déployez ainsi que les balises générales déployées par des tiers. N'oubliez pas que les AAR sont spécifiques aux appareils Android 4.0 ou versions ultérieures. Par conséquent, lorsque vous déployez des balises, vous devez probablement utiliser une combinaison d'AAR et de types/URI MIME pour prendre en charge la plus large gamme d'appareils possible. De plus, lorsque vous déployez des tags NFC, réfléchissez à la manière dont vous souhaitez les écrire pour permettre la prise en charge de la plupart des appareils (Android et autres). Pour ce faire, définissez un type MIME ou un URI relativement unique afin de faciliter la distinction par les applications.

Android fournit une API simple pour créer un AAR, createApplicationRecord(). Il vous suffit d'intégrer l'AAR n'importe où dans votre NdefMessage. Vous ne souhaitez pas utiliser le premier enregistrement de votre NdefMessage, sauf si l'AAR est le seul enregistrement de la NdefMessage. En effet, le système Android vérifie le premier enregistrement d'un NdefMessage pour déterminer le type MIME ou l'URI de la balise, qui est utilisé pour créer un intent que les applications peuvent filtrer. Le code suivant montre comment créer 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")}
        );
)