Lecture des tags NFC avec Android

Êtes-vous curieux de savoir ce qu'est la technologie NFC et comment l'intégrer à vos propres applications Android? Ce tutoriel vous présentera rapidement le sujet avant de plonger et de vous apprendre à créer une application de lecteur NFC simple.!


Qu'est-ce que le NFC??

NFC est l'abréviation de Communication en champ proche. C'est la norme internationale pour l'échange de données sans contact. Contrairement à une large gamme d'autres technologies, telles que le réseau local sans fil et Bluetooth, la distance maximale de deux appareils est de 10 cm. Le développement de la norme a commencé en 2002 par NXP Semiconductors et Sony. Le forum NFC, un consortium de plus de 170 entreprises et membres, comprenant Mastercard, NXP, Nokia, Samsung, Intel et Google, conçoit de nouvelles spécifications depuis 2004..

Il existe diverses possibilités d'utilisation NFC avec des appareils mobiles. Par exemple, les tickets sans papier, les contrôles d'accès, les paiements sans numéraire et les clés de voiture. Avec l’aide de balises NFC, vous pouvez contrôler votre téléphone et modifier les paramètres. Les données peuvent être échangées simplement en maintenant deux appareils l'un à côté de l'autre.

Dans ce tutoriel, je souhaite expliquer comment implémenter NFC avec le SDK Android, quels sont les pièges à éviter et ce qu'il faut garder à l'esprit. Nous allons créer une application étape par étape, capable de lire le contenu des tags NFC supportant NDEF..


Technologies NFC

Il existe une variété de tags NFC qui peuvent être lus avec un smartphone. Le spectre va des simples autocollants et des porte-clés aux cartes complexes avec un matériel cryptographique intégré. Les étiquettes diffèrent également par leur technologie de puce. Le plus important est NDEF, qui est supporté par la plupart des tags. De plus, Mifare doit être mentionné car il s'agit de la technologie de puce sans contact la plus utilisée dans le monde. Certaines balises peuvent être lues et écrites, alors que d'autres sont en lecture seule ou cryptées.

Seul le format d'échange de données NFC (NDEF) est présenté dans ce didacticiel..


Ajout de la prise en charge NFC dans une application

Nous commençons avec un nouveau projet et une activité en blanc. Il est important de sélectionner une version minimale du SDK de niveau 10, car la technologie NFC n'est prise en charge qu'après Android 2.3.3. N'oubliez pas de choisir votre propre nom de package. j'ai choisi net.vrallev.android.nfc.demo, parce que vrallev.net est le domaine de mon site Web et que l’autre partie fait référence au sujet de cette application.

 

La présentation par défaut générée par Eclipse est presque suffisante pour nous. J'ai seulement ajouté un identifiant à TextView et changé le texte.

 

Pour avoir accès au matériel NFC, vous devez demander une autorisation dans le manifeste. Si l'application ne fonctionne pas sans NFC, vous pouvez spécifier la condition à l'aide de la balise uses-feature. Si la technologie NFC est requise, l'application ne peut pas être installée sur les appareils qui ne le sont pas et Google Play n'affichera votre application que pour les utilisateurs possédant un appareil NFC..

  

MainActivity doit uniquement comprendre la méthode onCreate (). Vous pouvez interagir avec le matériel via la classe NfcAdapter. Il est important de savoir si le NfcAdapter est null. Dans ce cas, le périphérique Android ne prend pas en charge NFC.

 package net.vrallev.android.nfc.demo; importer android.app.Activity; importer android.nfc.NfcAdapter; importer android.os.Bundle; importer android.widget.TextView; importer android.widget.Toast; / ** * Activité de lecture de données depuis une balise NDEF. * * @author Ralf Wondratschek * * / public class MainActivity étend l'activité public static final String TAG = "NfcDemo"; TextView privé mTextView; private NfcAdapter mNfcAdapter; @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); mTextView = (TextView) findViewById (R.id.textView_explanation); mNfcAdapter = NfcAdapter.getDefaultAdapter (this); if (mNfcAdapter == null) // Arrêtez-vous ici, nous avons certainement besoin de NFC Toast.makeText (this, "Ce périphérique ne prend pas en charge NFC.", Toast.LENGTH_LONG) .show (); terminer(); revenir;  if (! mNfcAdapter.isEnabled ()) mTextView.setText ("NFC est désactivé.");  else mTextView.setText (R.string.explanation);  handleIntent (getIntent ());  private void handleIntent (Intention Intention) // TODO: handle Intent

Si nous commençons notre application maintenant, nous pouvons voir le texte si NFC est activé ou désactivé.

Comment filtrer les tags NFC

Nous avons notre exemple d'application et souhaitons recevoir une notification du système lorsque nous attachons une balise NFC à l'appareil. Comme d'habitude, Android utilise son système Intent pour fournir des balises aux applications. Si plusieurs applications peuvent gérer l'intention, le sélecteur d'activité s'affiche et l'utilisateur peut décider quelle application sera ouverte. L'ouverture d'URL ou le partage d'informations sont traités de la même manière.


Filtre d'intention NFC

Il existe trois filtres différents pour les tags:

  1. ACTION_NDEF_DISCOVERED
  2. ACTION_TECH_DISCOVERED
  3. ACTION_TAG_DISCOVERED

La liste est triée de la priorité la plus élevée à la plus basse.

Maintenant que se passe-t-il lorsqu'un tag est associé au smartphone? Si le système détecte une balise avec prise en charge NDEF, une intention est déclenchée. Un ACTION_TECH_DISCOVERED L'intention est déclenchée si aucune activité d'aucune application n'est enregistrée pour l'intention NDEF ou si la balise ne prend pas en charge NDEF. Si, à nouveau, aucune application n'est trouvée pour l'intention ou si la technologie de la puce n'a pas pu être détectée, ACTION_TAG_DISCOVERED L'intention est renvoyée. Le graphique suivant montre le processus:


En résumé, cela signifie que chaque application doit filtrer après l’intention avec la priorité la plus élevée. Dans notre cas, il s’agit de l’intention NDEF. Nous mettons en œuvre le ACTION_TECH_DISCOVERED Intention d'abord pour souligner la différence entre les priorités.


Tech Découvert Intention

Nous devons spécifier la technologie qui nous intéresse. Pour cela, nous créons un sous-dossier appelé xml dans le res dossier. Dans ce dossier, nous créons le fichier nfc_tech_filter.xml, dans lequel nous spécifions les technologies.

    android.nfc.tech.Ndef    

Maintenant, nous devons créer un IntentFilter dans le manifeste, et l'application sera lancée lorsque nous attacherons une balise.

           

Si aucune autre application n'est enregistrée pour cette intention, notre activité commencera immédiatement. Sur mon appareil, cependant, d'autres applications sont installées, ainsi le sélecteur d'activité est affiché..



Intention découverte par le NDEF

Comme je l’ai déjà mentionné, l’intention Tech Discovered est la deuxième priorité. Cependant, comme notre application ne prend en charge que NDEF, nous pouvons utiliser l’intention découverte NDEF, qui a une priorité plus élevée. Nous pouvons à nouveau supprimer la liste des technologies et remplacer le filtre IntentFilter par le suivant.

     

Lorsque nous attachons la balise maintenant, l'application sera lancée comme avant. Il y a une différence pour moi, cependant. Le sélecteur d'activité n'apparaît pas et l'application démarre immédiatement, car l'objectif de NDEF est prioritaire et les autres applications ne sont enregistrées que pour les priorités inférieures. C'est exactement ce que nous voulons.


Expédition au premier plan

Notez qu'il reste un problème. Lorsque notre application est déjà ouverte et que nous relions le tag, l'application est ouverte une seconde fois au lieu de livrer le tag directement. Ce n'est pas notre comportement prévu. Vous pouvez contourner le problème en utilisant une répartition au premier plan.

Au lieu du système ayant distribué l'intention, vous pouvez enregistrer votre activité pour recevoir le tag directement. Ceci est important pour un flux de travail particulier, où l'ouverture d'une autre application n'a aucun sens..

J'ai inséré les explications aux endroits appropriés dans le code.

 package net.vrallev.android.nfc.demo; importer android.app.Activity; importer android.app.PendingIntent; importer android.content.Intent; importer android.content.IntentFilter; import android.content.IntentFilter.MalformedMimeTypeException; importer android.nfc.NfcAdapter; importer android.os.Bundle; importer android.widget.TextView; importer android.widget.Toast; / ** * Activité de lecture de données depuis une balise NDEF. * * @author Ralf Wondratschek * * / public class MainActivity étend l'activité public static final String MIME_TEXT_PLAIN = "text / plain"; public static final String TAG = "NfcDemo"; TextView privé mTextView; private NfcAdapter mNfcAdapter; @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); mTextView = (TextView) findViewById (R.id.textView_explanation); mNfcAdapter = NfcAdapter.getDefaultAdapter (this); if (mNfcAdapter == null) // Arrêtez-vous ici, nous avons certainement besoin de NFC Toast.makeText (this, "Ce périphérique ne prend pas en charge NFC.", Toast.LENGTH_LONG) .show (); terminer(); revenir;  if (! mNfcAdapter.isEnabled ()) mTextView.setText ("NFC est désactivé.");  else mTextView.setText (R.string.explanation);  handleIntent (getIntent ());  @Override protected void onResume () super.onResume (); / ** * Il est important que l'activité soit au premier plan (reprise). Sinon, une exception IllegalStateException est levée. * / setupForegroundDispatch (this, mNfcAdapter);  @Override protected void onPause () / ** * Appelez ceci avant onPause, sinon une exception IllegalArgumentException est également générée. * / stopForegroundDispatch (this, mNfcAdapter); super.onPause ();  @Override protected void onNewIntent (Intention d'intention) / ** * Cette méthode est appelée, lorsqu'un nouvel Intent est associé à l'instance d'activité en cours. * Au lieu de créer une nouvelle activité, onNewIntent sera appelé. Pour plus d'informations, consultez * la documentation. * * Dans notre cas, cette méthode est appelée lorsque l'utilisateur associe une balise au périphérique. * / handleIntent (intention);  private void handleIntent (Intention Intention) // TODO: handle Intent / ** * Activité @param Activité @link correspondante demandant l'envoi du premier plan. * @param adapter @link NfcAdapter utilisé pour la répartition en avant-plan. * / public static void setupForegroundDispatch (activité finale, adaptateur NfcAdapter) intention finale intention = nouvelle intention (activity.getApplicationContext (), activity.getClass ()); intent.setFlags (Intent.FLAG_ACTIVITY_SINGLE_TOP); final PendingIntent waitingIntent = PendingIntent.getActivity (activity.getApplicationContext (), 0, intention, 0); IntentFilter [] filters = new IntentFilter [1]; String [] [] techList = new String [] [] ; // Notez qu'il s'agit du même filtre que dans notre manifeste. filtres [0] = new IntentFilter (); filtres [0] .addAction (NfcAdapter.ACTION_NDEF_DISCOVERED); filtres [0] .addCategory (Intent.CATEGORY_DEFAULT); try filters [0] .addDataType (MIME_TEXT_PLAIN);  catch (MalformedMimeTypeException e) lève une nouvelle exception RuntimeException ("Vérifie ton type mime.");  adapter.enableForegroundDispatch (activité, attente en attente, filtres, liste de technologies);  / ** * Activité @param La @link BaseActivity correspondante demandant de mettre fin à la répartition en avant-plan. * @param adapter @link NfcAdapter utilisé pour la répartition en avant-plan. * / public statique statique stopForegroundDispatch (activité finale, adaptateur NfcAdapter) adaptateur.disableForegroundDispatch (activité); 

Maintenant, lorsque vous attachez une balise et que notre application est déjà ouverte, onNewIntent est appelé et aucune nouvelle activité n'est créée..


Lecture de données à partir d'une balise NDEF

La dernière étape consiste à lire les données de la balise. Les explications sont à nouveau insérées aux endroits appropriés dans le code. La NdefReaderTask est une classe interne privée.

 package net.vrallev.android.nfc.demo; importer java.io.UnsupportedEncodingException; importer java.util.Arrays; importer android.app.Activity; importer android.app.PendingIntent; importer android.content.Intent; importer android.content.IntentFilter; import android.content.IntentFilter.MalformedMimeTypeException; importer android.nfc.NdefMessage; importer android.nfc.NdefRecord; importer android.nfc.NfcAdapter; importer android.nfc.Tag; importer android.nfc.tech.Ndef; importer android.os.AsyncTask; importer android.os.Bundle; importer android.util.Log; importer android.widget.TextView; importer android.widget.Toast; / * *… Autres parties de code * / private void handleIntent (Intention Intent) Action sur les chaînes = intent.getAction (); if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals (action)) Type de chaîne = intent.getType (); if (MIME_TEXT_PLAIN.equals (type)) Tag Tag = intent.getParcelableExtra (NfcAdapter.EXTRA_TAG); new NdefReaderTask (). execute (tag);  else Log.d (TAG, "Type de mime incorrect:" + type);  else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals (action)) // Dans le cas où nous utiliserions toujours la balise Tech Discovered Intent Tag = intent.getParcelableExtra (NfcAdapter.EXTRA_TAG); String [] techList = tag.getTechList (); String searchTech = Ndef.class.getName (); for (String tech: techList) if (createdTech.equals (tech)) new NdefReaderTask (). execute (tag); Pause; 
 / ** * Tâche d'arrière-plan pour la lecture des données. Ne bloquez pas le fil de l'interface utilisateur pendant la lecture. * * @author Ralf Wondratschek * * / classe privée NdefReaderTask étend AsyncTask @Override protected String doInBackground (Tag… params) Tag tag = params [0]; Ndef ndef = Ndef.get (étiquette); if (ndef == null) // NDEF n'est pas pris en charge par cette balise. return null;  NdefMessage ndefMessage = ndef.getCachedNdefMessage (); NdefRecord [] records = ndefMessage.getRecords (); for (NdefRecord ndefRecord: records) if (ndefRecord.getTnf () == NdefRecord.TNF_WELL_KNOWN && Tableaux.equals (ndefRecord.getType (), NdefRecord.RTD_RXT_TEXT) tentative de retour de lecture  catch (UnsupportedEncodingException e) Log.e (TAG, "Codage non pris en charge", e);  return null;  La chaîne privée readText (enregistrement NdefRecord) émet une exception UnsupportedEncodingException / * * Voir la spécification de forum NFC pour "Définition du type d'enregistrement de texte" à 3.2.1 * * http://www.nfc-forum.org/specs/ * * bit_7 définit le codage * bit_6 réservé pour une utilisation future, doit être 0 * bit_5… 0 longueur du code de langue IANA * / byte [] payload = record.getPayload (); // Récupère la chaîne d'encodage du texte textEncoding = ((charge utile [0] & 128) == 0)? "UTF-8": "UTF-16"; // Récupère le code de langue int languageCodeLength = payload [0] & 0063; // String languageCode = new String (charge utile, 1, languageCodeLength, "US-ASCII"); // par exemple. "en" // Récupère le texte retourné par une nouvelle chaîne (charge, langageCodeLength + 1, payload.length - langageCodeLength - 1, textEncoding);  @Override protected void onPostExecute (Résultat de la chaîne) if (résultat! = Null) mTextView.setText ("Lire le contenu:" + résultat); 

L'application lit maintenant avec succès le contenu.



Applications utiles

Pour vérifier si les données sont lues et écrites correctement, j'aime personnellement utiliser les applications suivantes:

  • NFC TagInfo par NFC Research Lab pour la lecture de données
  • TagInfo de NXP SEMICONDUCTORS pour la lecture de données
  • TagWriter de NXP SEMICONDUCTORS pour l'écriture de données

Conclusion

Dans ce tutoriel, je vous ai montré comment extraire les données d'une balise NDEF. Vous pouvez élargir l’exemple à d’autres types de mime et technologies de puces; une fonction permettant d'écrire des données serait également utile. La première étape pour travailler avec NFC a été faite. Cependant, le SDK Android offre beaucoup plus de possibilités, comme un échange facile de données (appelé Android Beam).

Si vous souhaitez approfondir votre développement Android, consultez la vaste gamme de modèles d'applications Android utiles sur Envato Market. Ou embauchez un développeur Android sur Envato Studio.


A propos de l'auteur

Ralf Wondratschek est un étudiant en informatique originaire d'Allemagne. En plus de ses études, Ralf travaille en tant que pigiste dans le domaine de l'informatique mobile. Au cours des dernières années, il a travaillé avec Java, XML, HTML, JSP, JSF, Eclipse, Google App Engine et bien sûr Android. Il a publié deux applications Android à ce jour que vous pouvez trouver ici..

Vous pouvez en savoir plus sur le travail de l'auteur sur sa page d'accueil vrallev.net.


Sources

http://www.nfc-forum.org/home/n-mark.jpg

http://commons.wikimedia.org/wiki/File%3A%C3%9Cberlagert.jpg

http://developer.android.com/images/nfc_tag_dispatch.png