Pour vérifier si vos tags fonctionnent bien (ou pour les fainéants Sourire), avant même de lancer Visual Studio, vous pouvez utiliser une application qui lit/écrit des tags appelée NFC Interactor. La version d’essai est gratuite et limitée à 10 écritures de tags.

Comme ce serait bien trop facile, nous allons en écrire une nous-même. Pour cela, il faut utiliser l’API Windows Proximity. Vous avez de la chance, grâce au noyau partagé entre Windows et Windows Phone, cette Proximity API fonctionne exactement de la même façon depuis les deux OS. J’ai écrit l’exemple qui suit pour Windows Phone 8, mais sachez que le même code fonctionnerait pour Windows 8.

Dans cet article, je vais supposer que vous connaissez bien les bases du développement pour Windows Phone. Si ce n’est pas le cas, vous trouverez une série de tutoriels pour vous former sur MSDN et vous pouvez suivre l’actu sur le blog de Pierre Cauchois.

 

Pour démarrer, créez un nouveau projet Windows Phone 8 (ou Windows 8) dans Visual Studio. Parmi les modèles, prenez le plus simple « Windows Phone App », et choisissez bien sûr Windows Phone 8.0 pour la version de l’OS. Vous pouvez télécharger l’exemple de code ici : ReadWriteNFCTags.zip

 

Avant de commencer le développement, 2 choses :

- précisez dans le manifeste de l’application – fichier WMAppManifest.xml - que vous allez utiliser du NFC en ajoutant la capability « ID_CAP_PROXIMITY ». Sans cette précision, votre application ne pourra pas être déployée.

- Vous pouvez aussi ajouter dans l’onglet « Requirements » du manifeste que vous ne souhaitez installer l’application que sur des téléphones équipés de NFC avec « ID_REQ_NFC ».

 

clip_image002

 

Etape 1 : Initialiser la connexion au NFC

Pour que votre application soit « NFC » aware, c’est-à-dire qu’elle entende si on lui envoie des infos via NFC et qu’elle puisse en émettre, il va falloir initialiser un ProximityDevice au chargement de votre page principale. Pour écrire du code bien propre, je vous conseille de mettre toutes les fonctions spécifiques NFC dans un helper dédié. Ici, je vais au plus simple :

        ProximityDevice device { get; set; }
        long PublishedMessageID = -1;
        long SubscribedMessageID = -1;

        // Constructor
        public MainPage()
        {
            InitializeComponent();
            
            this.Loaded += MainPage_Loaded;

        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            this.InitializeProximityDevice();
        }

 

Pour initialiser votre ProximityDevice, une fonction toute simple : GetDefault, qui vous retourne l’instance du ProximityDevice utilisé par défaut. Dans mon application, je vais juste afficher dans un TextBlock baptisé « lblTagStatus » l’état de mon device.

        private void InitializeProximityDevice() 
        {
                if (this.device == null) {
                    this.device = ProximityDevice.GetDefault();
                }

                if (this.device != null)
                {
                    this.device.DeviceArrived += ProximityDeviceArrived;
                    this.device.DeviceDeparted += ProximityDeviceDeparted;
                    lblTagStatus.Text = MSG_NFC_ACTIVE;
                } 
                else 
                { 
                    lblTagStatus.Text = MSG_NFC_NOT_FOUND; 
                }
        }

 

Etape 2 : Ecrire un message sur un tag NFC

Chose à savoir, il existe un format standard pour les messages échangés en NFC appelé NDEF, pour NFC Data Exchange Format. Vous n’êtes pas obligés de l’utiliser, mais c’est toujours mieux si vous envisagez des développements multiplateformes.

Bonne nouvelle, il existe une librairie NDEF pour Windows 8 sur CodePlex que vous pouvez récupérer, et qui fonctionne très bien aussi sur Windows Phone (c’est ça, la magie des API en commun). Pour l’ajouter à votre application, un clic-droit sur le projet dans Visual Studio, lancer NuGet, rechercher NDEF, installer et hop c’est terminé.

 

clip_image004

 

Pour plus de détails sur cette librairie, https://ndef.codeplex.com/

Voici la structure d’un message NDEF. Comme vous le voyez, il peut contenir plusieurs enregistrements.

 

clip_image006

 

Pour construire un message NDEF avec cette librairie, je vais avoir besoin des using suivants dans ma classe :

using NdefLibrary.Ndef;
using System.Runtime.InteropServices.WindowsRuntime;

 

Et voici la fonction que j’appelle pour écrire sur un tag (que vous pouvez appeler au clic sur un bouton) :

 

  private void WriteNDEFToNfc() 
        {
            // Initialize Smart Poster record with URI, Action + 1 Title
            var spRecord = new NdefSpRecord
            {
                Uri = "http://msdn.microsoft.com/windows",
                NfcAction = NdefSpActRecord.NfcActionType.DoAction
            };

            spRecord.AddTitle(new NdefTextRecord
            {
                Text = "Windows Dev Center",
                LanguageCode = "en"
            });

            // Add record to NDEF message
            var msg = new NdefMessage { spRecord };

            // Publish NDEF message to a tag
            if (device != null)
            {
                PublishedMessageID = device.PublishBinaryMessage("NDEF:WriteTag", msg.ToByteArray().AsBuffer());
                Debug.WriteLine("Published Message. ID is {0}", PublishedMessageID);

                lblSender.Text = "Published Message. ID is: " + PublishedMessageID.ToString();
                lblMessageContent.Text = "Content: " + spRecord.Uri.ToString();
                lblMessageType.Text = "Type: " + spRecord.Type.ToString();
            }

            // Alternative: send NDEF message to another NFC device
            //device.PublishBinaryMessage("NDEF", msg.ToByteArray().AsBuffer());
        }

 

J’ai créé un enregistrement (NdefTextRecord), que j’ai ajouté au message (NdefMessage). Ensuite, si mon device NFC est bien initialisé, j’envoie ce message et je récupère son ID (PublishedMessageID). Cette fonction marche très bien, à condition que vos tags soient bien formatés avant.

Une fois que mon tag contient le message, je n’ai plus qu’à le passer près du téléphone pour qu’il soit reconnu. Aucune application à lancer, NFC le reconnait directement.

Petite remarque, Windows Phone étant un OS à la sécurité bien pensée, il y aura toujours un prompt demandant l’approbation de l’utilisateur à la lecture d’un tag. Voilà à quoi ce prompt ressemble :

 

clip_image008

 

Etape 3 : Lire un message depuis un tag NFC

Pour lire un message depuis un tag, il va falloir dire au ProximityDevice de votre application qu’il faut qu’il s’intéresse à un certain type de messages, ici NDEF, en appelant la fonction SubscribeForMessage, et lui préciser quoi faire en cas de réception, ici appeler la fonction messageReceived.

Dans mon exemple, j’ai ajouté un bouton Read dans ma page principale qui m’abonne à un type de message (et me désabonne des anciens si besoin) :

 

        private void btnReadNFC_Click(object sender, RoutedEventArgs e)
        {
            InitLabels();

            // Make sure NFC is supported
            if (device != null)
            {
                if (SubscribedMessageID != -1)
                {
                    device.StopSubscribingForMessage(SubscribedMessageID);
                }
                //Suscribe to NDEF new message
                SubscribedMessageID = device.SubscribeForMessage("NDEF", messageReceived);
                Debug.WriteLine("Subscribed Message. ID is {0}", SubscribedMessageID);
            }
        }

 

Si je passe mon tag avec un message NDEF près de mon téléphone, la fonction suivante messageReceived sera appelée. Celle-ci va récupérer le message et l’analyser en fonction de son type : SpRecord, UriRecord, ou TextRecord.

 

 private void messageReceived(ProximityDevice sender, ProximityMessage message)
        {
            var rawMsg = message.Data.ToArray();
            var ndefMessage = NdefMessage.FromByteArray(rawMsg);
            SubscribedMessageID = -1;

            // Loop over all records contained in the NDEF message
            foreach (NdefRecord record in ndefMessage)
            {
                // Check the type of each record - handling a Smart Poster, URI and Text record in this example
                var specializedType = record.CheckSpecializedType(false);
                if (specializedType == typeof(NdefSpRecord))
                {
                    // Convert and extract Smart Poster info
                    var spRecord = new NdefSpRecord(record);

                    Dispatcher.BeginInvoke(() => {
                        lblSender.Text = "Message received from: " + sender.DeviceId;
                        lblMessageContent.Text = "Content: " + spRecord.Uri;
                        lblMessageType.Text = "Type: " + spRecord.Type.ToString();
                    });
                }
                else if (specializedType == typeof(NdefUriRecord))
                {
                    // Convert and extract Smart Poster info
                    var uriRecord = new NdefUriRecord(record);
                    Dispatcher.BeginInvoke(() =>
                    {
                        lblSender.Text = "Message received from: " + sender.DeviceId;
                        lblMessageContent.Text = "Content: " + uriRecord.Uri;
                        lblMessageType.Text = "Type: " + uriRecord.Type.ToString();
                    });
                }
                else if (specializedType == typeof(NdefTextRecord))
                {
                    // Convert and extract Smart Poster info
                    var textRecord = new NdefTextRecord(record);
                    Dispatcher.BeginInvoke(() =>
                    {
                        lblSender.Text = "Message received from: " + sender.DeviceId;
                        lblMessageContent.Text = "Content: " + textRecord.Text;
                        lblMessageType.Text = "Type: " + textRecord.Type.ToString();
                    });
                }
            }
        }

 

Tada ! Maintenant, vous savez lire des tags, et même modifier leurs contenus.

Vous pouvez télécharger le code source correspondant à cet exemple ici : ReadWriteNFCTags.zip

Dans le prochain article, nous verrons comment communiquer avec une autre instance de votre application, pratique pour des jeux par exemple.

 

Liens utiles