First steps with NFC in Android
This post describes how to use NFC in Android. The NFC technology stands for Near Field Communication and you can find the specification at NFC Forum. In this first post, we will analyse some basic aspects of NFC and we will describe how we can implement an app in Android that handles NFC tags.
If you want to experiment NFC, there are several web site where you can buy NFC with a few euro.
NFC can be used in different situation: we can use it to turn on our Wife when we are at home or launch task actions and so on.
We will focus our attention on NDEF data that is a special type of NFC tag. There are some basic steps we have to follow before using the NFC.
NFC Filter
When we use NFC tag,, the first thing we want is our app is notified when we get near a NFC tag. To this purpose we use a intent filter. Android SDK provides three different filter that we can use with different level of priority:
- ACTION_NDEF_DISCOVERED
- ACTION_TECH_DISCOVERED
- ACTION_TAG_DISCOVERED
We focus our attention on ACTION_NDEF_DISCOVERED, that has the highest level of priority. As said, our goal is being notified when the smart phone is near a NFC tag and, if we have only this app installed and capable to handle this NFC tag, we want that the app starts immediately. To do it, we register the filter in the Manifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.survivingwithandroid.nfc" > .... <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain"/> </intent-filter> <manifest>
At line 6 we register our app so that it can be notified with ACTION_NDEF_DISCOVERED
. We can use different types of filter, in this example (at line 8) we used mime type. In other word when a NFC tag NDEF is discovered and it has a mime type text/plain then our app will be started. We can filter using several mime types not only text/pain. We can, moreover, use other type of filters like android:scheme to filter using the protocol or using a string pattern.
NFC Foreground Dispatch
Filtering with intents works if our app is not in foreground. If our app is running in foreground, it won’t be notified, if move our smart phone near a NFC tag. In this case we have to use a different technique called NFC Foreground dispatch. The first step is defining in our code the intent filter (as we did in the manifest.xml):
@Override protected void onCreate(Bundle savedInstanceState) { ... Intent nfcIntent = new Intent(this, getClass()); nfcIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); nfcPendingIntent = PendingIntent.getActivity(this, 0, nfcIntent, 0); IntentFilter tagIntentFilter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); try { tagIntentFilter.addDataType("text/plain"); intentFiltersArray = new IntentFilter[]{tagIntentFilter}; } catch (Throwable t) { t.printStackTrace(); } }
Now we have to register our filter, and we do it in onResume
method, in this way:
protected void onResume() { super.onResume(); nfcAdpt.enableForegroundDispatch( this, nfcPendingIntent, intentFiltersArray, null); handleIntent(getIntent()); }
We should, also, remember to disable foreground dispatch as soon as the app gets in background and the best place to do it is in onPause method.
@Override protected void onPause() { super.onPause(); nfcAdpt.disableForegroundDispatch(this); }
where nfcAdpt is the NFC Adapter.
Handle NFC using NFCAdapter
Once we created our filters, we have to interact with the NFC component in our smart phone. For this purpose, we use NfcAdapter, provided by Android SDK. Using this class, we can check, for example, if the NFC is supported by our smart phone or if the NFC is turned on or off:
@Override protected void onCreate(Bundle savedInstanceState) { ... nfcAdpt = NfcAdapter.getDefaultAdapter(this); // Check if the smartphone has NFC if (nfcAdpt == null) { Toast.makeText(this, "NFC not supported", Toast.LENGTH_LONG).show(); finish(); } // Check if NFC is enabled if (!nfcAdpt.isEnabled()) { Toast.makeText(this, "Enable NFC before using the app", Toast.LENGTH_LONG).show(); } }
NFC Data: Payload
Once we know how to handle NFC tag, we want to read the tag content. There are several type of content defined in NFC specs:
- NFC Forum well-known type
- Media-type
- Absolute URI
- NFC Forum external type
Each type has it is own payload. Generally speaking, a NFC NDEF data is composed by a Message. A message can contain one or more records. Each record is made by an header and a payload (the real information). By now, if we want to read the data inside a NFC NDEF tag we can use:
@Override public void onNewIntent(Intent intent) { Log.d("Nfc", "New intent"); getTag(intent); } private void getTag(Intent i) { if (i == null) return ; String type = i.getType(); String action = i.getAction(); List dataList = new ArrayList(); if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) { Log.d("Nfc", "Action NDEF Found"); Parcelable[] parcs = i.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); for (Parcelable p : parcs) { recNumberTxt.setText(String.valueOf(numRec)); NdefRecord[] records = msg.getRecords(); for (NdefRecord record: records) { short tnf = record.getTnf(); // Here we handle the payload } } } }
Reference: | First steps with NFC in Android from our JCG partner Francesco Azzola at the Surviving w/ Android blog. |