Forums GAMERGEN

[TUTO] Android et NFC : réception et lecture d'un TAG

[TUTO] Android et NFC : réception et lecture d'un TAG

Message non lupar Viish » 13 Mar 2011, 02:33

Bonsoir.

Avant de commencer à bricoler des programmes avancés utilisant le NFC, commençons par nous familiariser avec la base : l'envoi et la réception/lecture de TAG.

Tout d'abord intéressons nous à la réception et la lecture d'un TAG.

Nous allons commencer par créer un projet Android et y créer 2 Activity, l'une qui servira à l'envoi, l'autre à la réception.

Note : Tout d'abord il est important de préciser que lire un Tag "réel" (une puce) ou lire un Tag "émulé" par un autre terminal, pour nous, au niveau programmation, c'est la même chose. Vous n'aurez donc pas à faire la distinction dans votre programme pour prendre en compte les deux.

Rajoutons à notre Manifest les lignes suivantes (ici RActivity fera référence au nom de mon Activity qui s'occupera de gérer la réception) :
Code: Select All Code
<activity android:name=".ChatClient" android:label="ChatClient">
    <intent-filter>
        <action android:name="android.nfc.action.TAG_DISCOVERED"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

Vous remarquerez les 2 lignes atypiques dans la balise intent-filter qui servent à "inscrire" auprès du système notre Activity pour que lorsqu'un TAG arrive, le système propose (possiblement entre autres) la notre pour gérer l'évènement. Notez qu'il est possible de s'inscrire à différents niveaux d'abstraction. Regardez le schéma suivant qui montre comment le système détermine quelle Activity va être utilisée :

Celui-ci explique que lors de la découverte d'un TAG, le système va regarder si l'application au premier plan peut gérer l'événèment. Si non, il regarde si il existe une (ou plusieurs) application(s) sur le système s'étant enregistrée(s) pour gérer les évènements de type "NDEF_DISCOVERED".

Note : Même si l'application au premier plan est inscrite pour gérer les application au niveau le plus haut (ici TAG_DISCOVERED), elle aura tout de même la priorité sur les autres applications, et ce même ci ces dernières ont la "priorité" en temps normal.

Le NDEF étant le nom donné au message contenu dans les TAGs, il est donc à un niveau d'abstraction plus bas. Si tel est le cas, alors il lance l'application ou demande à l'utilisateur si plusieurs demandent la main. Sinon c'est TECH (pour technologie) découvert qui prendra la main pour le choix de l'Activity à lancer, sur le même principe que pour NDEF. Pour finir, le système en cherche une proposant ses services lorsqu'un TAG est découvert. Là encore, même chose en cas d'application(s) trouvée(s).

Note : D'une manière générale, préférez l'utilisation du TAG_DISCOVERED au NDEF_DISCOVERED, la majorité des applications du Market utilisant TAG_DISCOVERED (à moins que vous teniez absolument à avoir la priorité). Notez également qu'il est possible d'affecter un filtre à ces précédentes règles pour affiner le type de TECH, TAG ou de NDEF qui à été découvert. Ici nous nous contenterons de DEFAULT, qui regroupe tous les TAGs.

Note : L'utilisation de TECH_DISCOVERED est très utile si vous créez une application compatible qu'avec un sous ensemble des technologies NFC (comme les chips MiFare Classic).

Une fois ceci fait, attaquons nous à la partie Java du code. Créez dans votre classe une méthode (que je nommerai resoudreIntent) prenant en paramètre un Intent. Si vous êtes habitué au développement Android cela ne devrait pas vous choquer. Que va faire cette méthode ? Tout simplement vérifier la présence d'un TAG dans l'Intent courant et le cas échéant le lire. Notez ici que le système se charge de lui même de passer à l'Intent le TAG.

Attention ! Si votre Activity peut être déjà lancée par votre programme, vous devrez surcharger la méthode OnNewIntent(Intent intent) et y effectuer de la même manière un appel à votre resoudreIntent.

Vérifions maintenant dans resoudreIntent la présence d'un TAG dans l'Intent passé en paramètre :

Code: Select All Code
String action = intent.getAction();
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {


Attention ! Si vous utilisez dans le Manifest NDEF_DISCOVERED ou TECH_DISCOVERED, vous devrez utiliser respectivement ACTION_NDEF_DISCOVERED ou ACTION_TECH_DISCOVERED.

Si votre condition est fausse, à vous de faire ce que vous désirez (ce ne sera le cas que si l'utilisateur peut lancer l'Activity "à la main"). Nous allons nous interesser à la lecture de ce TAG s'il est présent. Nous allons récupérer 3 objets : un de type Tag qui contiendra l'entête du TAG, un de type byte[] qui sera l'id du tag et un de type NdefMessage[] qui contiendra le message en lui-même. Pour ce faire :

Code: Select All Code
Tag tag = (Tag) intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
byte[] id = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage[] messages;
if (rawMsgs != null) {
    msgs = new NdefMessage[rawMsgs.length];
    for (int i = 0; i < rawMsgs.length; i++) {
        messages[i] = (NdefMessage) rawMsgs[i];
}


Je ne m'attarderai pas ici sur l'id ou sur le tag, mais bien sur le message en lui même. Il faut savoir qu'un tag peut contenir plusieurs messages, donc pensez bien à vérifier le contenu de chacun. Chaque message est donc un NdefMessage, ici contenu dans notre variable messages. Notez qu'un NdefMessage est un ensemble de NdefRecord, et qu'un NdefRecord est caractérisé par 4 valeurs : son TNF (Type Name Format), son type, son id et ses données (appelées Payload).

Voici donc comment récupérer depuis un NDefMessage tous ces NdefRecord, puis pour chacun ses caractéristiques :

Code: Select All Code
NdefRecord record = messages[i].getRecords()[i];
byte[] id = record.getId();
short tnf = record.getTnf();
byte[] type = record.getType();
String message = getTextData(record.getPayload());


Note : Les TNFs et les Types disponibles sont énumérés dans la classe NdefRecord.
Note : Les TNFs commencent tous par TNF_.
Note : Les Types commencent tous par RTD_.

La fonction getTextData est générique pour les TAGs de type RTD_TEXT (texte brut). Elle est définie comme suit :

Code: Select All Code
String getTextData(byte[] payload) {
    String texteCode = ((payload[0] & 0200) == 0) ? "UTF-8" : "UTF-16";
    int langageCodeTaille = payload[0] & 0077;
    return new String(payload, langageCodeTaille + 1, payload.length - langageCodeTaille - 1, texteCode);
}


Attention : Si vous lisez des TAGs de type URI ou SMART_POSTER, la méthode de récupération des données diffère quelque peu. Vous pouvez visiter cette page qui donne des exemples de décodage en fonction du type (en Anglais) : http://programming-android.labs.oreilly.com/ch14.html

Remarquez ici que le "décryptage" du payload nécessite de connaître l'encodage utilisé ! Vous comprendrez cela mieux quand nous verrons comment créer ces messages.

Voilà, c'est terminé ! Vous pouvez maintenant créer une application capable de lire un TAG NFC quel qu'il soit pourvu que l'encodage que vous utiliserez pour les lire soit le même.

J'espère que ce tutoriel vous aura été utile et clair. Si jamais vous avez des remarques, des critiques ou des questions, s'il vous plait faites m'en part ! En attendant je vous invite à lire (dès qu'il sera disponible ce qui ne devrait tarder) la suite de ce tutoriel, consacré à l'envoie de TAGs, toujouts en utilisant le NFC.

PS : J'en profite pour préciser que cet exemple à été crée pour la version d'Android 2.3.3, soit la version 10 du SDK. Il se peut que si vous utilisez une version différente, quelques changements soient nécessaires.
Dernière édition par PLUM2010 le 14 Mar 2011, 08:55, édité 3 fois.
Mes tutos Android (en Français) : http://www.thinkdroid.eu
Viish Gamer du Dimanche
Gamer du Dimanche
Messages: 21
Inscription: 03 Aoû 2010, 00:05
Localisation: Grenoble
Prénom: Sylvain
Pays: France
Sexe: Homme

Re: [TUTO] Utilisation du NFC

Message non lupar marshallino16 » 13 Mar 2011, 13:06

C'est super mais si tu souhaites porter un tuto de toi ici, fais en c/c dans le sujet. Nous n'autorisons pas les liens vers des sites francophones traitants d'android ;)
marshallino16 Gamer Argent
Gamer Argent
Messages: 3777
Inscription: 12 Déc 2009, 18:21
Localisation: Toulouse
Pays: France
Sexe: Homme

Re: [TUTO] Utilisation du NFC

Message non lupar Viish » 13 Mar 2011, 18:57

Voilà, post modifié.
Mes tutos Android (en Français) : http://www.thinkdroid.eu
Viish Gamer du Dimanche
Gamer du Dimanche
Messages: 21
Inscription: 03 Aoû 2010, 00:05
Localisation: Grenoble
Prénom: Sylvain
Pays: France
Sexe: Homme

Re: [TUTO] Utilisation du NFC

Message non lupar marshallino16 » 14 Mar 2011, 00:56

Super ;) merci, très bon tuto
marshallino16 Gamer Argent
Gamer Argent
Messages: 3777
Inscription: 12 Déc 2009, 18:21
Localisation: Toulouse
Pays: France
Sexe: Homme


 

Retourner vers Vos tutos et astuces Android