Working with Android’s HCE, libnfc, and Chrome-NFC

A guest blog by Justin Ribeiro, Stickman Ventures

If you’ve taken a look at the slides from Neel Rao’s Android HCE presentation, you’ll note that the Android’s host-based card emulation is incredibly powerful. As a developer you can create your own NFC conversation in any manner you like. The question that often comes up is “How do I actually test it?” Let’s walk through a basic setup and a couple of options that you can use off the shelf.

The basics of the API

Android’s host-based card emulation is straight forward to get started with. The documentation goes further into the details, but for the sake of this example let’s talk about the basics. Extending from HostApduService, we see that our API footprint is rather small and powerful. We can operate on responses within processCommandApdu:

public class myHostApduService extends HostApduService {
  private static final String TAG = "HostApduService";
  
  // Using default AID from the HCE Android documentation
  // Ala... aid-filter android:name="F0394148148100"
  private static final byte[] APDU_SELECT = {
      (byte)0x00, // CLA
      (byte)0xA4, // INS	
      (byte)0x04, // P1	
      (byte)0x00, // P2
      (byte)0x07, // Lc field
      (byte)0xF0, (byte)0x39, // NDEF Tag Application name
      (byte)0x41, (byte)0x48, // NDEF Tag Application name (cont)
      (byte)0x14, (byte)0x81, // NDEF Tag Application name (cont)
      (byte)0x00, // NDEF Tag Application name (cont)
      (byte)0x00  // Le field
  };

  private static final byte[] A_OKAY = {
      (byte)0x90,  // SW1	
      (byte)0x00   // SW2
  };

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    // start up
  }

  @Override
  public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
    // process commands
  }

  @Override
  public void onDeactivated(int reason) {
      // all stop
  }
}

In the code block above, I’ve defined a couple of variables we can use to get started. APDU_SELECT matches one of the existing aid-filters from the Android documentation and A_OKAY is what we’ll send back to our reader to tell it things are okay.

How do we check this? We can compare what the reader sends with something like:

public class myHostApduService extends HostApduService {
  ...
  @Override
  public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {     
    if (Arrays.equals(APDU_SELECT, commandApdu)) {
      // We match!
      return A_OKAY;
    }
  }
  ...
}

Great, but how do I actually send that? You’ve got a couple options.

Using LibNFC

There are a number of libraries available that let you write NFC applications. But what if you just want to start now so you can talk to your Android device? Assuming you have a reader attached to your PC you can use the open source libnfc to create a program to send commands.

A simplified version in C might look like:

...

// select application
memcpy(capdu, "\x00\xA4\x04\x00\x07\xF0\x39\x41\x48\x14\x81\x00\x00", 13);
capdulen=13;
rapdulen=sizeof(rapdu);

printf("Sending ADPU SELECT...\n");
if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0) {
  exit(EXIT_FAILURE);
}

...

Where the CardTransmit() function uses libnfc’s nfc_initiator_transceive_bytes() to send bytes through the reader. When in action, the conversation looks like the screenshot below:

NFC Developer Tip for Android Developers

An example of this code is available on both the libnfc wiki (Libnfc:APDU example) and a specific version to this APDU is available on Github.

Using Chrome-NFC

The Chrome OS team released a sample showing off NFC support via Chrome’s USB API months back. It’s use has been well documented, including recently in a talk from Francois Beaufort, Alexis Moussine-Pouchkine, and Alex Van Boxel at Devoxx, where NFC and Chrome OS were in use.

By default, the library won’t send our aid select, but via a few modifications you can use it to do just that. In this case I’ve created a branch that adds the ability to have NFC Forum Type 4 Tag Operation Specification 3.0 conversation, which includes sending the required bytes to start our conversation with Android.

Putting all the pieces together

Once you have your Android app, your reader, and a small program to tell the reader what to say, you can start developing further. A full example of all the pieces mentioned above along with documentation are available as open source on Github:

1. Android HCE example: https://github.com/justinribeiro/android-hostcardemulation-sample
2. libnfc Tester example: https://github.com/justinribeiro/android-hostcardemulation-sample/tree/master/apdu_exchange_tester
3. Chrome-NFC for Type 4: https://github.com/justinribeiro/chrome-nfc/tree/type4-conversation
4. Chrome App Tester example: https://github.com/justinribeiro/hce-to-chromenfc-app

Want to see all the pieces working in action? The video below shows Android’s HCE sending NDEF text to a Chrome App through Chrome-NFC:

About our guest blogger: 
Justin Ribeiro is software engineer and show runner at Stickman Ventures and Google Developer Expert in Wearables. He can often be found working with NFC and various sensor technologies for Android and the Web. When not writing code, he can be found co-organizing Google Developer Group Oakdale, Oakdale OpenMesh, and spending time with his three daughters.

Share
Tagged:Tags:

Leave A Comment?

You must be logged in to post a comment.