Near Field Communication (NFC) enables wireless communication
between things like phones, stickers and cards. In this tutorial Richard
Leggett shows us how to write a game demo that both reads and writes
custom data to an NFC tag
NFC or “Near Field Communication” is a technology that
allows wireless close-proximity data communication between things like
phones, stickers and cards. If you’re familiar with Barclays PayWave or
the Oyster Card, you’ll know that the technology this is built on,
“RFID”, allows data to be read by simply touching things together. You
might touch a phone against stickers, posters and with NFC, other
phones. This action can be used to launch a website or an app, make a
payment or even transfer data in both directions (on Android the latter
is called Beam). When compared to QR codes, NFC provides a far
simpler (and built-in) mechanism for opening URLs, downloading apps, or
even reading and writing custom content.
Near Field Communication (NFC) enables wireless communication
between things like phones, stickers and cards. In this tutorial Richard
Leggett shows us how to write a game demo that both reads and writes
custom data to an NFC tag
NFC or “Near Field Communication” is a technology that
allows wireless close-proximity data communication between things like
phones, stickers and cards. If you’re familiar with Barclays PayWave or
the Oyster Card, you’ll know that the technology this is built on,
“RFID”, allows data to be read by simply touching things together. You
might touch a phone against stickers, posters and with NFC, other
phones. This action can be used to launch a website or an app, make a
payment or even transfer data in both directions (on Android the latter
is called Beam). When compared to QR codes, NFC provides a far
simpler (and built-in) mechanism for opening URLs, downloading apps, or
even reading and writing custom content.
Advertisement
In this tutorial we’re going to build an app that writes to NFC tags,
and also reads Top Trumps-like data from them for a retro console game.
If a user without our app touches the tag, it’ll use a built in
mechanism to take them to the download page for the app in the Android
Play Store. Once installed any subsequent taps will launch the app and
show the game card on screen. All in less than 200 lines of code!
In order to follow along you will need an NFC enabled Android phone
such as the Samsung Galaxy Nexus or Samsung Nexus S. The other thing you
will need is a few NFC tags or stickers. You can find these many places
online but RapidNFC offer a great
starter pack, which includes a variety of re-writable tags and the
website also includes a good amount of info around the different tag
types. Be sure to order them pre-formatted (this appears as an option after payment), a bug in Android 4.0.2 may prevent you encoding completely blank tags.
Before we start writing our own code I’d also recommend downloading NXP TagWriter to get you familiar with reading and writing your tags.
Along with reading and writing text and URLs you can enable
“professional mode” for free in the app’s preferences screen (accessible
via the menu button). Once enabled this gives you the ability to
format/erase and write-protect tags.
Getting started
Now onto our app… The first job is to write some data to a blank tag.
We’re going to be including a special record which links to the app
download page, and the game data itself in NDEF (NFC Data Exchange
Format).
I recommend you open up the source code at this point, as I will be
highlighting the key parts on this page. When you have the project
imported, open up AndroidManifest.xml in the XML view.
Before we can make use of NFC we need to add a few new tags to our manifest XML:
The uses-permission tag will allow us to access the NFC chip in the phone, and the uses-hardware tag will make it a requirement, which will mean our app only appears to NFC enabled phones in the Play Store. For our CardActivity tag we add a new intent-filter, this will launch the activity when a tag is scanned that contains data in our game format. We do this by specifying a custom mime-type, in this case I’ve chosen “application/vnd.netmagazine.nfcdemo”.
Android handles NFC tag scans by trying to find the best match for the
data on the tag, providing several fallback mechanisms to make sure the
tag is handled by the right app and allowing the user to pick from a
chooser dialog when there is no clear target.
The first thing we need to do is write some data to a blank NFC tag, so open up MainActivity.java.
This activity is launched when the user clicks the app’s icon. It
displays a button that, when pressed, waits for a tag to write to.
In our onCreate() we grab a reference to the NFC adapter for later use:
View source
Copy code
mAdapter = NfcAdapter.getDefaultAdapter(this);
The NfcAdapter allows us to begin listening to tag
being scanned, before any other app gets a chance. This is called
“foreground dispatch”. When the user presses the button we call enableWriteMode() to begin this process:
In this method we set up a PendingIntent to run when a tag gets scanned, in this case we simply want to the Intent to launch the current Activity when any tag gets scanned, so set up no special filters. When the system dispatches ACTION_TAG_DISCOVERED, this Activity will launch and onNewIntent() will get called with the tag details.
View source
Copy code
public void onNewIntent(Intent intent) {
if(mInWriteMode) {
mInWriteMode = false;
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
writeTag(tag);
}
}
In onNewIntent() we pull out the NFC Tag and begin writing to it in writeTag(). This is by far the largest method in our demo:
View source
Copy code
private boolean writeTag(Tag tag) {
// record to launch Play Store if app is not installed
NdefRecord cardRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, mimeBytes, new byte[0], payload);
NdefMessage message = new NdefMessage(new NdefRecord[] { cardRecord, appRecord});
try {
// see if tag is already NDEF formatted
Ndef ndef = Ndef.get(tag);
if (ndef != null) {
ndef.connect();
if (!ndef.isWritable()) {
displayMessage("Read-only tag.");
return false;
}
// work out how much space we need for the data
int size = message.toByteArray().length;
if (ndef.getMaxSize() < size){
displayMessage("Tag doesn't have enough free space.");
return false;
}
ndef.writeNdefMessage(message);
displayMessage("Tag written successfully.");
return true;
} else {
// attempt to format tag
NdefFormatable format = NdefFormatable.get(tag);
if (format != null){
try {
format.connect();
format.format(message);
displayMessage("Tag written successfully!");
return true;
} catch (IOException e){
displayMessage("Unable to format tag to NDEF.");
return false;
}
} else {
displayMessage("Tag doesn't appear to support NDEF format.");
return false;
}
}
} catch (Exception e){
displayMessage("Failed to write tag");
}
return false;
}
NDEF
The data we store is organised into NDEF Records inside a single NDEF
Message. The first thing we do is create an “application record”, appRecord.
This is something new to Android 4, it forces the system to launch your
app before others if a matching package name is found in the NFC tag.
After that we create our cardRecord which contains a randomly generated game console. The payload is where we store our custom data, in this case simply a game console’s name in lower case.
Next we determine whether the tag is already NDEF formatted by calling Ndef.get(tag).
If it’s already NDEF formatted we check it’s writeable and that the
data is not too large. With all being well we write the data with ndef.writeNdefMessage(). If the tag was not already NDEF formatted we use NdefFormattable.format() to write the data at the same time as formatting the tag. That’s it, we’ve written an NFC tag!
With the tag written hit the home button to exit the app and re-scan the tag. It should now launch the CardActivity and show the console’s game card. Open up CardActivity.java to see how we read the information from the Intent:
String consoleName = new String(cardRecord.getPayload());
displayCard(consoleName);
}
Here we are simply checking the Intent to make sure the type matches our custom mime-type. With that determined we can go ahead and grab the NdefMessage from the Intent’s extras. In our case we know the first NdefRecord is our cardRecord, containing our console name in the payload. With the console name known we simply show the correct image in an ImageView.
In very little time we’ve managed to write custom data to an NFC tag,
automatically download an app to read it and read back that custom game
data. From here you could expand the demo to become a fully playable
game and even use Android Beam’sphone to phone NFC to make it multiplayer.