Integrating NFC into your BlackBerry 10 Application

Open Source

Guest post from John Murray – Ed.

You know, working in the Developer Relations team at Research In Motion® (RIM®), you get to get to play around with some fun stuff. Recently, Near Field Communication (NFC) has been exercising my brain cells. Some of you may be familiar with the NFC-related articles and code samples that I’ve co-authored with my co-conspirator, Martin Woolley (@mdwrim), which you can find listed in our NFC Article and Code index.

Now, whenever you mention NFC in a conversation, people invariably think of payments. Using NFC to make secure payments is perhaps the most obvious use case. However, when I think of NFC I tend to think of workflows as well. “Workflows,” you say? What do you mean?

OK, let’s think about it anecdotally. How many times have you had the challenge of transcribing some data from an external source to your handset whilst holding a bag and trying to hold a conversation at the same time? How many times have you tried to share information on your handset with someone else and had to struggle with inputting email addresses whilst doing three other things at the same time? These use cases are examples of Workflows, or Business Processes, that stumble on the point of having to accommodate more “human” interaction than is really necessary. NFC can be used to help streamline simple workflows that involve human interactions on mobile devices and ultimately help achieve efficiencies.

So, having thought about this and how to demonstrate a simple but realistic use case (whilst also having some fun), we came up with the concept of the “Fun Run”.

Suppose you’re taking part in a charity “Fun Run” – not quite a marathon but something shorter for fun. The race organizers have developed a simple mobile application to allow you to register for the event and have placed NFC Tags in the starting and finishing areas. As you start you tap on one of the tags, your race timer is started as well as notifying the organizers that you have begun. When you pass the finish line, simply tap on one of the tags in the Finish area to stop your timer and notify the organizers of your finishing time!

In between the start and finish, there may be Way Points with NFC Reader devices that can be used to register intermediate times as the runner passes these points. Tap the handset to the NFC Reader and receive confirmation that the timing data has been transferred successfully.

OK, maybe it’s not 100% realistic, but as an example it is sufficient to demonstrate how a workflow process that involves having to record start and finish times and tracking progress can be made more efficient using NFC. The key learning point is to understand how integrating NFC technology into your application can be used to achieve efficiencies in similar processes.

The Applications

Let’s take a look at how we implemented this simple example using BlackBerry® 10 and BlackBerry® 7 NFC capable devices. There are really three use cases:

1. Tap your handset against an NFC tag at the start of the race to start your race timer.
2. Tap your handset against NFC readers at intermediate waypoints during the race to transfer your current race timer data to an application that manages the reader.
3. Tap your handset against an NFC tag at the end of the race to stop your race timer.

Acting on External Tag Events

To implement the first and last use case, we decided to provide two NFC tags that had specific NDEF messages as their content. There would be one tag that would start the timer at the start of the race and one tag that would stop the timer at the end of the race.

Specifically the data in the two tags is:

1. Tag used to start the timer:

NDEF TNF = External ( integer value 4 )
Type = “my.rim.com:myrecordtype”
Payload = “start”

2. Tag used to stop the timer:

NDEF TNF = External ( integer value 4 )
Type = “my.rim.com:myrecordtype”
Payload = “stop”

Why use this data? Well, firstly we choose an NDEF TNF (Type Name Format) for the NDEF Message because it allows us to define custom tag content that won’t clash with standard tag message types such as Smart Poster (“Sp”) or URL (“U”) or Text (“T”). We want to make sure that when one of these tags is presented, our application, and our application alone, is launched to process the tag.

Secondly, we choose a “Type” of “my.rim.com:myrecordtype“. Within the context of an External TNF record the Type can be arbitrary, but in order to prevent clashes with other organizations’ custom tag formats, we use the DNS naming scheme to set the namespace of the tag as “my.rim.com” to establish it as a RIM NDEF message. We further qualify it with a specific sub-type of “myrecordtype” since an organization may define a whole family of custom tag formats for its own use.

So, these settings ensure that these tags will only make sense to our application and not overlap with tags form elsewhere. The “Payload” of the two tags differs in that one has the string “start” and the other has the string “stop” to mark them as ones to be used to start and stop the timers respectively.

In the case of BlackBerry 10, our application registered with the Invocation Framework through the stanza in its “bar-descriptor.xml” file as shown in Figure 1. The “uris” attribute of the “<property … />” tag has been set to the value “ndef://4/my.rim.com/myrecordtype” which a URI format specification of the two tags just described above.

...
<invoke-target id="com.example.NfcRaceTimeWay">
    <type>APPLICATION</type>
    <filter>
        <action>bb.action.OPEN</action>
        <mime-type>application/vnd.rim.nfc.ndef</mime-type>
        <property var="uris" value="ndef://4/my.rim.com/myrecordtype"/>
    </filter>
</invoke-target>
...

Figure 1 Registering for tag types in BlackBerry 10

When a “start” or “stop” tag is presented to the handset, then our application is launched if it’s not already running, and the tag contents are handled as shown in Figure 2 -- where the payload of “start” or “stop” is extracted once we’ve verified that it’s of the correct type.

...
void NfcListener::receivedInvokeRequest(const bb::system::InvokeRequest& request) {

    QByteArray data = request.data();
    QtMobilitySubset::QNdefMessage ndefMessage = QtMobilitySubset::QNdefMessage::fromByteArray(data);

    handleNdefRequest(ndefMessage);
}

void NfcListener::handleNdefRequest(const QtMobilitySubset::QNdefMessage ndefMessage) {

    QList::const_iterator ndefRecord;

    for ( ndefRecord = ndefMessage.begin(); ndefRecord != ndefMessage.end(); ndefRecord++) {
        if (ndefRecord->typeNameFormat() == QtMobilitySubset::QNdefRecord::ExternalRtd) {
            if (QString(ndefRecord->type()).compare("my.rim.com:myrecordtype") == 0 ) {
                emit raceTagDetected(QString(ndefRecord->payload()));
            }
        }
    }
}
...

Figure 2 Handling a Start or Stop tag in BlackBerry 10

In the case of BlackBerry 7, registration is achieved in Java® by registering a listener for the specific NDEF message type as shown in Figure 3.

...
    nfcManager = ReaderWriterManager.getInstance();
    nfcManager.addNDEFMessageListener(listener, NDEFRecord.TNF_EXTERNAL, "my.rim.com:myrecordtype", true);
...

Figure 3 Registering for tag types in BlackBerry 7

A similar behaviour is achieved for BlackBerry 7 through the implementation of the “onNDEFMessageDetected()” method of the “NDEFMessageListener” interface as shown in Figure 4.

...
    public void onNDEFMessageDetected(NDEFMessage msg) {
        NDEFRecord[] records = msg.getRecords();
        int numRecords = records.length;
        if(numRecords > 0) {
            byte[] payloadBytes = records[0].getPayload();
            try {
                String ascii_payload = new String(payloadBytes,"US-ASCII");
                Utilities.log("XXXX payload="+ascii_payload);
                if (ascii_payload.equals("start")) {
                    startTimer();
                }
                if (ascii_payload.equals("stop")) {
                    stopTimer();
                }
            } catch(UnsupportedEncodingException e) {
                Utilities.log("XXXX "+e.getClass().getName()+":"+e.getMessage());
            }
        }

    }

...

Figure 4 Handling a Start or Stop tag in BlackBerry 7

So, what we’ve achieved here is the ability to use an external NFC tag to trigger a process in our application. In this case it’s simply the starting and stopping of a timer, but it could be extended quite easily to, say, call a web service and integrate the event into a larger workflow process.

What does this look like in practice? Well, here’s a short video of the BlackBerry 10 application in action:

[ YouTube link for mobile viewing ]

Virtual Tag Emulation

Let’s get back to the original use cases. To implement the second one, we decided to have the BlackBerry handset emulate a virtual tag and allow the contents of the virtual tag to be read by an external NFC reader.
What format of tag should be emulated by the handset? This is what we chose:

1. Virtual tag emulated by the application

NDEF TNF = External ( integer value 4 )
Type = "my.rim.com:myrecordtype"
Payload = "hh:mm:ss"

a. That is the time displayed on the handset in:
Hours (hh)
Minutes (mm)
Seconds (ss)

The type of the virtual tag is exactly the same as for the “start” and “stop” physical tags for the very same reasons, except that the payload is a representation of the current race timer value (“hh:mm:ss”) as displayed by the application.

...
void NfcListener::startTagEmulation(const QString &tagData) {
    nfc_ndef_record_t *ndefRecord = makeCustomRecord(QString("my.rim.com"), QString("myrecordtype"), tagData);
    if (_emulateNdefMessage) {
        CHECK(nfc_delete_ndef_message(_emulateNdefMessage, true));
        _emulateNdefMessage = 0;
    }
    CHECK(nfc_create_ndef_message(&_emulateNdefMessage));
    CHECK(nfc_add_ndef_record(_emulateNdefMessage, ndefRecord));
    CHECK(nfc_start_ndef_tag_emulation(_emulateNdefMessage));
...

Figure 5 BlackBerry 10 - starting virtual tag emulation

As shown in Figure 5, starting tag emulation in BlackBerry 10 is quite simple. It just involves calling “nfc_start_ndef_tag_emulation()”. In addition we can use BPS (BlackBerry Platform Services) to determine when a read on the virtual tag has been successful, as shown here in Figure 6:

...
void NfcListener::handleNfcEvent(bps_event_t *event) {
    uint16_t code = bps_event_get_code(event);
    if (NFC_VIRTUAL_TAG_SELECTION_EVENT == code) {
        emit tagEmulationSelectEvent();
    } else if (NFC_VIRTUAL_TAG_LEFT_EVENT == code) {
        emit tagEmulationLeftEvent();
    } else if (NFC_VIRTUAL_TAG_READ_EVENT == code) {
        emit tagEmulationReadEvent();
    }
}
...

Figure 6 BlackBerry 10 - stopping virtual tag emulation

So, what we’ve achieved here is the ability to transmit live information from an application in the BlackBerry handset in real time to an external application via an NFC reader. The external application simply displays the time displayed by the BlackBerry application, but it could easily be extended to integrate with some larger workflow process.

Take a look at the video here for a demonstration of this on BlackBerry 10:

[ YouTube link for mobile viewing ]

If you’re interested, the virtual tag emulation functionality was tested using an NFC Reader attached to a PC controlled by a Python application using the “PyScard” (Python for Smart Cards) library available from SourceForge.net. (Python and Ruby are my favorite programming languages!)

The two versions of our NFC-enabled “Fun Run” applications are available with full source code from our GitHub repositories here:

https://github.com/blackberry/Cascades-Community-Samples/tree/master/NfcRaceTimeWay
https://github.com/blackberry/Samples-for-Java/tree/master/NFC/NfcRaceTime7

Just in closing, it’s worth making one or two comments about the relative ease of developing applications to the same set of end user specifications in BlackBerry 10 Cascades™ versus BlackBerry 7 Java. I’ve been developing code in C/C++ for more years than I care to remember and for a shorter time in Java (but still since the language first saw the light of day), so I feel I’m qualified to make comparisons. I’ll be honest: I’ve found it much easier to develop applications using C/C++ and Cascades. The user interface elements are particularly easy to use, and I’ve found it possible to get a user interface up and running in Cascades much faster than I would have done in Java. It’s much easier to modify and extend since Cascades elements map directly to Qt/Cascades C++ classes and the SIGNAL() / SLOT() model makes it so easy to connect events to handlers.

I’m definitely sold on Cascades, Qt and C/C++!

About mdwrim

My name’s Martin Woolley and I work in BlackBerry's Developer Relations team as a Senior Application Development Consultant. I’ve been with BlackBerry since 2009 but have worked in software development in various capacities for 30 years in a whole range of industry sectors and on numerous computing platforms small and large. These days I specialise in areas such as Bluetooth Low Energy, NFC, Internet of Things (Iot) and wearable technologies amongst other things.

Join the conversation

Show comments Hide comments
+ -
blog comments powered by Disqus