It was good seeing so many familiar faces from Launchpad at our 2012 Americas AppForum  in Schaumburg, IL earlier this month.  Thanks to all those who managed to make it to my session and for those who couldn't make it I understand they'll be posting it online in the coming weeks.

 

In the following blog post I'll walk through the application that I built up during the presentation, "Adding Device Capabilities and HTML5 features to your Application".  You'll find my slides at https://launchpad.motorolasolutions.com/appforum/presentations/rhomobile/Adding%20Device%20Capabilities%20and%20HTML5%20Features%20to%20your%20Application.pdf.  The "Event Attendee Tracker" application is designed to be used at events such as the app forum to keep track of the attendees in each session.

 

1) The Event Attendee Tracker Web Application.

  This shows HTML5 local storage.

  Web App.png

So here's the web application, it doesn't use any device capabilities and so you can run it fully functional in any HTML5 capable web browser (any modern browser).  The idea here is that you're using any device and you're standing at the door of the session keeping track of the number of people that come into the room.  To use the app select the session name from the drop down and then hit the 'add attendee' button as people enter the room.

 

I use the HTML5 concept of 'local storage' to keep track of two important items of data here:

* Which session has been selected in the combo box

* How many people are in each of the sessions.

 

Have a play with the application by downloading "EAT-1.zip", as I say you don't need a device to try this out, just launch it in your browser.

 

Here's the Javascript code when the user hits the 'add attendee' button:

function onAddAttendee()

{
          sId = localStorage.getItem('sID');
          if (sId != -1) 
          {
                    var iAttendees = localStorage.getItem("RE-" + sId);
                    if (iAttendees != 'NaN' && iAttendees != null)
                              attendeeCount.innerHTML = iAttendees; 
                    else
                              attendeeCount.innerHTML = 0;
                    var nAtt = parseInt(attendeeCount.innerHTML) + 1;
                    attendeeCount.innerHTML = nAtt;
                    localStorage.setItem("RE-" + sId, nAtt);
          }
}

 

Notice the lines "localStorage.getItem..." and localStorage.setItem...".  You can think of local storage as a series of name-value pairs.  The sID key refers to the combo box, so retrieving the value for this tells us the currently selected session.  The RE-sID keys refer to the number of attendees in each session, it is this item of data that we're incrementing when the button is pressed.

 

2) The Event Attendee Tracker Application with Scanning

 

OK, so having the ability to keep track of the number of people in the room is quite swish but it's far from the capabilities of a Mobile Device (it's far from the capabilities of a pencil and piece of paper!)  What we're going to do now is to integrate Scanning into our application.

 

Event Attendee Tracker 2.png

 

Now imagine the conference is being attended by delegates who have all been issued with ID badges that have QR code barcodes printed on them, much like the screenshot below which I prepared earlier.

 

DevConfBadge.png

 

These barcodes contain the name and company of the delegate, along with some additional information that we won't be using in this application.

 

Now we will modify our application to use the Scanner capability of the device, try it yourself by loading 'EAT-2.zip' on any Motorola Device.  To do this install the RhoElements shared runtime and modify your config.xml file to point to your application, here's the detailed steps for installation:

 

1) Download RhoMobile Suite from http://www.motorola.com/Business/US-EN/RhoMobile+Suite/Downloads (any version will do)

2) Install RhoMobile Suite on your PC (or Mac)

3) On your PC navigate to C:\MotorolaRhoMobileSuite2.0.5\RhoElements2 Shared Runtime

3.1) You might have to modify the directory slightly if you didn't install to the default location

4) Install the appropriate .cab / .apk file for your device

5) On WM / CE navigate to \Program Files\RhoElements\Config\ and copy config.xml to your PC using activesync (on Android you'll find the config file after launching under com.motorolasolutions.rhoelements)

6) Copy the EAT-2 application to your device filesystem under \eat

7) Modify your config.xml to point your start page to file://\eat\index.html

8) Copy your config.xml back to the device, overwriting the old file and launch RhoElements from the start menu.

 

OK, now you've seen it working, let's take a look at the relevent bits of Javascript to enable the Scanner (http://docs.rhomobile.com/rhoelements/scanner):

 

//  Called on session change
function enableScanner()
{
          scanner.decodeEvent = 'doScan(%json)';  //event handler
          scanner.enable(); //enable default scanner
}

 

function doScan(scanData)
{
          displayScanData(scanData.data);
}

 

That's all it is, pretty simple huh?  The 'enableScanner()' function declares a Javascript function that will be called whenever a barcode is decoded and then enables the Scanner.  Enabling a scanner puts the hardware in a state where pressing the yellow trigger key on the device will start a scan.   Each successful barcode scan will result in the doScan function being called which takes a JSON Object containing the data associated with the scan, here's what the displayScanData function looks like:

 

function displayScanData(scanData)
{
          onAddAttendee();  //  Same code as local storage example
          var attendeeData = getVcardInfo(scanData,'fn') + " : " +           getVcardInfo(scanData,'org');
          var scanInfoField=document.getElementById('scanInfo');
          document.getElementById('scanInfo').innerHTML          =           attendeeData; 
}

 

The QR code is parsed to extract the delegate's name and organisation, this delegate information is then output to the DOM so the greeter can say, "Welcome <name> from <organisation>, I hope you enjoy this session"

 

Again, for the complete code listing, download and have a browse through EAT-2.zip, the ONLY file modified from EAT-1.zip is index.html (search for my initials, 'dcc' to see the changes, that's what I used to make quick changes on the fly during the presentation).  I've also attached a Word document of the barcodes you'll need to play with the app at the bottom of this blog.

 

3) The Event Attendee Tracker Application using WebSQL

 

OK, so those sharp eyed readers amongst you will notice that it's a bit superfluous scanning a barcode on the name badge just to say "Welcome <name>" when the name and organisation are printed right there on the badge in plain text!!

 

We're going to make this application a bit more useful now by adding WebSQL capabilities.  WebSQL is not technically an HTML5 feature as it was removed from the specs for technical reasons.  You'll find it has become a defacto standard adopted by all the major browsers however and is incredibly powerful, giving you an essentially complete SQL interface to a database that is created right there on your device.  WebSQL is particulrly useful in partially connected environments, imagine your worker on the edge of a connection scanning barcodes in a warehouse which are uploaded via AJAX to a server for processing.  When the device loses connection (see the network module for how to detect this, http://docs.rhomobile.com/rhoelements/network), rather than stop the user working you can store the barcodes in a WebSQL database and then upload them when the device re-establishes connection.

 

Event Attendee Tracker 3.png

 

So now whenever we scan a barcode we'll add the delegate to a Web SQL database and display the updated contents of that database on the screen.

 

We need to modify our doScan function we dicussed earlier, rather than display the delegate's name / organisation now we'll just insert it into the database along with the time they entered:

 

function doScan(scanData) {
          dbInsertScanData(scanData.data, scanData.time);
}

 

Now for the SQL 'nitty gritty', here's the code for creating the database:

 

function dbInit() {
          //  Estimated size of around 5MB
          db = openDatabase('EventTracker', '1.0', 'Attendee Tracker', 5000000); 
          db.transaction(function(tx)
          {
                    tx.executeSql("CREATE TABLE sessionAttendees (sessionId TEXT,scanData TEXT,scanTime TEXT)", [],
                    function(tx) {},
                    onError);
          });}

 

A few things to point out here:

1) We create the database with a size of 5MB, this seems to be the industry standard and if you want to specify a value greater than 5000000 here you'll need to also modify your config.xml to increase the size WebKit allocates for each database.

2) The line "CREATE TABLE sessionAttendees (sessionId TEXT,scanData TEXT,scanTime TEXT)" is standard SQL, you could run that against any database engine

3) Each transaction takes two anonymous Javascript functions, the first is executed on success and the second is executed if the transaction failed.  In this example we do nothing on success and we have a standard error handler for any errors.

 

The code for inserting the scanned data into the database looks like this:

 

function dbInsertScanData( scanData, checkInTime) {
          sessionId = localStorage.getItem('sID');
          db.transaction(
                    function(tx) {
          tx.executeSql("INSERT INTO sessionAttendees ( sessionId,scanData,scanTime) VALUES (?,?,?)", 
[sessionId, scanData,checkInTime],
                              function(tx, result) {
                                        onAddAttendee();  // as Local Storage
                                        fnDbLoadData(sessionId);
                              },
                              onError);
                    }
  );
}

 

Hopefully it should be easy to follow, again the SQL is fairly standard, this example showing the INSERT syntax.  Notice that I call fnDbLoadData after each scan, this ensures the latest database data is read and displayed on the page.  The code for this is shown below:

 

function fnDbLoadData(sessionId) 
{
          db.transaction(function(tx) {
                    tx.executeSql("SELECT sessionId, scanData, scanTime 
                                        FROM sessionAttendees WHERE sessionId=? 
                                        ORDER BY scanTime DESC", [sessionId], function(tx, result) {
                              for (var i = 0, item = null; i < result.rows.length; i++) {
                                        //  Add Rows to the HTML
                                          //  record = result.rows.item(i);
                                        //  scanTime = record['scanTime'];
                              } 
                    }
          }
}

 

Well, this isn't the full code, it's been edited for brevity and this isn't a tutorial on processing recordsets returned from DBMS transactions, the way you do this is common with every other language you have used.

 

Again for the full code listing just take a look at "EAT-3.zip"

 

It's beyond the scope of this blog to discuss the full WebSQL syntax.  If you do a google search for 'WebSQL' you'll find a number of hits which I won't link to here as they're not authoritative.  I would suggest searching wider afield than the W3C spec, that doesn't contain many examples.

 

4) Adding a battery icon

 

OK, so we're doing good, we're scanning barcodes as people arrive, greeting them and keeping a detailed log of who is late for each session so we can tell their managers... but all this is for nothing if our device's battery dies as we're half way through the conference!

 

To avoid our users having running out of juice we'll display a battery icon on the page so they know when to charge, here's the code for doing this in Javascript:

 

function showBattery()
{
          battery.visibility = 'visible';
          battery.left = 210;
          battery.top = 9;
          battery.color = '#0373BD';
          battery.layout = 'up';
}

 

If you want to see the documentation for the battery module then head over to http://docs.rhomobile.com/rhoelements/battery, you'll see this example shows the battery indicator around the center of a VGA screen, near the top.  Those readers who can interpret hex colours will also see the battery indicator will be a pastel shade of blue.

 

Event Attendee Tracker 4.png

 

You can see the updated application at "EAT-4.zip", though it's only a two line change from "EAT-3.zip" to uncomment the call to showBattery() on page load.

 

That pretty much covers the Event Attendee application so have a play and leave a comment below if you feel like it. I covered more than just this application in my presentation including application cache and cross platform considerations so watch the whole recording when it's posted if you want to learn more.

 

Here's the link to the slides again: https://launchpad.motorolasolutions.com/appforum/presentations/rhomobile/Adding%20Device%20Capabilities%20and%20HTML5%20Features%20to%20your%20Application.pdf