Lecture et Ecriture de tags NFC avec Android

De $1

Table des matières
aucun titre

Version de 17:06, 19 Mai 2024

cette version.

Revenir à liste des archives.

Voir la version actuelle

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 tems, 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 modifier l'activité (afficher) afin de lire l'identifiant de l'utilisateur dans un tag et récupérer les informations sur le serveur avant de l'afficher. 

Modification du Manifest

  • Vérifiez si le téléphone supporte la technologie NFC 
<uses-feature
android:name="android.hardware.nfc"
android:required="true"/>
  • Ajoutez les permissions necessaires à votre application afin de pouvoir utiliser le NFC. 
<uses-permissionandroid: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é créée précedemment en lui passant en paramètre l'identifiant à écrire sur le tag. 

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 des avec des 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("Replace current content?").setMessage(new String(msg.getRecords()[0].getPayload()))
                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface arg0, int arg1) {
                        writeTag(getMessageAsNdef(idclient)); 
                    }
                })
                .setNegativeButton("No", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface arg0, int arg1) {

                    }
                }).show();
    }