Lire/Ecrire des tags NFC depuis Windows 8 ou Windows Phone 8
Pour vérifier si vos tags fonctionnent bien (ou pour les fainéants ), 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 ».
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 8sur 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é.
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.
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 = "https://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 :
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
- Application NFC Interactor pour Windows Phone 8: https://www.nfcinteractor.com/download-nfc-interactor-for-windows-phone-8/
- Proximity API for Windows Phone : https://msdn.microsoft.com/en-US/library/windowsphone/develop/jj207060(v=vs.105).aspx
- Understanding NFC Data Exchange Format (NDEF) messages : https://www.developer.nokia.com/Community/Wiki/Understanding_NFC_Data_Exchange_Format_(NDEF)_messages
- Blog de Pierre Cauchois sur Windows Phone 8 : https://blogs.msdn.com/b/pierreca/