NFC - NDEF Tag Reading from WebWorks Applications

by Retired ‎12-07-2011 12:03 PM - edited ‎07-06-2012 04:44 AM (7,599 Views)

Introduction

This article is part of a series intended to act as an introduction to the world of NFC as it applies to BlackBerry® smartphones such as the BlackBerry® Bold™ 9900 and is aimed at developers who wish to take advantage of this exciting new technology. Readers of this article should have some pre-existing knowledge of the fundamental architecture of NFC systems and be familiar with the BlackBerry® WebWorks™ SDK. Familiarity with Java® is required for those parts of the article which deal with the sample WebWorks extension that illustrates how to add NFC NDEF capabilities to a WebWorks application.

 

Importantly, unless you already have good knowledge of the subjects covered, it’s recommended that you read the articles in this series entitled: "NFC Primer for Developers" and “Reading and Writing NFC Smart Tags”. Links to these articles can be found at the end of this one.

 

This article will look specifically at an example WebWorks extension which allows WebWorks applications to read NFC Smart Posters.

 

The Authors

This article was co-authored by Martin Woolley , John Murray and Rob Williams all of whom work in the RIM Developer Relations team and specialise in NFC applications development (amongst other things).

 

About this article

The BlackBerry® 7.0 Java APIs provide BlackBerry Java developers with the ability to read and write NFC tags. However, what about BlackBerry WebWorks developers? Well, as this article and attached sample code will illustrate, WebWorks developers too can quite easily exploit NFC in their applications.

 

BlackBerry Web Works Extensions

The BlackBerry WebWorks SDK allows developers to create great looking and functionally rich BlackBerry applications for either: the BlackBerry smartphone range, the BlackBerry® PlayBook™ tablet or both!

 

Developers use HTML5, JavaScript® and CSS and can leverage a growing WebWorks API to incorporate native device functionality in their applications. The WebWorks API takes the form of a collection of JavaScript functions that provide functionality relating to a large range of areas. Occasionally however, a developer will find that there is no standard WebWorks API function which does what they want. The WebWorks SDK is extensible and developers can write their own extensions which add new APIs that their WebWorks application can exploit.

 

At the time of writing, the WebWorks SDK has no standard NFC capabilities. So the authors of this article have put together a WebWorks extension for the BlackBerry smartphone range and the source code is available in the WebWorks GitHub repository (details below). The extension allows WebWorks applications to register to receive NDEF messages. A simple WebWorks application which uses the extension is also in the repository.

Let’s explore what was involved in creating the extension and how it can be used from a simple WebWorks application.

 

The Sample WebWorks Application

When started, the sample WebWorks application automatically registers as an NDEF listener for NDEF messages relating to “smart posters” and several common image types. It has a simple, one page user interface (as shown in Figure 1) that allows the user to register for “smart posters”, well known image types and a custom type (the interface for the custom type is shown in Figure 2). After registering, an NFC tag (virtual or real) entering the NFC radio field of the BlackBerry smartphone will cause a popup showing certain details of the NDEF message to be displayed (as shown in Figure 3). The JSON representation of the message will be shown in the text area (as shown in Figure 4).  

 

A “real” application would of course do something more interesting with the NDEF message. But we’ll leave such creativity to you, the BlackBerry WebWorks developer.

 

fig1.png

Figure 1 - WebWorks application user interface

 

fig2.png

Figure 2 - Custom type registration is selected - so more fields are visible

 

fig3.png

Figure 3 - Part of a Smart Poster NDEF message is displayed by the WebWorks application

 

fig5.png

Figure 4 - Part of the JSON message representing an NDEF Smart Poster

 

The sample application code resides in several files with the essential code in “index.html”. It includes the in-line JavaScript functions shown here:

 

function initLogging() {
	var ok = blackberry.nfc.ndef.init_logging();
	if (ok) {
	} else {
		alert("The was a problem initialising logging");
	}
}
function registerListener(record_type) {
	var ok = blackberry.nfc.ndef.register_ndef(ndefMessageReceived, onNdefError, record_type);
	if (ok) {
		alert("NDEFMessageListener registered OK for record type "+record_type);
	} else {
		alert("There was a problem registering a NDEFMessageListener for record type "+record_type)
	}
}
function removeListener(record_type) {
	var ok = blackberry.nfc.ndef.unregister_ndef(record_type);
	if (ok) {
		alert("NDEFMessageListener unregistered OK for record type "+record_type);
	} else {
		alert("The was a problem unregistering the NDEFMessageListener for record type "+record_type)
	}
}
// call back functions
function ndefMessageReceived(ndef_message) {
	alert("NDEF message:"+ndef_message);
}
function onNdefError(error_message) {
	alert("NDEF error:"+error_message);
}

  

 

The JavaScript in the index.html page reveals the various API functions exposed or used by the WebWorks extension. These are as follows:

 

blackberry.nfc.ndef.init_logging()

 

The extension classes write log messages to the BlackBerry event log if logging has been switched on.

Calling this API function achieves this. You can then extract the log file from your device using the javaloader tool:

javaloader -u eventlog > eventlog.txt

or you may view it on device by keying “ALT+LGLG”.

Notice that messages are logged at the Information level.

 


blackberry.nfc.ndef.register_ndef(
<callback function>,
<callback error function>,
<NDEF record type>
)

 

By calling the “register_ndef” function, you register your application’s interest in a specific NDEF record type.

callback function - is the function which will be called when a message of the given record type is received.

callback error function - is the function which will be called when an error occurs in the library / processing a message.

NDEF record type – is the type of record your application is interested in receiving. This parameter must be a string. It is interpreted by the extension in two ways.

  1. As a JSON message which must contain the following fields;
    1. type – the type of the message. (examples used in the application are “Sp” and “image/bitmap”
    2. typeNameFormat – a number representing the format of the provided type.

For “Sp” – the typeNameFormat should is “well known” (1)

For a MIME like tag – the typeNameFormat should be “media”. (2)

Some useful constants are included in the file blackberry_nfc_ndef.js. (eg: ndef.tnf.WELL_KNOWN). Keep in mind that these constants should be used and evaluated in JavaScript, not passed to the extension.

  1. For backwards compatibility; if this string does not look like a JSON message, it is treated as a type. The typeNameFormat of the call defaults to “well known” (2).

     

To register for a “Smart Poster”, your code can do the following:

blackberry.nfc.ndef.register_ndef(funca,funcb,”Sp”);

or

blackberry.nfc.ndef.register_ndef(funca,funcb,”{‘type’: ‘Sp’, ‘typeNameFormat’: 1}”);

 

To register for your own MIME payload, your code can do this:

blackberry.nfc.ndef.register_ndef(funca,funcb,”{‘type’: ‘application/fred’, ‘typeNameFormat’:2}”);

 

Note that there is a helper function in index.html to create the JSON from two arguments.

 

blackberry.nfc.ndef.unregister_ndef(
<NDEF record type>
)

 

By calling unregister_ndef you unregister your application as a listener for the given type.
NDEF record type - is logically the same as in register_ndef. It can be just a type, or a JSON message containing a type and a typeNameFormat.

 

blackberry.nfc.isNFCAvailable()

 

At certain times, NFC may not be available on a BlackBerry device which supports it. The most obvious time it is not available is when a user has disabled (or has not enabled) NFC communication in the “Manage Connections” configuration screen.

 

blackberry.nfc.isNFCSupported()

 

Not all BlackBerry devices include NFC support. This function returns true iff the device the code is running on supports NFC.

 

ndefMessageReceived(ndef_message)

 

To be able to receive NDEF messages of a given type when detected, you must implement a JavaScript function which can accept a single parameter as shown. You must supply the name of this function to your invocation of the blackberry.nfc.ndef.register_ndef function. In our example, the name used is ndefMessageReceived but you can choose your own function name. You may also register a different function for each registered NDEF record type or use the same function for all types, the choice is yours.

On detecting an NDEF message of the registered type, the extension will make a call back to the named JavaScript function, passing the NDEF message as a string variable.

The string is a JSON formatted representation of the NDEF message which your application may then process according to its requirements.

 

onNdefError(error_message)

 

Errors which occur whilst processing an NDEF message will be reported via a call back to the call back error function that was specified when registering for the NDEF message type. Here we used the name onNdefError but you can choose your own name.

 

The “index.html” page uses window.onload to initialise itself. Its code is probably best read to be understood. It will check for NFC support and availability, complain if there is none, otherwise register the default listeners. It will also toggle some field visibilities so that the UI makes sense.

 

 

The WebWorks NFC NDEF Extension

Overview

You should already be familiar with the concept and practice of implementing WebWorks extensions. If you’re not, it is suggested that you review the following documentation from the BlackBerry HTML5 and WebWorks microsite:

https://bdsc.webapps.blackberry.com/html5/documentation/ww_developing/using_javascript_extensions_18...

 

This sample WebWorks application has been developed against BlackBerry WebWorks Smartphone SDK version 2.3.1.5 which was the most recent version at the time of the writing of this article.

 

The “src” directory of the extension project (see Figure 3) contains a number of Java classes contained within a package called “widgetpackage”. It also includes an XML file called “library.xml” which defines the feature ID to be used from within JavaScript as the prefix to API methods exposed by the extension and the Java class which implements the “WidgetExtension” interface.

 

We’ll describe each of the classes and interfaces next.

For those people in a hurry however, those classes whose names begin with “Function” implement the three API functions:

  •          WidgetNdefMessageListener is where NDEF messages are received from the device NFC stack;

  •          NdefMessageParser parses the data received and turns it into a JSON string;

  •          NdefJavaScriptBridge passes that JSON string to your Web Works application by calling theJavaScript callback function you specified when registering for this type of NDEF message.

Simple! J

 

fig6.png 

Figure 5 - The NfcExtension project source

 

The Extension Classes and Interfaces

Here is a brief description of the objects as shown in the project in Figure 3

 

Item

Description

 

Constants

 

This contains the definitions of various constant String variables.

 

 

FunctionInitLogging

 

This is a sub-class of ScriptableFunction that implements the “init_logging” function and switches on the logging to the event log.

 

It achieves this by making the following call:

 

Utilities.initLogging(log_id, app_name);

 

Note that you can supply your own “app_name” value as an argument when you call this JavaScript.

 

If you do not, a default value of “NfcExtension” is used and this becomes the application name you will see in the BlackBerry event log viewer.

 

FunctionIsNfcAvailable

This is a sub-class of ScriptableFunction that is used to see if NFC is currently available. This of this as permission from the user (via “Manage Connections” and/or other security dialogues).

 FunctionIsNfcSupported This is a sub-class of ScriptableFunction that is used to see if NFC is supported. Think of this as a hardware check. 

 

FunctionRegisterNdefListener

 

This is a sub-class of ScriptableFunction that implements the “register_ndef” function. It accepts as parameters, a mandatory JavaScript function which will be called to deliver ndef messages, a second mandatory JavaScript function which is used for reporting errors and optionally, a third optional parameter which may specify an NDEF record type or a JSON message containing a “type” and “typeNameFormat”. In the absence of the third, optional parameter, a default value of “Sp” (the official designation of a Smart Poster from the NFC Forum) is applied. Note though, that for the moment, the sample code supports only “Sp” (smart poster).

This means that you should not use other record type values unless you are also prepared to enhance the NdefMessageParser so that it supports your type.

Execution of the invoke() method proceeds by registering the specified NDEF record type and associated call back functions with the FunctionRegistry and then using the NFC ReaderWriterManagerclass to register the WidgetNdefMessageListener singleton object as an NDEF message listener for the given record type. This registration call is handled as shown:

ReaderWriterManager manager = ReaderWriterManager.getInstance();

manager.addNDEFMessageListener(listener,
NDEFRecord.TNF_WELL_KNOWN, record_type, true);

Notice carefully that a final parameter value of true is specified. (Note that the final parameter is deprecated in BlackBerry 7.1)


This indicates that if a smart poster tag is encountered when our WebWorks application is not running the application it will be automatically launched for us.


Under these circumstances the WebWorks application must register as an NDEF listener very soon after being launched (within 15 seconds is a good rule of thumb) in order to receive the call back containing the NDEF message itself.

This is achieved through making a call to registerListeners()('Sp') in ourindex.html page’s window.onLload handler. The net result of all this is that, irrespective of whether our WebWorks application is running or not, it will receive the NDEF message and have the opportunity to process it; provided it has registered at some point to be an NDEF message listener for a given type smart posters at some point after the device was powered on.

FunctionRegistry

Maintains a register of NDEF record types and associated call back functions.

 

FunctionUnregisterNdefListener

 

This is a sub-class of ScriptableFunction which implements the “unregister_ndef” function. Its type parameter behaves the same as FunctionRegisterNdefListener.

It too can accept a record type as a parameter; though, once again, please do note that the sample extension supports only smart poster messages at this time.

The invoke method proceeds by calling removeNDEFMessageListeneron a ReaderWriterManager object as shown:

ReaderWriterManager manager = ReaderWriterManager.getInstance();

manager.removeNDEFMessageListener(NDEFRecord.TNF_WELL_KNOWNtypeNameFormat, record_type);

 

 

NdefJavaScriptBridge

 

This class is a singleton whose purpose is to pass a parsed NDEF message in JSON format back up to the JavaScript in our WebWorks application where it can be acted upon.

 

Its method “useNDEFMessage” is called by the NDEFMessageParser and receives the parsed NDEF message as a JSON string.

 

It then communicates the JSON string to the WebWorks application by invoking the ScriptableFunction object obtained from the FunctionRegistry singleton for the relevant NDEF record type.

 

Similarly, its reportError function looks up the error reporting call back function for a specified record type and calls it to report errors up to the web application layer.

 

NdefMessageParser

 

This is a simple parser which extracts ‘any’ type of NDEF message from a smart poster NDEFthe message from the message received from by the NFC interface.

Note that it only supports smart poster (“Sp”) record types. It implements the Runnable interface so that it can run in a background thread and not block the NFC interface during a potentially lengthy parsing operation.

You may recognise some of this code from the article entitled “Reading and Writing NFC Smart Tags” here: http://supportforums.blackberry.com/t5/Java-Development/Reading-and-Writing-NFC-Smart-Tags/ta-p/1379

 

NfcExtension

This implements the WidgetExtension interface.

All WebWorks extensions must include a class which implements this interface.

It defines a feature ID of “blackberry.nfc”.ndef” and links this to theScriptableNdef the ScriptableNfc class which maps the individual API function names. of “register_ndef”, “unregister_ndef” and “init_logging” to the classes which implement the appropriate logic.Note that prior to this update, this class defined the feature “blackberry.nfc.ndef”. The existing ScriptableNdef class is now access as a property of ScriptableNfc so that logic from blackberry.nfc and blackberry.nfc.ndef are available in the same extension.

 

 

ScriptableNdef

 

Our WebWorks extension must include a class which extends Scriptable and maps the individual API function names of “register_ndef”, “unregister_ndef” and “init_logging” to the classes which implement their logic.

 

ScriptableNfc Our WebWorks extension must include a class which extends Scriptable and maps the individual API function names of “isNFCAvailable” and “isNFCSupported” to the implementing classes. This class also has the field “ndef” to offer access to ScriptableNdef.

 

Utilities

 

A simple “utility” class which contains various static methods including those concerned with logging to the event log.

 

URLPrefixes

This class is a collection of constants for decoding the standard NDEF URI prefixes. NDEF specifications state that URLs are transmitted for a very basic compression.

URIs generally start with a very small number of prefixes so it is easy to compress them.

For example “http://www.” is 11 bytes of text – but can be sent in 1 byte thanks to these prefixes.

 

WidgetNdefMessageListener

 

This implements the NDEFMessageListener interface. It is here that NDEF messages are initially delivered by the NFC sub-system.

 

On receipt of a call back to its onNDEFMessageDetected() method, it invokes the parseAndDeliver() method of the NdefMessageParser, resulting in the message being parsed and converted into a JSON string which is then delivered via the NdefJavaScriptBridge to our JavaScript code.

 

NdefMessageParser.getInstance(message).parseAndDeliver(message);

 

 

 

The JSON Message

Here's an example of the full JSON message as received by the WebWorks application from the extension:

 

{
  "uri":"http://www.thenedoko.com",
  "url":"http://www.thenedoko.com",
  "text":"The Nedoko",
  "textValues":[
    {
      "id":"",
      "type":"T",
      "typeNameFormat":1,
      "payload":[
        2,101,110,84,104,101,32,78,101,100,111,107,111
      ],
      "languageCode":"en",
      "value":"The Nedoko"
    }
  ],
  "id":"",
  "type":"Sp",
  "typeNameFormat":1,
  "records": -- removed for clarity --,
  "payload":[ 145, 1, . . . -- removed for clarity -- ]
}

 

Let’s look at each element – note that the ordering is not significant.

 

"uri":"http://www.thenedoko.com",
"url":"http://www.thenedoko.com",

The uri of a SmartPoster. The uri field was added to match the naming used in NDEF documents. The url field remains for backwards compatibility.
 "text":"The Nedoko", This is the text of the first element of text found in the SmartPoster 
 

"textValues":[
{
"id":"",
"type":"T",
"typeNameFormat":1,
"payload":[
2,101,110,84,104,101,32,78,101,100,111,107,111
],
"languageCode":"en",
"value":"The Nedoko"
}
]

This is an array of ALL text elements found in the SmartPoster. Your application can iterate through the array and chose the most appropriate for your user based on the languageCode.
 "id":"", The id of the record. 
 "type":"Sp", The type of the record. For an NDEF SmartPoster, this will be “Sp”. 
 "typeNameFormat":1, The typeNameFormat of the record. For an NDEF SmartPoster, this will be 1. 
 

payload":[ 145, 1, 14, 85, 1, 116, 104, 101, 110, 101, 100, 111, 107, 111, 46, 99, 111, 109, 81, 1, 13, 84, 2, 101, 110, 84, 104, 101, 32, 78, 101, 100, 111, 107, 111

  ]

 

This is an array of numbers which are the actual bytes that were contained in the payload of the NDEF record.

 

In general, there’s no reason to read these. If you want to parse your own content though – accessing payload is your start point.

 

The Fake button in the GUI sends a very small (and badly drawn) image. It is in a MEDIA record. Here’s what the JSON looks like:

 

{

  "records": -- removed for clarity --

  "id":"",

  "type":"image/bmp",

  "typeNameFormat":2,

  "payload":[ 67, 77 -- removed for clarity -- ],

  "mimeType":"image/bmp",

  "body":"Qk1+AAAAAAAAAD4AAAAoAAAAEAAAABAAAAABAAEAAA -- removed for clarity --",

  "dataURI":"data:image/bmp;base64,Qk1+AAAAAAAAAD4AAAAoAAAAEAAAABAAAAABAAEAAA -- removed for clarity --"

}

 

"type":"image/bmp", This is a MIME type that we registered for. The sample application registers for several common image types. The typeNameFormat
 "typeNameFormat":2, The type name format is MEDIA (2).
 "mimeType":"image/bmp", This field is added for convenience reasons by the parser, it is the same as type
 "body":"Qk1+AAAAAAAAAD4AAAAoAAAAEAAAABAAAAABAAEAAA…" This is a Base64 encoding of the payload of the record.
 

"dataURI":"data:image/bmp;base64,Qk1+AAAAAAAA…"

This is a data URI which uses the Base64 encoding in body. In the sample application, this dataURI is used to populate an <IMG> 

 

Records…

 

You can use the extension without caring at all about its use of records, but here’s how it works and what it does.

 

The records element was removed above – for clarity. The records element reveals the NDEF structure;

  • an NDEF message can contain multiple NDEF records. Each record could be a different type (and type name format)
  • a SmartPoster contains multiple NDEF records. ie: An NDEF record containing NDEF records.
  • the code only works with self contained, complete records

 

The current message parser does the following;

  • all outer records are decoded and placed in the top level records array of the JSON object.
  • all inner records are decoded and placed in the records array of the correct object to accurately represent the record tree.
  • all attributes of the first record (except for records) are copied into the root level object.
    • For the SmartPoster example, this means that x.url === x.records[0].url (etc).

 

Future Evolution of the Extension

The code for the WebWorks extension described in this article is available from our GitHub repository. We’d love to see contributions from the community which result in the extension becoming more fully functional and useful. The version presented here supports tag reading but does not support tag writing. Nor does it support other aspects of NFC. There’s a lot we could do together.

 

As far as NDEF tags are concerned, we believe there to be no reason to design a JSON structure to represent NDEF messages. That work has already been done by the NFC Forum. What we need from our Web Works extension is a way to deliver that same structure in a JSON format. Just our $0.02. What do you think?

 

Summary

This article should have demonstrated how easy it is to exploit NFC from a WebWorks application.

 

The place to go for more information on the BlackBerry WebWorks SDK is here:

https://bdsc.webapps.blackberry.com/html5/ 

 

BlackBerry Java APIs are documented here if you'd like to browse further: http://www.blackberry.com/developers/docs/7.0.0api/

 

Source code for the WebWorks NFC extension described in this article is in the following GitHub repository:

https://github.com/blackberry/WebWorks-Community-APIs

 

And finally, the sample application can be found embedded in the page here:

https://github.com/blackberry/WebWorks-Community-APIs/tree/master/Smartphone/NFC

 

Other BlackBerry Developer NFC Articles

 

See the NFC Article Index for the list of other articles in this series

 

 

Glossary of NFC Terms

  • APDU - Application Protocol Data Unit. A message type which forms part of a protocol and which may be exchanged between peers as either a request or a response message. Applications on a BlackBerry smartphone may communicate with applets in an SE using the ISO7816-4 APDUs for example.
  • CLF - Contactless Front-end. Part of the NFC Controller. Communicates via RF with an NFC reader.
  • HCI - Hardware Controller Interface. Amongst other things, this component of the NFC system architecture redirects radio communication to appropriate SE.
  • ISO7816-4 - the specification which defines the protocol which allows applications to communicate with applets installed in an SE or smart card.
  • NDEF - NFC Data Exchange Format
  • NFC - Near Field Communications
  • PCD – Proximity Coupling Device (also known as “card reader”)
  • PICC – Proximity Integrated Circuit Card
  • SE - Secure Element. A hardware component which can host and act as an execution environment for small software applications known, in this context, as "applets".
  • SIM - Subscriber Identity Module. In 2G modules this used to be synonymous with the SIM *card* i.e. the small smart card inserted in the handset. In 3G networks, the SIM is a software module installed on the UICC.
  • SWP - Single Wire Protocol.
  • UICC - Universal Integrated Circuit Card - the smart card used in mobile terminals in GSM® and UMTS® networks