INVISIBLE HEADING 1

How to NFC on the Android Platform

August 30, 2011 12:51 pm by
Android and NFC

Introduction

Starting with Android 2.3, the platform includes an NFC stack and framework API that allows you to read/write to NDEF (NFC Forum Data format) tags.  For Android smartphones, that means the requirement is to be running at least Android 2.3 and have a NFC chip on the phone. For iOS, we’ll have to see if the rumors are true that the iPhone 5 is NFC-enabled :) .

The only resource I used was the 2011 Google I/O NFC Talk:

and the Sticky Notes demo source code from the NFC talk above.

Let’s pretend that you are an engineer at Facebook working on the Android app, when suddenly the PM tells you that they want to integrate NFC into the Facebook app. Some basic functionality that they want implemented to get started with is to be able to add friends, and check in to places instantly via NFC. This would be a simple way to get started..

(there is no Facebook for Android source code here, I’m writing this tutorial as if we were writing for the app)

P2P Data Transfer – Add Friends Example

Two NFC-enabled devices have the ability to transfer data to each other simultaneously.  For example, two people who just met with NFC-enabled phones can quickly touch their phones together to automatically add each other as friends on Facebook.

To begin, both phones have to be running the same Activity in the foreground in order to work.  Let’s call this Activity ‘NfcAddFriendsActivity’.

In NfcAddFriendsActivity’s onCreate method, we have the following code:

mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
mNfcPendingIntent = PendingIntent.getActivity(this, 0,
    new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
// Intent filters for exchanging over p2p.
IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
    ndefDetected.addDataType("text/plain");
} catch (MalformedMimeTypeException e) {
}
mNdefExchangeFilters = new IntentFilter[] { ndefDetected };

This sets up the different intents that are needed in order for p2p to work.  mNfcPendingIntent is a generic PendingIntent that will be delivered to this activity, Android fills the intent later with the details from the discovered tag before sending it to this activity.  The nDefDetected IntentFilter is set to filter for the intent NfcAdapter.ACTION_NDEF_DISCOVERED with the mime type “text/plain”.  So there will be a dispatch to the foreground Activity when Android receives an intent matching the IntentFilter we just created.

The next step is to enable pushing NDEF messages and receiving NDEF messages.  That means in our onResume method, we call enableNdefExchangeMode which looks like:

private void enableNdefExchangeMode() {
    mNfcAdapter.enableForegroundNdefPush(NfcAddFriendsActivity.this,
        NfcUtils.getUidAsNdef(mUserId));
    mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent, 
        mNdefExchangeFilters, null);
}

These method calls are what allows our device to initiate p2p communiation via NFC.  NfcUtils.getUidAsNdef is the method that creates a NDEF message with mime type “text/plain” with the user’s UID as the payload.  enableForegroundNdefPush will push this message to the other device.  enableForegroundDispatch will set up the listener for the intent that we are filtering for such that when it detects an intent matching the intent filter, it calls our activity’s onNewIntent method:

@Override
protected void onNewIntent(Intent intent) {
    // NDEF exchange mode
    if (!mWriteMode && NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
        NdefMessage[] msgs = NfcUtils.getNdefMessages(intent);
        fireFriendRequest(msgs[0]);
        Toast.makeText(this, "sent friend request via nfc!", Toast.LENGTH_LONG).show();
    }
}

Here, it parses the received NDEF message and gets the payload which should be the other user’s UID.  Then I call fireFriendRequest which is a method that we can assume sends a friend request to the UID that was given.

NfcUtils.getNdefMessages is below, exactly the same as the Sticky Notes demo:

NdefMessage[] getNdefMessages(Intent intent) {
    // Parse the intent
    NdefMessage[] msgs = null;
    String action = intent.getAction();
    if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
        || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
        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];
            }
        } else {
            // Unknown tag type
            byte[] empty = new byte[] {};
            NdefRecord record = 
                new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
            NdefMessage msg = new NdefMessage(new NdefRecord[] {
                record
            });
            msgs = new NdefMessage[] {
                msg
            };
        }
    } else {
        Log.d(TAG, "Unknown intent.");
        finish();
    }
    return msgs;
}

Writing to a NFC Tag – Checking into Places Example

Let’s create a way for people to check in to places simply by tapping on a NFC tag.  To start, we need to write some data onto a NFC tag, such that when the user taps on the tag, an Activity will launch based on the type of data stored on the tag.  Well, each Facebook “Place” has an id associated with it, so lets write those ids onto NFC tags such that when a user taps on the tag, we can launch the correct Activity, passing the id as a parameter.

Lets assume you have a list of Facebook Places, and when the user clicks on a Place, we prompt them to touch the phone to the tag to write that corresponding Place id onto the tag.  So, when the user taps on a place, onListItemClick is called and this is what happens:

...

Place place = (Place) mListAdapter.getItem(position);

// NFC: Write id to tag
placeidToWrite = place.mPlaceId;
enableTagWriteMode();

new AlertDialog.Builder(NfcWriteCheckinActivity.this).setTitle("Touch tag to write")
    .setOnCancelListener(new DialogInterface.OnCancelListener() {
        @Override
        public void onCancel(DialogInterface dialog) {
            disableTagWriteMode();
        }
    }).create().show();

...

I hold the placeid in placeidToWrite, and call enableTagWriteMode.  An alert dialog pops up prompting the user to tap the phone to the tag to write.  enableTagWriteMode below:

private void enableTagWriteMode() {
    mWriteMode = true;
    IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
    mWriteTagFilters = new IntentFilter[] { tagDetected };
    mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent, mWriteTagFilters, null);
}

I create a new IntentFilter for the intent NFCAdapter.ACTION_TAG_DISCOVERED, which is the intent to start an Activity when a NFC tag is discovered.  Then, like in the adding friends example, enableForegroundDispatch is called to dispatch a discovered tag to the foreground activity.  Once this is all set up, and the user taps the phone onto a tag, the ACTION_TAG_DISCOVERED intent is detected and onNewIntent is called:

@Override
protected void onNewIntent(Intent intent) {
    // Tag writing mode
    if (mWriteMode && NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
        Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (NfcUtils.writeTag(NfcUtils.getPlaceidAsNdef(placeidToWrite), detectedTag)) {
            Toast.makeText(this, "Success: Wrote placeid to nfc tag", Toast.LENGTH_LONG)
                .show();
            NfcUtils.soundNotify(this);
        } else {
            Toast.makeText(this, "Write failed", Toast.LENGTH_LONG).show();
        }
    }
}

NfcUtils.getPlaceidAsNdef takes the placeid and creates a NDEF message with mimetype “application/vnd.facebook.places”, which is a custom and vendor-specific mimetype that I made up to distinguish the different NFC tags (places, url, pages) for Facebook.  That way, when the phone reads a NFC tag, it knows which Activity to launch (I detect mimetype “application/vnd.fb.places” – I should launch this specific Activity from Facebook).

NfcUtils is my handy utility class for all things NFC.  NfcUtils.getPlaceidAsNdef looks like:

/*
* Converts a Long into a NdefMessage in application/vnd.facebook.places MIMEtype.
*
* for writing Places
*/
public static NdefMessage getPlaceidAsNdef(Long id) {
    String msg = ((Long) id).toString();
    byte[] textBytes = msg.getBytes();
    NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,
        "application/vnd.facebook.places".getBytes(), new byte[] {}, textBytes);
    return new NdefMessage(new NdefRecord[] { textRecord });
}

Once you construct the NDEF message, you need to actually write it to the tag.  NfcUtils.writeTag looks like:

/*
* Writes an NdefMessage to a NFC tag
*/
public static boolean writeTag(NdefMessage message, Tag tag) {
    int size = message.toByteArray().length;
    try {
        Ndef ndef = Ndef.get(tag);
        if (ndef != null) {
            ndef.connect();
            if (!ndef.isWritable()) {
                return false;
            }
            if (ndef.getMaxSize() < size) {
                return false;
            }
            ndef.writeNdefMessage(message);
            return true;
        } else {
            NdefFormatable format = NdefFormatable.get(tag);
            if (format != null) {
                try {
                    format.connect();
                    format.format(message);
                    return true;
                } catch (IOException e) {
                    return false;
                }
            } else {
                return false;
            }
        }
    } catch (Exception e) {
        return false;
    }
}

And that’s how you write to a tag.  Now, any person with an Android NFC-enabled phone with this build of Facebook for Android would just have to touch their phone onto the sticker (doesn’t need Facebook to be in the foreground), and wham, it takes you straight to the checkin activity with the place already set.

Reading from a NFC tag – Checking into Places Example

Now, we’ll talk about how the phone reads the tag and launch the appropriate Activity.

In the AndroidManifest, we need to write intent-filters that captures the different intents we created with our examples above.  Such that when the Android phone receives the intent, it knows where to pass it along. For checking in, we have an Activity called, lets say, CheckInActivity.  Within the activity, I am going to write an intent-filter that matches the exact intent I created in the NfcWriteCheckinActivity.

This is a snippet of the AndroidManifest for the app:

<activity android:name=".CheckInActivity">
    <intent-filter>
      <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
      <data android:mimeType="application/vnd.facebook.places"/>
      <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

Notice the exact specification of the mimetype, which is the custom vendor mimetype that I created for checking in to places.  That way, I can have one application, like Facebook, pass different intents to different Activities within Facebook.

Within CheckInActivity, it is fairly simple to extract the placeid and open the checkin activity.  You do it in the onResume method of CheckInActivity:

@Override
protected void onResume() {
    super.onResume();
    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
        NdefMessage[] messages = NfcUtils.getNdefMessages(getIntent());
        byte[] payload = messages[0].getRecords()[0].getPayload();
        String placeId = new String(payload);
        NfcUtils.soundNotify(this);
    }
}

Note: The user ID and the place ID are all written and transmitted in plaintext with no authentication or encryption. FWIW, that may or may not be acceptable for some apps. I haven’t looked into the security implications on NFC, but if you are passing confidential data, you will have to find a way to encrypt the data before writing, verifying the integrity of the data when receiving, and authenticating the entity that sent the data. Since this was a personal hackathon project, I did not implement any security features.

Background

Last semester, I was in IEOR 171 – Technology Leadership which is a course where you form small groups to hypothesize and analyze an industry change in the next ten years.  During the beginning of the semester was around the time when Google’s mobile payment service via NFC was leaked, as well as when Gingerbread (Android 2.3) was announced, which is the first version of Android that includes an NFC stack.  It was the first time I heard of NFC and I thought that it had tremendous potential for different applications on mobile phones.  So I proposed to my group that we research the potential for NFC technology in the United States for the next ten years in the United States.  My group was enthusiastic about it, and you can read our final paper in the IEOR 171 section.

Last summer, I interned at Facebook and one of the best things about working there are the hackathons – all night coding sessions with beer, music, and takeout food where you can work on a team or by yourself to build a product out of an idea.  Being excited about NFC (see above), I decided to integrate NFC technology into the Facebook for Android app as a personal hackathon project.  Overnight, I was able to have a working build of the Facebook app where you can add friends, check in to places, share URLs, and go to a Page via NFC.

I pitched my hackathon project to the Product Managers, Directors, and even Zuck himself (emailed him some demos but he didn’t respond haha).  They all said that it was awesome but the problem was not enough NFC-enabled phones in the market – so unfortunately, it is not happening.

I didn’t want all that work to be wasted, so this is a tutorial on how to integrate NFC technology on the Android platform in hopes that people can use it to build cool applications that uses NFC!

You can also read about my second hackathon project, implementing Google Plus’s Instant Upload feature on Facebook.

Do you enjoy reading my posts? Subscribe to me on Facebook below to stay updated!

Tags: , , , , , , , , , , , ,

About

Jesse is a software engineer at Facebook, who just graduated from UC Berkeley. Passionate about mobile technology and entrepreneurship, he started his own blog as a home for his tutorials, projects, and random thoughts. Follow him on Facebook to stay updated on his latest tutorials and projects.

37 Comments »

  1. Interesting write-up, but I’m wondering why you didn’t use the syntax highlighter from before? It really helps in the readability of the code, especially on a site with this theme.

    Comment by Ryan — September 1, 2011 @ 10:28 AM

  2. Excellent examples! Found one little thing that has been puzzled me for a long time. Now I got everything working in my project and even some extra knowledge. Thank you!

    Comment by vpt — September 9, 2011 @ 4:40 AM

  3. Much appreciated for the information and share!

    Comment by Robert — September 21, 2011 @ 12:27 AM

  4. Hi !

    First, thank you for the information, this is very interesting and useful !

    Otherwise, I see that you use “NFCUtils” functions. I wanted to download it but I did not find it.

    Could you give me where to find it and also what is it ? A library ?

    Thanks for your help !

    Mylene

    Comment by Mylene — November 29, 2011 @ 2:50 AM

  5. I wonder about the peer to peer NFC limitation on android 2.3.3. I read this on other page:

    Some limited support for peer-to-peer connection with other NFC devices.

    Do you know what limitations are?

    thanks for your replay

    Comment by ikki_fenix — December 1, 2011 @ 2:31 AM

  6. Nice writeup… Working on some NDEF goodness my self.

    Comment by @gavin_payne — December 4, 2011 @ 6:57 AM

  7. @Mylene That was a utility file that I created for various NFC boilerplate code. I shared the functions that I used in my examples in the article, just search for “NFCUtils” and you’ll see the functions.

    @ikki_fenix Unfortunately, I don’t know the limitations of p2p communication with other NFC devices, sorry. My code worked with two Nexus S running 2.3 FWIW.

    Comment by Jesse Chen — December 12, 2011 @ 5:27 PM

  8. Hi Chen,
    first of all many thanks for sharing. Please share finish() and soundNotify() methods.

    thanks

    Comment by Gayath — January 15, 2012 @ 10:18 AM

  9. HI i m new to android programming. i went through the NFc Demo Code of devloper.android.com

    the problem is that this code uses API level 9. and the intent filter is ACTION_TAG_DISCOVERED

    I want it to be in api level 10 and using NDEF_DISCOVERED..

    is there some tutorial or link which will show me how to read and write ndef messages for api level 10 and beyond..

    this are the links that i have tried..

    http://developer.android.com/resources/samples/NFCDemo/index.html

    Thank You

    Comment by Abhishek Singh — January 24, 2012 @ 2:36 AM

  10. Good job chen!

    Comment by elh2fat — February 4, 2012 @ 5:01 PM

  11. Hey,
    Im new in android. Nowadays i just work with blackberry nfc and see lots of things is the same in android.
    But i cannot find any way to reach the smart card. Is there any security element or things like that in android?
    Blackberry link -> http://www.blackberry.com/developers/docs/7.1.0api/net/rim/device/api/io/nfc/se/SecureElement.html

    or it is impossible nowadays on android?

    Comment by hEngi — February 8, 2012 @ 6:39 AM

  12. [...] I’ve a problem when I try to write a NFC A tag on Android 2.3.6 (nexus S). I use the code from this example: http://www.jessechen.net/blog/how-to-nfc-on-the-android-platform/ [...]

    Pingback by Android NFC Write NFCA tag — February 10, 2012 @ 2:47 PM

  13. I’m using a Galaxy Nexus and a Nexus S to do some tests both with ICS on.
    But both NFCDemo and StickyNote (downloaded from the link in this how-to) are not working…

    Someone know why?

    Comment by Emanuele — March 1, 2012 @ 3:48 AM

  14. Hey there, good tutorial. I have a slightly different usecase.

    I have a mifare ultralight c card. So getting an object of its type and interacting with the card through writepages and readpages function is the easiest thing for me to do.

    qsn 1 : Is what is written in the card through these functions by default NDEF formatted?
    qsn 2: Should i write it as ndef messages and then convert them to byte array and write them on using writepages? or should i not use this class at all?
    qsn 3: i want to use the Android Application Record feature to launch my desired activity alone, starting from api 14, but i dont know how to do this using the MifareUltralight class!

    thanks

    Comment by Akash — March 5, 2012 @ 7:56 PM

  15. Hi Akash,

    Unfortunately I don’t have experience working with other NFC tags that don’t support NDEF messages. This other NFC tutorial might help: http://mifareclassicdetectiononandroid.blogspot.com/2011/04/reading-mifare-classic-1k-from-android.html

    Comment by Jesse Chen — March 6, 2012 @ 6:56 PM

  16. Mifareultralight does support NDEF Jesse.

    Thats the problem, i have a completely empty tag, how do i format it into ndef for the first time and then beyond that, whether i’m supposed to use the ndef at all!

    Ofcourse my previous 3 questions also apply :)

    Comment by Akash — March 8, 2012 @ 8:38 PM

  17. hi,i cannot figure out the NFCUtils class that u have mentioned in your code..pls explain how to use it??

    Comment by prachi — March 20, 2012 @ 10:37 PM

  18. Thanks for such a great blog.

    Comment by Suhas — April 3, 2012 @ 9:08 PM

  19. good post but i see for transfer string from one android to another android via internet please help send code or suggestion for this problem

    thanks in advance

    Comment by sukhpal — April 23, 2012 @ 1:39 AM

  20. Dear Sir,

    You do good job on NFC’s application.

    Thanks for your sharing!

    Gary

    Comment by Gary — May 21, 2012 @ 9:40 PM

  21. Hi. I’m new to android.Can you please submit a code that read a text from NFC tag and get it to a String variable.

    Comment by kasun — July 8, 2012 @ 9:08 PM

  22. How i can put this app in default selection list “Select an action” or “Complete action using”? As soon as i touch the card, “Select an action” ask where i want to show this app also with NFC TagReader or NXP tag reader.

    Comment by Deepak — July 26, 2012 @ 1:03 PM

  23. Thank you for this tutorial..
    I could do the things simply following your article..
    Thanks a lot..

    Comment by Arshad — August 9, 2012 @ 3:35 AM

  24. I have created an Eclipse plugin for NFC, basically an NDEF editor, which you all might be interested in. Check out http://code.google.com/p/nfc-eclipse-plugin/

    Comment by Thomas — August 15, 2012 @ 8:43 AM

  25. Hi. This tutorial is quite helpful but I need to understand more specific of NFC reading and writing between two phones.
    Can you provide sample code for just sharing data between two phones via NFC. I want in my application that one phone can push String data for reading by another phone.

    Thanks.

    Tausif

    Comment by tausif — August 21, 2012 @ 6:59 AM

  26. Hi Jesse,

    I was wondering if you could help, I am reading the Tag but getting that “en” in front of my string. How can I get read of it?

    Thanks heaps

    Comment by Mary — September 14, 2012 @ 11:30 PM

  27. Excelent post. Thanks a lot

    Comment by Renata Barbosa — September 19, 2012 @ 12:27 PM

  28. I used P-P NFC demo code but I alway have touched device on the same time.

    How do i do cant zero touch and exchange data?

    Comment by Lee — October 20, 2012 @ 2:39 AM

  29. Hi, thanks a lot for sharing your code. I was wondering if you might know if it is possible to scan tags when the phone screen is on but it has pin number. Basically the pin is written in the tag and it is able to unlock the phone and take you to the desired application.

    Comment by Narine — November 13, 2012 @ 2:09 PM

  30. Why not providing whole source code of application ?
    Or where I can download it ?

    Comment by murat — January 9, 2013 @ 4:33 AM

  31. Narine, it is possible with a mod for certain devices, you can read about it here (http://www.xda-developers.com/android/use-nfc-with-screen-off-or-in-lock-screen-on-galaxy-nexus/). However, it’s not advised to do this because of security reasons (e.g. malicious people reading/writing NFC to your device without your knowledge).

    Comment by Jesse Chen — January 27, 2013 @ 11:24 AM

  32. Hi,thanks a lot for your share, and can you providing the whole source code for me for study, tks~ (Email:skyseraph00@163.com)

    Comment by skyseraph — January 28, 2013 @ 5:30 PM

  33. Hi thanks for nice tutorial.I new to android so can you provide your source code for NfcUtlis

    Comment by Bindhu — February 5, 2013 @ 11:36 PM

  34. Wonderful blog! I found it while surfing around on Yahoo News.

    Do you have any tips on how to get listed in Yahoo News? I’ve been trying for a while but I never seem to get there! Thanks

    Comment by Cellulari Android — February 11, 2013 @ 5:40 PM

  35. Hi,
    Great work on NFC, and thanks a lot for sharing your work.
    I am currently working on a NFC android related project where I need to have p2p communication with an android phone and a NFC reader (ASS ACR122U). Have you done anything related to this?, If so where can I find the required resources.
    I must add there are instances where some people have done similar projects with the Nexus S phone and the reader I have mentioned. But I am trying with the Xperia S phone where the reader has problems connecting with it seems.

    Comment by Samitha — February 12, 2013 @ 1:55 AM

  36. I have a question regarding peer 2 peer.

    On the YouTube video from 10 minute 20 seconds, they demonstrated a situation where both devices has the same application installed, with the same Activity displayed that once touch both devices shared their payloads.

    In ICS above, you have Android Beam. So there is an extra step to transfer the NDefMessage across. The problem is that in order to achieve the above, both devices will need to tap “Touch To Beam” at the same time. This is not user friendly and you can have different outcomes happening which can be inconsistent. Do you know if there is a workaround that once any device touch to beam that both payloads can be shared?

    Comment by Richard Tan — March 27, 2013 @ 6:26 AM

  37. Hi
    I immediate need help for my project. You please help me.
    I need a piece of code in the application of the nfc.’ve Written about this in the code above?
    Can you please help me?
    I’m looking for a piece of code to analyze it.
    Please help me
    Thank you

    Comment by camelia — March 30, 2013 @ 5:52 AM

RSS feed for comments on this post. TrackBack URL

Leave a comment