NFC and RFID Basics

Using NFC within Android development is quite easy, at least when it comes to doing basic stuff as reading an ID of a RFID tag. From SDK v.9 the NFC reader produces an intent every time the NFC is activated e.g. by reading an RFID tag. This intent can then be picked up in an appropriate way and parsed for details, e.g. a tag ID. First we need to make sure our app has the appropriate permissions and that the activity will listen to the intents.

<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />


<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>

Next step is to get some code in place in this case collected from two examples, one from a simple NFC read tutorial and the second from an example for how to parse Byte[] code into readable HEX code (String).

import android.app.Activity;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
static String TAG = "NFCREADER";

NFCForegroundUtil nfcForegroundUtil = null;

private TextView info;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
info = (TextView)findViewById(R.id.title);

nfcForegroundUtil = new NFCForegroundUtil(this);
}

public void onPause() {
super.onPause();
nfcForegroundUtil.disableForeground();
}

public void onResume() {
super.onResume();
nfcForegroundUtil.enableForeground();

if (!nfcForegroundUtil.getNfc().isEnabled())
{
Toast.makeText(getApplicationContext(),
"Please activate NFC and press Back to return to the application!",
Toast.LENGTH_LONG).show();
startActivity(
new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS));
}

}

public void onNewIntent(Intent intent) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
/*StringBuilder sb = new StringBuilder();
for(int i = 0; i < tag.getId().length; i++){
sb.append(new Integer(tag.getId()[i]) + " ");
}*/
info.setText("TagID: " + bytesToHex(tag.getId()));

}

/**
* Convenience method to convert a byte array to a hex string.
*
* @param data the byte[] to convert
* @return String the converted byte[]
*/

public static String bytesToHex(byte[] data) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < data.length; i++) {
buf.append(byteToHex(data[i]).toUpperCase());
buf.append(" ");
}
return (buf.toString());
}

/**
* method to convert a byte to a hex string.
*
* @param data the byte to convert
* @return String the converted byte
*/
public static String byteToHex(byte data) {
StringBuffer buf = new StringBuffer();
buf.append(toHexChar((data >>> 4) & 0x0F));
buf.append(toHexChar(data & 0x0F));
return buf.toString();
}

/**
* Convenience method to convert an int to a hex char.
*
* @param i the int to convert
* @return char the converted char
*/
public static char toHexChar(int i) {
if ((0 <= i) && (i <= 9)) {
return (char) ('0' + i);
} else {
return (char) ('a' + (i - 10));
}
}

}

The other class where the actual NFC parsing happens is the NFCForegroundUtil class.

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter.MalformedMimeTypeException;
import android.nfc.NfcAdapter;
import android.nfc.tech.NfcV;
import android.util.Log;

public class NFCForegroundUtil {
private NfcAdapter nfc;

private Activity activity;
private IntentFilter intentFiltersArray[];
private PendingIntent intent;
private String techListsArray[][];

public NFCForegroundUtil(Activity activity) {
super();
this.activity = activity;
nfc = NfcAdapter.getDefaultAdapter(activity.getApplicationContext());

intent = PendingIntent.getActivity(activity, 0, new Intent(activity,
activity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);

try {
ndef.addDataType("*/*");
} catch (MalformedMimeTypeException e) {
throw new RuntimeException("Unable to speciy */* Mime Type", e);
}
intentFiltersArray = new IntentFilter[] { ndef };

techListsArray = new String[][] { new String[] { NfcV.class.getName() } };

}

public void enableForeground()
{
Log.d("demo", "Foreground NFC dispatch enabled");
nfc.enableForegroundDispatch(
activity, intent, intentFiltersArray, techListsArray);
}

public void disableForeground()
{
Log.d("demo", "Foreground NFC dispatch disabled");
nfc.disableForegroundDispatch(activity);
}

public NfcAdapter getNfc() {
return nfc;
}
}

The output to the screen should be the the tag ID. Now an important aspect is to know which type of tag we are detecting. In the example above we will detect a type V tag given in the techlist:

NfcV.class.getName()

For instance, this means that if we are reading from plastic cards this won’t work until we change into NfcA.class.getName() since most plastic cards are using type A.