Mobile Zone is brought to you in partnership with:

Den is a DZone Zone Leader and has posted 460 posts at DZone. You can read more from them at their website. View Full User Profile

Working With Static NFC Cards on Windows Phone 8

12.13.2012
| 6445 views |
  • submit to reddit
With the release of Windows Phone 8, developers are able to create applications that take advantage of the proximity (NFC - Near Field Communications) sensor. This capability enables a variety of sharing scenarios, both with other devices (not necessarily Windows Phone), as well as with other static items, such as NFC cards, which is going to be the focus of this piece.

NOTE: You will need a physical Windows Phone 8 device to follow this article. Also, make sure to enable the Tap+Send Capability on the device.

First things first, create a new Windows Phone 8 project in Visual Studio 2012. The core class that works with data shared through the proximity sensor is ProximityDevice. Because, for obvious reasons, there is only one NFC device hooked to the existing hardware, the developer has to access the current instance.

Make sure to declare the ID_CAP_PROXIMITY capability in WMAppManifest.xml:

To do this, GetDefault is called:

ProximityDevice device = ProximityDevice.GetDefault();

if (device != null)
{

}

You might ask - if this is a Windows Phone 8 application, why do I still have to check whether the device is null? Scenarios can be different in this case - for example, the provider might be unavailable or disabled.

First of all, let's assume that you want to write something to an NFC card. To do this, you need to use the DataWriter  class, coupled with PublishBinaryMessage  - a method exposed through the currently available NFC provider.

A snippet like this will write a string to the card:

DataWriter writer = new DataWriter();
writer.WriteString("Test Message");

device.PublishBinaryMessage("Windows:WriteTag.NFCTest", writer.DetachBuffer(), new MessageTransmittedHandler((pDevice, id) =>
    {
        Debug.WriteLine("Message sent.");
    }));

At this point, if you run the application and tap a compatible NFC tag to the phone, the message will be written to it. It's a pretty basic set-up, but there is something you should pay attention to. When PublishBinaryMessage is called, the first argument that is being passed to the function represents the protocol and the subtype (read more here).

Windows:WriteTag means that there is a binary message that has to be written. The subtype (in this case, NFCTest) is specified by the developer and links the tag to the application.

To read the message from the tag, you need to use SubscribeForMessage :

device.SubscribeForMessage("Windows.NFCTest", new MessageReceivedHandler((proxDevice, message) =>
    {
        Debug.WriteLine(message.DataAsString);
    }));

Notice that you are still referencing the Windows protocol (for binary data) and the NFCTest subtype. If the card contains a subtype that is not associated with your application, it will be ignored. If the message is read, you will have access to a ProximityMessage  instance.

A simple text message can be useful, depending on the application, but there is much more that you can do. For example, you can also write a URL to the card, that will open any webpage on the phone:

DataWriter writer = new DataWriter();
writer.UnicodeEncoding = UnicodeEncoding.Utf16LE;
writer.WriteString("http://bing.com");

device.PublishBinaryMessage("WindowsUri:WriteTag", writer.DetachBuffer(), new MessageTransmittedHandler((pDevice, id) =>
    {
        Debug.WriteLine("Message sent.");
    }));

You need to explicitly specify the encoding here to be UTF16-LE. If the encoding is not specified, the URL will not be written to the tag. The URL that is written will be system-wide accessible, which means that if the user will tap on the tag, he will get a prompt to open the browser.

You can also write URIs that are associated with specific stock or third-party Windows Phone 8 applications. For example, you could easily write these URI schema references:

  1. ms-settings-bluetooth:
  2. mailto:[email address]
  3. ms-settings-accounts:
  4. ms-settings-wifi:

For a more detailed list, you can visit this MSDN page.

You can also write custom content to the tag, such as a picture. For example, here is a snippet to write a JPEG image to a Nokia NFC card:

Uri uri = new Uri("/test.jpg", UriKind.Relative);
BitmapImage image = new BitmapImage(uri);
imgTest.Source = image;

DataWriter writer = new DataWriter();

WriteableBitmap bitmap = new WriteableBitmap(image);
int[] data = bitmap.Pixels;
int length = data.Length * 4;
byte[] result = new byte[length];
System.Buffer.BlockCopy(data, 0, result, 0, length);

writer.WriteBytes(result);

device.PublishBinaryMessage("WindowsMime:WriteTag.image/jpeg", writer.DetachBuffer(), new MessageTransmittedHandler((pDevice, id) =>
    {
        Debug.WriteLine("Message sent.");
    }));

It's worth mentioning that at this point, you need to be really careful with the amount of information you are trying to write to the tag. You can call device.MaxMessageBytes  to find out the sending limit, but there is also the tag size constraint.

What happens if you are attempting to send a photo that is too large to a tag that cannot store it? The MessageTransmittedHandler will never be triggered, but you will also not get an error.