09 April, 2014

How to develop Android NFC HCE

What is hce?

Android 4.4 introduces an additional method of card emulation that does not involve a secure element, called host-based card emulation. This allows any Android application to emulate a card and talk directly to the NFC reader.

How to enable hce

The first step is to create a service to extend HostApduService.
HostApduService has two abstract methods need to implment:
processCommandApdu: This method will be called when a command APDU has been received from a remote device.
Genernally, we should return the message to the remote device if the messag size is small.

    public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {

        Log.e(TAG, "Runinig");
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-DD:HH:mm:ss.SSS");
        if (isSelectAIDRequest(commandApdu)) {
            return ("Message started " + format.format(new Date())).getBytes();
        } else {
            return "null".getBytes();


The second step is to register the service.

<service android:exported="true" android:name="com.example.normaltest.HCEService" android:permission="android.permission.BIND_NFC_SERVICE">
                <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE">

            <meta-data android:name="android.nfc.cardemulation.host_apdu_service" android:resource="@xml/apdu">
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
     <aid-group android:description="@string/apdu_group_desc"
              <aid-filter android:name="F0050607080910"></aid-filter>  
              <aid-filter android:name="F0394148148100" />       

Android device as an nfc reader

To emulate as an NFC reader, we use NFC foreground Dispatch feature.
Please refer to http://developer.android.com/guide/topics/connectivity/nfc/advanced-nfc.html#foreground-dispatch

mPendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);  
mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, new IntentFilter[]{filter},null);

To send Select AID APDU:
private static final byte[] CLA_INS_P1_P2 = {
    0x00, (byte) 0xA4, 0x04, 0x00
private static final byte[] AID_ANDROID = {
    (byte) 0xF0, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10
private byte[] createApdu(byte[] aid) {
    byte[] request = new byte[6 + aid.length];
    System.arraycopy(CLA_INS_P1_P2, 0, request, 0, CLA_INS_P1_P2.length);
    request[4] = (byte) aid.length;
    System.arraycopy(aid, 0, request, 5, aid.length);
    request[request.length - 1] = 0;
    return request;

byte[] response = isoDep.transceive(createApdu(AID_ANDROID)); // here we can process the response data.

HCE secruity

A very good article: http://www.ul-ts.com/downloads/whitepapers/finish/6-whitepapers/289-hce-security-implications

Source code

Link: http://pan.baidu.com/s/1mgDgFRM PWD: 18wn
Please note that the HCE will only work when the screen is locked and turned on if the device is touching an Android device which acts as an NFC reader.
Because when both devices are screen-unlock, they will enter into P2P mode.

But if your device has 4.4 KitKat installed, then you can set your device as reader-writer only to emulate the nfc reader. Then everything will work well.

public void enableReaderMode (Activity activity, NfcAdapter.ReaderCallback callback, int flags, Bundle extras)
Limit the NFC controller to reader mode while this Activity is in the foreground.

In this mode the NFC controller will only act as an NFC tag reader/writer, thus disabling any peer-to-peer (Android Beam) and card-emulation modes of the NFC adapter on this device.

For interacting with tags that are emulated on another Android device using Android's host-based card-emulation, the recommended flags are FLAG_READER_NFC_A and FLAG_READER_SKIP_NDEF_CHECK.