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 ces fonctionnalités. Pour des sujets plus avancés, y compris une discussion sur le travail avec des données non-NDEF, consultez la section NFC avancé.

Il existe deux cas d'utilisation principaux lorsque vous travaillez avec des données NDEF et Android:

  • Lire les données NDEF à partir d'un tag NFC
  • Transfert de messages NDEF d'un appareil à un autre avec Android BeamTM

La lecture des données NDEF d'un tag NFC est gérée par le service de distribution des tags. de sécurité, qui analyse les tags NFC détectés, classe les données de manière appropriée et commence une application qui s'intéresse aux données catégorisées. Une application qui veut gérer le tag NFC scanné peut déclarer un filtre d'intent et pour traiter les données.

La fonctionnalité Android BeamTM permet à un appareil de transmettre un message NDEF à un autre appareil en tapotant physiquement les appareils ensemble. Cette interaction permet un moyen plus facile d'envoyer des données que d'autres technologies sans fil comme le Bluetooth, car avec la technologie NFC, découverte ou association est requise. La connexion démarre automatiquement lorsque deux appareils à portée. Android Beam est disponible via un ensemble d'API NFC, de sorte que toute application peut transmettre des informations entre les appareils. Par exemple, les applications Contacts, Navigateur et YouTube utilisent Android Beam pour partager des contacts, des pages Web et des vidéos avec d'autres appareils

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 la technologie NFC est désactivée dans le menu "Paramètres" de l'appareil. Lorsqu'un appareil Android détecte un tag NFC, le comportement souhaité consiste à utiliser l'activité la plus appropriée pour gérer l'intent sans demander à l'utilisateur quelle application utiliser. Étant donné que les appareils scannent les tags NFC à une portée très courte, il est probable que les utilisateurs soient sélectionner une activité les oblige à éloigner l'appareil du Tag et à interrompre la connexion. Vous devez développer votre activité de manière à ne gérer que les tags NFC qui sont importants pour votre activité. empêcher l'affichage du sélecteur d'activité.

Pour vous aider à atteindre cet objectif, Android fournit un système spécial de distribution des balises qui analyse les Les tags NFC, les analyse et essaie de localiser les applications intéressées par les données scannées. Il le fait en:

  1. Analyser le tag NFC et déterminer le type MIME ou un URI qui identifie la charge utile des données dans le tag.
  2. Encapsuler le type MIME ou l'URI et la charge utile dans un intent. Ces deux premiers la procédure est décrite dans la section Mise en correspondance des tags NFC avec les types MIME et les URI.
  3. Lance une activité basée sur l'intent. Cette procédure est décrite à la section Modalités de distribution des tags NFC aux applications

Mappage des tags NFC avec les types MIME et les URI

Avant de commencer à écrire vos applications NFC, il est important de comprendre les différents les types de tags NFC, la façon dont le système de distribution des tags analyse les tags NFC et les tâches spécifiques que le tag effectue lorsqu'il détecte un message NDEF. Les tags NFC sont fournis un large éventail de technologies et peuvent également y écrire des données de nombreuses façons différentes. Android est le plus compatible avec la norme NDEF, qui est définie par le forum NFC.

Les données NDEF sont encapsulées dans un message (NdefMessage) qui en contient un ou plusieurs enregistrements (NdefRecord). Chaque enregistrement NDEF doit être bien formé conformément à la spécification du type d'enregistrement que vous souhaitez créer. Android prend également en charge d'autres types de tags ne contenant pas de données NDEF, que vous pouvez utiliser en utilisant les 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 écrire votre propre pile de protocoles pour communiquer avec les tags. Nous vous recommandons donc d'utiliser NDEF lorsque 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, consultez la page NFC Forum Specifications & Application Documents (en anglais) et consultez Créer des types courants d'enregistrements NDEF pour découvrir comment créer des enregistrements NDEF.

Maintenant que vous en savez un peu plus 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 analyse un tag NFC contenant un NDEF données formatées, il analyse le message et tente de déterminer le type MIME des données ou l'identification URI. Pour ce faire, le système lit la première NdefRecord dans 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é, le premier élément 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 de l'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 façon unique, vous pouvez créer un ID pour celui-ci.
Charge utile de longueur variable
La charge utile de données réelle que vous souhaitez lire ou écrire. Un NDEF peut contenir plusieurs enregistrements NDEF. Par conséquent, ne partez pas du principe que la charge utile complète se trouve dans le premier NDEF du message NDEF.

Le système de distribution des tags utilise les champs TNF et de type pour essayer de mapper un type MIME ou un URI au Message NDEF. Si l'opération réussit, elle encapsule ces informations dans un intent ACTION_NDEF_DISCOVERED avec la charge utile réelle. Cependant, sont des cas où le système de distribution des tags ne peut pas déterminer le type de données en fonction du premier NDEF enregistrer. Cela se produit lorsque les données NDEF ne peuvent pas être mappées à un type ou à un URI MIME, ou lorsque le Le tag NFC ne contient pas de données NDEF pour commencer. Dans ce cas, un objet Tag contenant des informations sur les technologies du tag et la charge utile sont encapsulé dans un intent ACTION_TECH_DISCOVERED.

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

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

Tableau 1. TNF acceptés et leur mise en correspondance

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'URL dans le champ "Type". L'URL est encodée dans le champ de type NDEF dans une forme abrégée: <domain_name>:<service_name>. Android mappe cette valeur sur 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, donc revient à ACTION_TECH_DISCOVERED
TNF_UNKNOWN Retour à ACTION_TECH_DISCOVERED.
TNF_WELL_KNOWN le type MIME ou l'URI, selon la définition du type d'enregistrement (RTD), que vous avez définie dans le . Consultez le Tableau 2 pour en savoir plus sur les RTD disponibles et leurs correspondances.

Tableau 2. RTD acceptés pour TNF_WELL_KNOWN et ses mappages

Définition du type d'enregistrement (RTD) Mappage
RTD_ALTERNATIVE_CARRIER Retour à ACTION_TECH_DISCOVERED.
RTD_HANDOVER_CARRIER Retour à ACTION_TECH_DISCOVERED.
RTD_HANDOVER_REQUEST Retour à ACTION_TECH_DISCOVERED.
RTD_HANDOVER_SELECT Retour à 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é, créez un intent qui encapsule le tag NFC et ses d'informations d'identification, il envoie l'intent à une application intéressée des filtres pour l'intent. Si plusieurs applications peuvent gérer l'intent, le sélecteur d'activité s'affiche afin que l'utilisateur puisse sélectionner l'activité. Le système de distribution des tags définit trois intents, qui sont classés par ordre décroissant de priorité:

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

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

  1. Essayer de démarrer une activité avec l'intent créé par le système de distribution des tags lors de l'analyse du tag NFC ACTION_NDEF_DISCOVERED ou ACTION_TECH_DISCOVERED).
  2. Si aucun filtre d'activité n'est appliqué à cet intent, essayez de démarrer une activité avec l'élément l'intent ayant la priorité la plus faible (ACTION_TECH_DISCOVERED ou ACTION_TAG_DISCOVERED) jusqu'à ce qu'une application filtre ou jusqu'à ce que le système de distribution des tags essaie tous les intents possibles.
  3. Si aucune application ne filtre les intents, ne faites rien.
<ph type="x-smartling-placeholder">
</ph>
Figure 1 Système de distribution de tags

Dans la mesure du possible, utilisez les messages NDEF et l'intent ACTION_NDEF_DISCOVERED, car il s'agit de l'intent le plus spécifique les trois. Cet intent vous permet de lancer votre application à un moment plus approprié deux autres intents, ce qui améliore l'expérience utilisateur.

Demander un accès NFC dans le fichier manifeste Android

Avant de pouvoir accéder au matériel NFC d'un appareil et de gérer correctement les intents NFC, déclarez ces dans votre fichier AndroidManifest.xml:

  • L'élément NFC <uses-permission> 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 une distribution limitée des tags via ACTION_TAG_DISCOVERED et ne donne l'accès aux messages NDEF via l'extra EXTRA_NDEF_MESSAGES. Non d'autres propriétés de tag ou opérations d'E/S sont accessibles. Niveau d'API 10 Compatibilité complète avec les lecteurs/rédacteurs, transfert NDEF au premier plan et niveau d'API 14 permet de transférer plus facilement des messages NDEF vers d'autres appareils avec Android Beam et d'autres méthodes pratiques pour créer des enregistrements NDEF.
    <uses-sdk android:minSdkVersion="10"/>
    
  • L'élément uses-feature afin que votre application s'affiche dans Google Play uniquement pour les appareils dotés de matériel NFC:
    <uses-feature android:name="android.hardware.nfc" android:required="true" />
    

    Si votre application utilise la fonctionnalité NFC, mais que celle-ci n'est pas essentielle pour votre application, vous pouvez omettre l'élément uses-feature et vérifier la disponibilité de la technologie NFC à l'adresse l'environnement d'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. Cependant, vous vous souhaitez généralement filtrer l'intent ACTION_NDEF_DISCOVERED pour un contrôle maximal sur le démarrage de votre application. L'intent ACTION_TECH_DISCOVERED est une solution de remplacement pour ACTION_NDEF_DISCOVERED lorsqu'aucune application n'est filtrée ACTION_NDEF_DISCOVERED ou lorsque la charge utile n'est pas NDEF. Le filtrage de ACTION_TAG_DISCOVERED est généralement trop général une catégorie à filtrer. De nombreuses applications filtreront ACTION_NDEF_DISCOVERED ou ACTION_TECH_DISCOVERED avant le ACTION_TAG_DISCOVERED. Il est donc peu probable que votre application présente à partir de zéro. ACTION_TAG_DISCOVERED n'est disponible qu'en dernier recours des applications lorsqu'aucune autre application n'est installée pour gérer Intent ACTION_NDEF_DISCOVERED ou ACTION_TECH_DISCOVERED.

Les déploiements de tags NFC étant variables et souvent sous votre contrôle, ce n'est pas toujours le cas. c'est pourquoi vous pouvez revenir aux deux autres intents si nécessaire. Lorsque vous avez sur les types de tags et de données écrites, nous vous recommandons d'utiliser NDEF pour formater votre . Les sections suivantes décrivent comment filtrer chaque type d'intent.

ACTION_NDEF_DISCOVERED

Pour filtrer les intents ACTION_NDEF_DISCOVERED, déclarez le filtre d'intent et le type de données que vous souhaitez filtrer. La exemples de filtres suivants pour ACTION_NDEF_DISCOVERED intents 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 sous la forme suivante : 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>

TECHNOLOGIE D'ACTION DÉCOUVERTE

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 est considéré comme une correspondance si un ensemble tech-list est un sous-ensemble des technologies pris en charge par la balise, que vous pouvez obtenir en appelant getTechList().

Par exemple, si le tag analysé est compatible avec MifareClassic, NdefFormatable et NfcA, votre L'ensemble tech-list doit spécifier les trois, deux ou l'une des technologies (et aucun élément else) pour que votre activité soit mise en correspondance.

L'exemple suivant définit toutes les technologies. Vous devez supprimer celles qui ne le sont pas compatible avec votre tag NFC. Enregistrez ce fichier (vous pouvez lui attribuer le nom de votre choix) dans 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 tech-list est considéré comme indépendant, et votre activité est considérée comme une correspondance si un L'ensemble tech-list est un sous-ensemble des technologies renvoyées par getTechList(). Cela fournit AND et OR pour les technologies de mise en correspondance. L'exemple suivant correspond aux balises compatibles avec le paramètre technologies NfcA et Ndef, ou compatibles 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> à l'intérieur de <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 balise et de l'intent ACTION_TECH_DISCOVERED, consultez Utiliser des balises compatibles technologies décrites dans le document "NFC avancé".

ACTION_TAG_DÉCOUVERTE

Pour filtrer sur ACTION_TAG_DISCOVERED, utilisez l'intent suivant filtre:

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

Obtenir des informations à partir des intents

Si une activité démarre en raison d'un intent NFC, vous pouvez obtenir des informations sur l'objet NFC scanné. de l'intent. Les intents peuvent contenir les extras suivants en fonction de la balise analysée:

Pour obtenir ces extras, vérifiez si votre activité a été lancée avec l'un des les intents NFC pour vérifier qu'un tag a bien été scanné, puis obtenir les extras l'intention. L'exemple suivant vérifie la présence de ACTION_NDEF_DISCOVERED intent et obtient les messages NDEF 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 contenir la charge utile et vous permettre 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 courants d'enregistrements NDEF

Cette section explique comment créer des types courants d'enregistrements NDEF pour vous aider lors de l'écriture dans Tags NFC ou envoi de données avec Android Beam À partir d'Android 4.0 (niveau d'API 14), La méthode createUri() est disponible pour vous aider à créer automatiquement les enregistrements URI. À partir d'Android 4.1 (niveau d'API 16), createExternal() et createMime() sont disponibles pour vous aider à créer Enregistrements MIME et 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 les d'intent pour l'enregistrement. Tous ces exemples d'enregistrements NDEF doivent se trouver dans le premier NDEF d'enregistrement du message NDEF que vous écrivez dans un tag ou via un partage partagé.

TNF_ABSOLUTE_URI

Remarque:Nous vous recommandons d'utiliser le Saisissez RTD_URI à la place. de 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éez 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 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: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 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: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");

Avec 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éez 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 dans le code suivant : 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éez 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 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="vnd.android.nfc"
        android:host="ext"
        android:pathPrefix="/com.example:externalType"/>
</intent-filter>

Utilisez TNF_EXTERNAL_TYPE pour déployer davantage de tags NFC génériques afin de mieux prendre en charge ces deux types de tags. Appareils Android et appareils non compatibles avec Android

Remarque: Les URN pour TNF_EXTERNAL_TYPE ont le format canonique suivant: urn:nfc:ext:example.com:externalType, mais la spécification NFC Forum RTD déclare que la partie urn:nfc:ext: de l'URL doit être omise du 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'URL urn:nfc:ext:example.com:externalType en URI vnd.android.nfc://ext/example.com:externalType, ce qui correspond à le filtre d'intent déclaré dans l'exemple.

Enregistrements d'applications Android

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

Les AAR sont utiles si vous souhaitez empêcher d'autres applications de filtrer pour le même intent et pour gérer potentiellement les balises que vous avez déployées. Les AAR ne sont acceptés qu'au niveau au niveau de l'application, en raison de la contrainte du nom du package, et non au niveau de l'activité, comme le filtrage d'intents. 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é qui correspond l'intent correspond également à l'AAR, lancez l'activité.
  2. Si l'activité qui filtre l'intent ne correspond pas à AAR, si plusieurs activités peuvent gérer l'intent ou si aucune activité ne gère l'intent, 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 l'application en fonction de l'AAR.

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

Si vous souhaitez toujours filtrer les tags analysés qui ne contiennent pas d'AAR, vous pouvez déclarer comme d'habitude. Ceci est utile si d'autres balises s'intéressent à votre application. qui ne contiennent pas d'AAR. Par exemple, vous voulez peut-être garantir que votre application gère les tags propriétaires que vous déployez, ainsi que les tags généraux déployés par des tiers. À retenir que les AAR sont propres aux appareils Android 4.0 ou version ultérieure. Lorsque vous déployez des balises, pour utiliser une combinaison d'AAR et de types/URI MIME afin de prendre en charge une large gamme d'appareils. Dans De plus, lorsque vous déployez des tags NFC, réfléchissez à la manière dont vous souhaitez les écrire pour activer compatible avec la plupart des appareils (appareils Android et autres). Pour ce faire, vous pouvez définir un type MIME ou un URI relativement unique pour permettre aux applications de les distinguer plus facilement.

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

Partager des messages NDEF vers d'autres appareils

Android Beam permet d'échanger facilement des données peer-to-peer entre deux appareils Android. La l'application qui souhaite partager des données avec un autre appareil doit être exécutée au premier plan, et l'appareil la réception des données ne doivent pas être verrouillées. Lorsque l'appareil de partage est suffisamment proche du l'appareil récepteur, celui-ci affiche le message UI. L'utilisateur peut alors choisir si le message doit être partagé avec le périphérique destinataire.

Remarque:La transmission NDEF au premier plan était disponible au niveau d'API 10. qui offre des fonctionnalités semblables à celles d'Android Beam. Ces API sont depuis abandonnées, mais sont disponibles pour prendre en charge les appareils plus anciens. Pour en savoir plus, consultez les enableForegroundNdefPush().

Vous pouvez activer Android Beam pour votre application en appelant l'une des deux méthodes suivantes:

  • setNdefPushMessage(): accepte un NdefMessage à définir comme message à partager. Partage automatique du message lorsque deux appareils sont suffisamment proches.
  • setNdefPushMessageCallback(): Accepte un rappel contenant une createNdefMessage() qui est appelée lorsqu'un appareil est à portée pour le partage de données. Le rappel vous permet de créer le message NDEF que si nécessaire.

Une activité ne peut envoyer qu'un seul message NDEF à la fois. setNdefPushMessageCallback() est donc prioritaire. supérieure à setNdefPushMessage() si les deux sont définis. Pour utiliser Android Beam, les consignes générales suivantes doivent être respectées:

  • L'activité qui transmet les données doit se trouver au premier plan. Les deux appareils doivent avoir leurs écrans déverrouillés.
  • Vous devez encapsuler les données que vous partagez dans un NdefMessage. .
  • Le périphérique NFC qui reçoit les données transmises doit être compatible avec la Protocole push NDEF de com.android.npp ou protocole SNEP (Simple NDEF Exchange) du forum NFC Protocole). Le protocole com.android.npp est requis pour les appareils avec le niveau d'API 9 (Android). 2.3) au niveau d'API 13 (Android 3.2). com.android.npp et SNEP sont tous deux obligatoires sur Niveau d'API 14 (Android 4.0) ou version ultérieure.

Remarque:Si votre activité active Android Beam et qu'elle est au premier plan, le système standard de distribution des intents est désactivé. Cependant, si votre activité active de premier plan, il peut toujours analyser les balises qui correspondent aux filtres d'intent définis dans le la répartition au premier plan.

Pour activer Android Beam:

  1. Créer un NdefMessage contenant les NdefRecord que vous souhaitez transmettre à l'autre appareil.
  2. Appelez setNdefPushMessage() avec un NdefMessage ou appelez setNdefPushMessageCallback en transmettant un objet NfcAdapter.CreateNdefMessageCallback dans la méthode onCreate() de votre activité. Ces méthodes nécessitent au moins une activité que vous souhaitez activer avec Android Beam, avec une liste facultative d'autres activités à activer.

    En général, vous utilisez normalement setNdefPushMessage() si votre activité n'a besoin que transmettre le même message NDEF à tout moment, lorsque deux appareils sont à portée pour communiquer. Vous utilisez setNdefPushMessageCallback lorsque votre L'application se soucie du contexte actuel et souhaite transmettre un message NDEF en fonction de ce que l'utilisateur fait dans votre application.

L'exemple suivant montre comment une activité simple appelle NfcAdapter.CreateNdefMessageCallback dans la méthode onCreate() d'une (voir AndroidBeamDemo) pour l'échantillon complet). Cet exemple propose également des méthodes pour vous aider à créer un enregistrement 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()));
    }
}

Notez que ce code commente un fichier AAR, que vous pouvez supprimer. Si vous activez l'AAR, l'application spécifiée dans l'AAR reçoit toujours le message Android Beam. Si l'application n'est pas présent, Google Play commence à télécharger l'application. Par conséquent, l'intent suivant n'est techniquement pas nécessaire pour les appareils Android 4.0 ou version ultérieure si l'AAR est utilisé:

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

Avec ce filtre d'intent, l'application com.example.android.beam peut maintenant être lancée lorsqu'il scanne un tag NFC ou reçoit un Android Beam avec un AAR de Type com.example.android.beam, ou lorsqu'un message au format NDEF contient un enregistrement MIME de type application/vnd.com.example.android.beam.

Même si les AAR garantissent qu'une application est lancée ou téléchargée, les filtres d'intent sont car ils vous permettent de démarrer l'activité de votre choix application au lieu de toujours démarrer l'activité principale dans le package spécifié par un AAR. Les AAR n'ont pas de précision au niveau de l'activité. De plus, certains appareils Android prendre en charge les AAR, vous devez également intégrer des informations d'identification dans le premier enregistrement NDEF de votre et les filtrer également, au cas où. Voir la section Création de rapports Types d'enregistrements NDEF pour en savoir plus sur la création d'enregistrements