Amosse EDOUARD > MBDS - CASABLANCA 2014-2015 > Lecture et Ecriture de tags NFC avec Android

Lecture et Ecriture de tags NFC avec Android

De $1

Table des matières
  1. 1. Dans cette séance, nous allons modifier l'application des séances précédentes afin d'y intégrer la technologie NFC.  Nous nous limiterons uniquement au mode de lecture/ecriture de tag.  A la fin de l'inscription d'un utilisateur, le serveur renvoie un numéro qui identifie de manière unique l'utilisateur sur le serveur; dans un premier temps, nous allons récupérer ce numéro l'écrire sur un tag NFC (le message est à écrire au format NDEF).  Dans un second temps, nous allons créer une nouvelle ativité qui lira le contenu d'un tag et afficher l'utilisateur associé au numéro cosntenu dans le tag.  P.S: Il vous faudra un téléphone Android NFC pour tester cette étape.  Modification du Manifest Vérifiez si le téléphone supporte la technologie NFC  <uses-feature android:name="android.hardware.nfc" android:required="true"/> Le NFC est supporté à partir de l'API version 10.  Vérifiez dans votre fichier .gradle que la version minimale de votre application est supérieure ou égale à 10   defaultConfig { applicationId "..."minSdkVersion 17targetSdkVersion 21versionCode 1versionName "1.0"} Ajoutez les permissions necessaires à votre application afin de pouvoir utiliser le NFC.  <uses-permission android:name="android.permission.NFC"></uses-permission> Ajoutez une nouvelle activité à votre application (TagWriterActivity).  Cette activité sera destinée à écrire des informations sur un tag NFC. Après avoir inscrit un utilisateur sur le serveur, vous récupérerez l'identifiant unique renvoyé par le serveur puis vous appelerez l'activité TagWriterActivity  en lui passant en paramètre l'identifiant à écrire sur le tag.  Imlpémentation de la classe TagWriterActivity Surchagez la méthode onResume de l'activité pour activez la découverte de tag @Override protected void onResume() { super.onResume(); //Recupérez le lecteur NFC par défaut (normalement c'est celui qui est intégré au téléphone) mNfcAdapter = NfcAdapter.getDefaultAdapter(this); // Handle all of our received NFC intents in this activity. mNfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); // Nous voulons découvrir deux types de tag //1) Ceux qui sont formattés NDEF IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); try { ndefDetected.addDataType("text/plain"); } catch (IntentFilter.MalformedMimeTypeException e) { } mNdefExchangeFilters = new IntentFilter[] { ndefDetected }; // Et ceux qui ne sont pas encore formattés IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED); mWriteTagFilters = new IntentFilter[] { tagDetected }; //Maintenant nous indiquons au capteur de nous notifier à la decouverte de ces deux types de tags mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent, mNdefExchangeFilters, null); } Surchagez de même la méthode onPause de l'activité pour desactivté l'ecoute des tags quand lactivité est mise en pause.   @Override protected void onPause() { super.onPause(); mNfcAdapter.disableForegroundNdefPush(this); } A la lecture d'un tag, Android crée automatiquement une nouvelle intention contenant les informations sur le tag detectés; pour pouvoir récupérer cette intention, il vous faudra surcharger la méthode onNewIntent de l'activité.  Cette méthode sera appelé chaque fois qu'un tag est detecté par le lecteur.  @Override protected void onNewIntent(Intent intent) { // Le tag est déjà formatté et contient un message de type NDEF // Dans ce cas on demande à l'utilisateur de confirmer la réécriture if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) { NdefMessage[] msgs = getNdefMessages(intent); detectedTag= intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); promptForContent(msgs[0]); } // Le tag est vierge if ( NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) { detectedTag= intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); writeTag(getMessageAsNdef(String.valueOf(idclient)); } } //Cette méthode convertit une string au format NDEF private NdefMessage getMessageAsNdef(String message) { byte[] textBytes = message.getBytes(); NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, "text/plain".getBytes(), new byte[] {}, textBytes); return new NdefMessage(new NdefRecord[] { textRecord }); } //Cette méthode lit un message NDEF contenu dans un tag private NdefMessage[] getNdefMessages(Intent intent) { // Parse the intent NdefMessage[] msgs = null; String action = intent.getAction(); if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) { Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if (rawMsgs != null) { msgs = new NdefMessage[rawMsgs.length]; for (int i = 0; i < rawMsgs.length; i++) { msgs[i] = (NdefMessage) rawMsgs[i]; } } else { // Unknown tag type byte[] empty = new byte[] {}; NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty); NdefMessage msg = new NdefMessage(new NdefRecord[] { record }); msgs = new NdefMessage[] { msg }; } } else { Log.d(TAG, "Unknown intent."); finish(); } return msgs; } //Cette methode affiche un dialog à l'utiliser lui invitant à écraser les données du tag decouvert private void promptForContent(final NdefMessage msg) { new AlertDialog.Builder(this).setTitle(R.string.app_name).setMessage("Voulez vous remplacer " + new String(msg.getRecords()[0].getPayload()) + " par " + idclient + " ?") .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { writeTag(getMessageAsNdef(idclient)); } }) .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { } }).show(); } Méthode permettant de formatter et\ou d'écrire de nouvelles données sur un tag NFC  boolean writeTag(NdefMessage message) { int size = message.toByteArray().length; try { Ndef ndef = Ndef.get(detectedTag); if (ndef != null) { ndef.connect(); if (!ndef.isWritable()) { error("Tag is read-only."); return false; } if (ndef.getMaxSize() < size) { error("Tag capacity is " + ndef.getMaxSize() + " bytes, message is " + size + " bytes."); return false; } ndef.writeNdefMessage(message); toast("Le message a ete ecrit avec succes."); long id = System.currentTimeMillis() ; return true; } else { NdefFormatable format = NdefFormatable.get(detectedTag); if (format != null) { try { format.connect(); format.format(message); long id = System.currentTimeMillis() ; //setNoteBody(String.valueOf(id)); toast("Le message a ete ecrit avec succes."); return true; } catch (IOException e) { error("Failed to format tag. " +e.getMessage()); return false; } } else { error("Tag doesn't support NDEF."); return false; } } } catch (Exception e) { error("Failed to write tag " + e.getMessage()); } return false; } private void toast(String text) { Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); } private void error(String text) { new AlertDialog.Builder(this) .setTitle("Erreur") .setMessage(text) .setPositiveButton("OK",null) .show(); } Pour que votre application soir plus parlante, il vous faudra modifier le layout de l'activité en y ajoutant un gentil petit message et une image de tag NFC pourquoi pas :)   Maintenant faites le lien avec l'activité (RegisterActivity) et faites en sortes que ca marche!  Lecture de l'identifiant de l'utilisateur dans un tag NFC Dans cette partie nous allons procéder à la lecture d'une information de type NDEF stockée dans un tag NFC (l'information que vous venez d'écrire dans le tag).  L'objecif consiste à récupérer l'identifiant du client dans un tag et lancer une requête au web service afin de récupérer les informations relatives au client dont l'id est stocké dans le tag NFC.  Si vous aviez compris le principe de fonctionnement des services Web REST, vous devriez pouvoir construire facilement cette requete; sinon RTFM.  Nous voulons que cette action puisse s'executer independamment que l'application soit lancée ou non; pour cela nous allons modifier la classe (AficherActivity) que vous avez créée dans le TP1 afin d'y ajouter des filtres d'intention pour la découverte de tags. Modifiez la balise de déclaration de l'activité  dans le Manifest, en y ajoutant:  <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <action android:name="android.nfc.action.TAG_DISCOVERED" /> <action android:name="android.nfc.action.TECH_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" /> </intent-filter> <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> Ces filtres d'intention vous permettront d'etre notifié par le système à la decouverte de tags NFC. Nous voulons dans cet exemple écouter tout type de tags NFC.  Comme dans le cas précédent nous allons modifier la méthode onResume pour activer la decouverte de nouveaux tags ou récupérer le tag qui a lancé a été utilisé pour lancer l'activité.  @Override protected void onResume() { super.onResume(); mNfcAdapter = NfcAdapter.getDefaultAdapter(this); // Handle all of our received NFC intents in this activity. mNfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); // Nous voulons découvrir deux types de tag //1) Ceux qui sont formattés NDEF IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); try { ndefDetected.addDataType("text/plain"); } catch (IntentFilter.MalformedMimeTypeException e) { } mNdefExchangeFilters = new IntentFilter[] { ndefDetected }; // Et ceux qui ne sont pas encore formattés IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED); mWriteTagFilters = new IntentFilter[] { tagDetected }; //Maintenant nous indiquons au capteur de nous notifier à la decouverte de ces deux types de tags mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent, mNdefExchangeFilters, null); if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) { NdefMessage[] msgs = getNdefMessages(getIntent()); detectedTag= getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG); promptForContent(msgs[0]); } } A partir de là, vous pouvez adapter le code et faire en sorte de récupérer l'identifiant du client, faire une requete http au WS et afficher les détails du client dans l'interface de l'activité.   

Dans cette séance, nous allons modifier l'application des séances précédentes afin d'y intégrer la technologie NFC.  Nous nous limiterons uniquement au mode de lecture/ecriture de tag.  A la fin de l'inscription d'un utilisateur, le serveur renvoie un numéro qui identifie de manière unique l'utilisateur sur le serveur; dans un premier temps, nous allons récupérer ce numéro l'écrire sur un tag NFC (le message est à écrire au format NDEF).  Dans un second temps, nous allons créer une nouvelle ativité qui lira le contenu d'un tag et afficher l'utilisateur associé au numéro cosntenu dans le tag. 

P.S: Il vous faudra un téléphone Android NFC pour tester cette étape. 

Modification du Manifest

  • Vérifiez si le téléphone supporte la technologie NFC 
<uses-feature
android:name="android.hardware.nfc"
android:required="true"/>
  • Le NFC est supporté à partir de l'API version 10.  Vérifiez dans votre fichier .gradle que la version minimale de votre application est supérieure ou égale à 10

 

defaultConfig {
applicationId "..."
minSdkVersion 17
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
  • Ajoutez les permissions necessaires à votre application afin de pouvoir utiliser le NFC. 
<uses-permission android:name="android.permission.NFC"></uses-permission>

Ajoutez une nouvelle activité à votre application (TagWriterActivity).  Cette activité sera destinée à écrire des informations sur un tag NFC. Après avoir inscrit un utilisateur sur le serveur, vous récupérerez l'identifiant unique renvoyé par le serveur puis vous appelerez l'activité TagWriterActivity  en lui passant en paramètre l'identifiant à écrire sur le tag. 

Imlpémentation de la classe TagWriterActivity

Surchagez la méthode onResume de l'activité pour activez la découverte de tag

@Override
    protected void onResume() {
        super.onResume();
        //Recupérez le lecteur NFC par défaut (normalement c'est celui qui est intégré au téléphone)
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        // Handle all of our received NFC intents in this activity.
        mNfcPendingIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

        // Nous voulons découvrir deux types de tag 
        //1) Ceux qui sont formattés NDEF 
        IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        try {
            ndefDetected.addDataType("text/plain");
        } catch (IntentFilter.MalformedMimeTypeException e) { }
        mNdefExchangeFilters = new IntentFilter[] { ndefDetected };

        // Et ceux qui ne sont pas encore formattés 
        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
        mWriteTagFilters = new IntentFilter[] { tagDetected };
       
        //Maintenant nous indiquons au capteur de nous notifier à la decouverte de ces deux types de tags 
        mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent, mNdefExchangeFilters, null);
        
    }

Surchagez de même la méthode onPause de l'activité pour desactivté l'ecoute des tags quand lactivité est mise en pause.  

@Override
    protected void onPause() {
        super.onPause();
        mNfcAdapter.disableForegroundNdefPush(this);
}

A la lecture d'un tag, Android crée automatiquement une nouvelle intention contenant les informations sur le tag detectés; pour pouvoir récupérer cette intention, il vous faudra surcharger la méthode onNewIntent de l'activité.  Cette méthode sera appelé chaque fois qu'un tag est detecté par le lecteur. 

@Override
    protected void onNewIntent(Intent intent) {
// Le tag est déjà formatté et contient un message de type NDEF 
        // Dans ce cas on demande à l'utilisateur de confirmer la réécriture 
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
            NdefMessage[] msgs = getNdefMessages(intent);
            detectedTag= intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            promptForContent(msgs[0]);

        }
// Le tag est vierge
        if ( NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
        detectedTag= intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            writeTag(getMessageAsNdef(String.valueOf(idclient)); 

        }
}
//Cette méthode convertit une string au format NDEF 
private NdefMessage getMessageAsNdef(String message) {
        byte[] textBytes = message.getBytes();
        NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, "text/plain".getBytes(),
                new byte[] {}, textBytes);
        return new NdefMessage(new NdefRecord[] {
                textRecord
        });
    }
//Cette méthode lit un message NDEF contenu dans un tag 
private NdefMessage[] getNdefMessages(Intent intent) {
        // Parse the intent
        NdefMessage[] msgs = null;
        String action = intent.getAction();
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
                || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
            Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            if (rawMsgs != null) {
                msgs = new NdefMessage[rawMsgs.length];
                for (int i = 0; i < rawMsgs.length; i++) {
                    msgs[i] = (NdefMessage) rawMsgs[i];
                }
            } else {
                // Unknown tag type
                byte[] empty = new byte[] {};
                NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
                NdefMessage msg = new NdefMessage(new NdefRecord[] {
                        record
                });
                msgs = new NdefMessage[] {
                        msg
                };
            }
        } else {
            Log.d(TAG, "Unknown intent.");
            finish();
        }
        return msgs;
    }
//Cette methode affiche un dialog à l'utiliser lui invitant à écraser les données du tag decouvert 
private void promptForContent(final NdefMessage msg) {
        new AlertDialog.Builder(this).setTitle(R.string.app_name).setMessage("Voulez vous remplacer " + new String(msg.getRecords()[0].getPayload()) + " par " + idclient + " ?")
                .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface arg0, int arg1) {
                        writeTag(getMessageAsNdef(idclient)); 
                    }
                })
                .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface arg0, int arg1) {

                    }
                }).show();
    }

Méthode permettant de formatter et\ou d'écrire de nouvelles données sur un tag NFC 

boolean writeTag(NdefMessage message) {
        int size = message.toByteArray().length;
       try {
            Ndef ndef = Ndef.get(detectedTag);
            if (ndef != null) {
                ndef.connect();
                if (!ndef.isWritable()) {
                    error("Tag is read-only.");
                    return false;
                }
                if (ndef.getMaxSize() < size) {
                    error("Tag capacity is " + ndef.getMaxSize() + " bytes, message is " + size
                            + " bytes.");
                    return false;
                }
                ndef.writeNdefMessage(message);
                toast("Le message a ete ecrit avec succes.");
                long id = System.currentTimeMillis() ;
                return true;
            } else {
                NdefFormatable format = NdefFormatable.get(detectedTag);
                if (format != null) {

                    try {

                        format.connect();

                        format.format(message);

                        long id = System.currentTimeMillis() ;

                        //setNoteBody(String.valueOf(id));

                        toast("Le message a ete ecrit avec succes.");

                        return true;

                    } catch (IOException e) {

                        error("Failed to format tag. " +e.getMessage());

                        return false;

                    }

                } else {

                    error("Tag doesn't support NDEF.");

                    return false;

                }

            }

        } catch (Exception e) {

            error("Failed to write tag " + e.getMessage());

        }


        return false;

    }
private void toast(String text) {
        Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
    }
    
    private void error(String text) {
       new AlertDialog.Builder(this)
               .setTitle("Erreur")
               .setMessage(text)
               .setPositiveButton("OK",null) 
               .show();
    }

Pour que votre application soir plus parlante, il vous faudra modifier le layout de l'activité en y ajoutant un gentil petit message et une image de tag NFC pourquoi pas :)

 Screenshot_2014-12-19-00-00-30.png

Maintenant faites le lien avec l'activité (RegisterActivity) et faites en sortes que ca marche! 

Lecture de l'identifiant de l'utilisateur dans un tag NFC

Dans cette partie nous allons procéder à la lecture d'une information de type NDEF stockée dans un tag NFC (l'information que vous venez d'écrire dans le tag).  L'objecif consiste à récupérer l'identifiant du client dans un tag et lancer une requête au web service afin de récupérer les informations relatives au client dont l'id est stocké dans le tag NFC.  Si vous aviez compris le principe de fonctionnement des services Web REST, vous devriez pouvoir construire facilement cette requete; sinon RTFM. 

Nous voulons que cette action puisse s'executer independamment que l'application soit lancée ou non; pour cela nous allons modifier la classe (AficherActivity) que vous avez créée dans le TP1 afin d'y ajouter des filtres d'intention pour la découverte de tags.

Modifiez la balise de déclaration de l'activité  dans le Manifest, en y ajoutant: 

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <action android:name="android.nfc.action.TAG_DISCOVERED" />
    <action android:name="android.nfc.action.TECH_DISCOVERED"/>
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="text/plain"  />
    <meta-data android:name="android.nfc.action.TECH_DISCOVERED"
    android:resource="@xml/nfc_tech_filter" />
</intent-filter>
<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>

Ces filtres d'intention vous permettront d'etre notifié par le système à la decouverte de tags NFC. Nous voulons dans cet exemple écouter tout type de tags NFC. 

Comme dans le cas précédent nous allons modifier la méthode onResume pour activer la decouverte de nouveaux tags ou récupérer le tag qui a lancé a été utilisé pour lancer l'activité. 

@Override

    protected void onResume() {

        super.onResume();

        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);

        // Handle all of our received NFC intents in this activity.

        mNfcPendingIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        // Nous voulons découvrir deux types de tag 

        //1) Ceux qui sont formattés NDEF 

        IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);

        try {

            ndefDetected.addDataType("text/plain");

        } catch (IntentFilter.MalformedMimeTypeException e) { }

        mNdefExchangeFilters = new IntentFilter[] { ndefDetected };
        // Et ceux qui ne sont pas encore formattés 

        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);

        mWriteTagFilters = new IntentFilter[] { tagDetected };

        //Maintenant nous indiquons au capteur de nous notifier à la decouverte de ces deux types de tags 

        mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent, mNdefExchangeFilters, null);

        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {

            NdefMessage[] msgs = getNdefMessages(getIntent());

            detectedTag= getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);

            promptForContent(msgs[0]);

        }

    }

A partir de là, vous pouvez adapter le code et faire en sorte de récupérer l'identifiant du client, faire une requete http au WS et afficher les détails du client dans l'interface de l'activité. 

 

 

Mots clés:
 
Images (1)
Voir 1 - 1 sur 1 images | Voir tout
Aucune description
Screensho...  Actions
Commentaires (0)
Vous devez être connecté pour poster un commentaire.