What is NFC ?
Near Field Communication (NFC) is a set of short-range wireless technologies, typically requiring a distance of 4cm or less to initiate a connection. NFC allows you to share small payloads of data between an NFC tag and an Android-powered device, or between two Android-powered devices. NFC-related APIs in Android are introduced starting from API level 9.
Mode of operations
Android-powered devices with NFC simultaneously support three main modes of operation:
- Reader/writer mode(API 10), allowing the NFC device to read and/or write passive NFC tags and stickers.
- P2P mode(API 14), allowing the NFC device to exchange data with other NFC device ; this operation mode is used by Android Beam.
- Host based Card emulation mode( Android 4.4 ), allowing the NFC device itself to act as an NFC card. The emulated NFC card can then be accessed by an external NFC reader, such as an NFC point-of-sale terminal.
Message format
The data stored in the tag can also be written in a variety of formats, but many of the Android framework APIs are based around a NFC Forum standard called NDEF (NFCData Exchange Format). All the messages that are transferred between two android devices or between devices or a NFC tag are mostly transferred in NDEF format. NDEF is a binary format structured in messages, each of which can contain several records. Eachrecord is made up of a header and the payload. Header contains meta data about the record, such as the record type, length, and so forth. Payload contains the content of the message. Android uses NdefMessage class to create a NDEF message
Basic setup for NFC Communication
Before you can access a device’s NFC hardware and properly handle NFC intents, declare these items in your AndroidManifest.xml file:
< uses-permission android:name=”android.permission.NFC” />
<uses-sdk android:minSdkVersion=”10″/>
<uses-feature android:name=”android.hardware.nfc” android:required=”true” />
The uses-feature element allows your application shows up in Google Play only for devices that have NFC hardware:
API level 9 only supports limited tag dispatch via ACTION_NDEF_DISCOVERED, and only gives access to NDEF messages via the EXTRA_NDEF_MESSAGES extra. No other tag properties or I/O operations are accessible. API level 10 includes comprehensive reader/writer support as well as foreground NDEF pushing, and API level 14 provides an easier way to push NDEF messages to other devices with Android Beam and extra convenience methods to create NDEF records.
Preparing App to handle NFC intent
The Tag Intent Dispatch system is used to launch applications when the predefined tags or NDEF data are identified in tags. In short, you scan to an NFC tag, and if any application is registered to handle the tag, then the registered application launches. If more than one application is registered to handle the tag, a pop-up to select the application (Activity Chooser) is displayed.When an NFC tag is discovered in proximity, the type and payload data in the tag will be encapsulated to intent, and the tag intent dispatch system in Android will run the corresponding application that can handle the tag.
There are 3 types of NFC intents :
- ACTION_NDEF_DISCOVERED :-
The tag dispatch system try to map a known MIME type or URI to the NDEF message. If successful, it encapsulates that information inside of a ACTION_NDEF_DISCOVERED intent along with the actual payload. Following intent filter required for this type of intent.
<intent-filter>
<action android:name=”android.nfc.action.NDEF_DISCOVERED”/>
<category android:name=”android.intent.category.DEFAULT”/>
<data android:mimeType=”text/plain” />
</intent-filter>
Or
<intent-filter>
<action android:name=”android.nfc.action.NDEF_DISCOVERED”/>
<category android:name=”android.intent.category.DEFAULT”/>
<data android:scheme=”http”
android:host=”developer.android.com
android:pathPrefix=”/index.html” />
</intent-filter>
This intent is used to start an Activity when a tag that contains an NDEF payload is scanned and is of a recognized type. This is the highest priority intent, and the tag dispatch system tries to start an Activity with this intent before any other intent, whenever possible.
- ACTION_TECH_DISCOVERED :-
If the tag dispatch system cannot determine the Type of data based on the first NDEF record. This happens when the NDEF data cannot be mapped to a MIME type or URI.
In such cases, a Tag object that has information about the tag’s technologies and the payload are encapsulated inside of a ACTION_TECH_DISCOVERED intent. Following intent filter required for this type of intent.
<activity>
<intent-filter>
<action android:name=”android.nfc.action.TECH_DISCOVERED”/>
</intent-filter>
<meta-data android:name=”android.nfc.action.TECH_DISCOVERED”
android:resource=”@xml/nfc_tech_filter” />
</activity>
Following file which contains list technologies should be declared in resources folder.
<resources xmlns:xliff=”urn:oasis:names:tc:xliff:document:1.2″>
<tech-list>
<tech>android.nfc.tech.IsoDep</tech>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.Ndef</tech>
<tech>android.nfc.tech.NdefFormatable</tech>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
</resources>
- ACTION_TAG_DISCOVERED :-
This intent has the lowest priority. If no activities in the device can handle the corresponding above intents, then ACTION_TAG_DISCOVERED is created.
<intent-filter>
<action android:name=”android.nfc.action.TAG_DISCOVERED”/>
</intent-filter>
Android application record(AAR)
AAR is introduced in API level 14 and is a very powerful property of Android NFC. An AAR has the package name of an application embedded inside an NDEF record. The main objective of AAR is to start only one required application when an NFC tag is scanned.When an NFC tag is scanned, Android searches the entire NDEF message for AAR. If it finds an AAR in any of the NDEF records, it starts the corresponding application. If the application is not installed on the device, Google Play is launched automatically to download the corresponding application.
following code shows you how to create an AAR message :
NdefMessage msg = new NdefMessage(
new NdefRecord[] { …, NdefRecord.createApplicationRecord(“com.example.android.beam”)}
Reading NFC Tag
If an activity starts because of an NFC intent, you can obtain information about the scanned NFC tag from the intent. Intents can contain the following extras depending on the tag that was scanned:
EXTRA_TAG (required): A Tag object representing the scanned tag.
EXTRA_NDEF_MESSAGES (optional): An array of NDEF messages parsed from the tag. This extra is mandatory on ACTION_NDEF_DISCOVERED intents.
EXTRA_ID (optional): The low-level ID of the tag.
To obtain these extras, check to see if your activity was launched with one of the NFC intents to ensure that a tag was scanned, and then obtain the extras out of the intent. The following example checks for the ACTION_NDEF_DISCOVERED intent and gets the NDEF messages from an intent extra.
NdefMessage class is used to construct a message. NfcAdapter Class is used for callback methods .
public void onResume() {
super.onResume();
…
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
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];
}
}
}
//process the msgs array
}
Alternatively, you can obtain a Tag object from the intent, which will contain the payload and allow you to enumerate the tag’s technologies:
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Writing NFC Tag
NDEF class provides access to NDEF content and operations on a Tag . It tries to get theNdef tag (line 4). If the tag is null, the app tries to “format” the tag and the write the message. If the tag is already formatted, the Android app tries to connect to the tag abstract representation and write the NdefMessage.
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction()))
{
if (tag != null) {
try {
Ndef ndefTag = Ndef.get(tag);
if (ndefTag == null) {
NdefFormatable nForm = NdefFormatable.get(tag);
if (nForm != null) {
nForm.connect();
nForm.format(message);
nForm.close();
}
}
else {
ndefTag.connect();
ndefTag.writeNdefMessage(message);
ndefTag.close();
}
}
catch(Exception e) {
e.printStackTrace();
}
}
}
Communicating between two NFC enabled devices
You can enable Android Beam for your application by implementing any of these two callback classes i.e. NfcAdapter.OnNdefPushCompleteCallback orNfcAdapter.CreateNdefMessageCallback. Corresponding to any of these two callback classes we should register following methods from NfcAdapter respectively.
setNdefPushMessage() : When two device are in close enough proximity, an overriden method createNdefMessage() is called which will be used to create and returnNdefMessage . Immediately created message will be beamed to another device.
setNdefPushMessageCallBack() : Similar to above scenario it callscreateNdefMessage() method to create NdefMessage and beams it to another device. Calls onNdefPushComplete() method after the message is beamed.
Host based card emulation
Many Android-powered devices that offer NFC functionality already support NFC card emulation. In most cases, the card is emulated by a separate chip in the device, called asecure element. Many SIM cards provided by wireless carriers also contain a secure element.
Android 4.4 introduces an additional method of card emulation that does not involve asecure element, called host-based card emulation. This allows any Android application to emulate a card and talk directly to the NFC reader.
Conclusion
NFC is gradually capturing the market and getting accepted widely . It is the core technology behind the card payment system like Apple pay and Google pay. Some other uses are like connecting with Bluetooth, creating e- business cards, automating IOT devices.