On cross-device mobile development – Part 1

Once in a while a demand for fast development of a mobile application for several platforms at once comes up. Your team of developers might be small or knowledge about the different Software Development Kits (SDKs) involved is scarce. But hey, perhaps you know how to write HTML & CSS and are also experienced with JavaScript. With the advent of the Apple iPhone and briefly afterwards the Android line of phones, mobile devices started to support a lot of modern HTML & CSS features. The progressing “applification” of the WWW further boosted the development of fast JavaScript engines. And with the recent addition of multitouch, geolocation and fast CSS3 animation support, the mobile browser has become a new deployment target for mobile applications. That’s the theory at least. In this series of articles we will provide an overview on the technologies involved, available frameworks and the approaches taken to bring your application to several mobile platforms at once.

It’s (not) in the browser

Developing applications with HTML, CSS & Javascript is a fundamentally different experience. It already is on the normal desktop with its widescreen browsers. On a mobile device it becomes a game changer. We are accustomed to graphical user interface (GUI) toolkits with their more direct manipulation of data through on-screen elements like buttons. While browsers and HTML provide their own set of UI elements and the ability to wire events like clicks to Javascript callbacks, they lack a lot of the bells and whistles. Especially in the handling of client-side data — the model in model-view-controller (MVC) so to say — and the controller abstraction even modern browsers lack the feature richness of common native SDKs. In the rest of this article we will give a short overview on which web technologies map to which concept in the MVC approach and how you would basically structure an application based on such technologies.

Of models, views & controllers

In “Building iPhone Apps with HTML, CSS and JavaScript” Jonathan Stark describes how to turn websites into single page iPhone applications. Views are implemented straight forward with plain HTML and CSS, throwing in some bits and pieces to make browser standard behavior of HTML elements more native like. To give an example, we will show how to create a graphical navigation bar and switch between different screens. First we need some HTML and CSS snippets to create the layout:

<ul id="navigation">
 <li><a class="current" href="#home">Home</a></li>
 <li><a href="#new">New things</a></li>
 <li><a href="#favorites">I like those</a></li>
 <li><a href="#more">More content</a></li>
 <li><a href="#info">About</a></li>
</ul>
<div class="view" id="home">...</div>
<div class="view" id="new">...</div>
<div class="view" id="favorites">...</div>
<div class="view" id="more">...</div>
<div class="view" id="info">...</div>

The navigational items are then replaced with nice button graphics via CSS and positioned on the page.

/* navigation is a fixed block */
#navigation {
  position: fixed; top: 0px; left: 0px;
  width: 320px; margin: 0; padding: 0;
}
#navigation li { display: block; position: absolute; }
#navigation li a {
  display: block; position: absolute;
  height: 48px; width: 80px; top: 0px;
  text-indent: -9999px;
}
a[href="#home"] { background: url(home.png); left: 0px; }
a[href="#home"].current { background: url(home-current.png); }
a[href="#new"] { background: url(new.png); left: 80px; }
a[href="#new"].current { background: url(new-current.png); }
a[href="#favorites"] { background: url(favorites.png); left: 160px; }
a[href="#favorites"].current { background: url(favorites-current.png); }
a[href="#more"] { background: url(more.png); left: 240px; }
a[href="#info"] {
  background: url(info.png); position: fixed;
  width: 48px; height: 48px; bottom: 16px; right: 16px;
}
/* finally position the views themselves */
div.view {
  position: absolute; top: 48px; left: 0px;
  width: 320px; height: 396px;
}

This can act as a simple framework for an application with multiple views. Now we still need to make our navigation controller to switch between the different views. jQuery to the rescue — a small snippet initializes our view hierarchy and provides switching capabilities:

$(document).ready(function() {
    var navitems = $('#navigation li a');
    navitems.click(function() {
        navitems.removeClass('current');
        var ref = $(this).addClass('current').attr('href');
        /* hide the other views, show the one navigated to
           and trigger a custom event */
        $('div.view').hide(); $(ref).show().trigger('becameActive');
    });
    $('div.view').hide();
    $("div.view.current").show().trigger('becameActive');
});

With custom events like becameActive it is easy to create new callbacks that are invoked when state changes occur — in this example when switching the active view through our navigation controller. For brevity we will omit a elaborate example of controller code, but if for example you want code to run when switching to the #new view, you could simply write:

$('#new').bind('becameActive', function(event) {
  $(event.target).doSomething();
});

So what is still missing now? We still haven’t provided a data model to operate on. While data provided via web services is not a big deal by the use of JSON-APIs, we would certainly want to have a local data storage too. For quite some time already, web engines provide a local SQLite-based storage system. On application initialization we can simply setup some tables to hold our data and send statements from anywhere in the application later on:

// open a database, providing it's name, version,
// maximum size and display name
var database = openDatabase("Example", "1.0",
  1048576, "Example Database");
database.transaction(function(transaction) {
  transaction.executeSQL(
    "CREATE TABLE IF NOT EXISTS data" +
    "(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," +
    "... more declarations ...);");
});
// other statements are issued the same way
database.transaction(function(transaction) {
  transaction.executeSQL("SELECT * FROM data;",
    function(transaction, result) {
      // do something with 'result'
  });
});

Putting it all together

A question remains: when this is the basic skeleton of an application, how do i put this on an actual device?

Example in Simulator
While this could be simply served by a web server to a mobile device, the main reason for developing applications instead of websites is the ability to expose them through an application store (e.g. Apples AppStore or the Android Market). We won’t go into much detail here now — this is something to be discussed in the following blog posts in this series — a simple answer is provided by a small framework named PhoneGap. PhoneGap provides the developer with a cross-platform deployment environment, which makes use of the web engines on the different mobile devices. It basically is a fullscreen web browser view, without any UI elements and other decorations but with added support for accessing hardware features of the actual device. Next to the already mentioned features, which are part of the modern web engines, it gives access to features like cameras, accelerometer or access to the native phonebook of your mobile phone. You simply drop all your HTML, CSS & JavaScript into a PhoneGap application package which is built for your particular device and are ready to deploy through any application store or similar channel you like.

What’s next?

So developing mobile applications with HTML, CSS & JavaScript is actually easy, isn’t it? Well, with the basic ideas outlined above it is — until it isn’t anymore. In the parts of this series which are still to come, we will answer some questions, that might be crucial to your development cycle:

  • What problems might arise with JavaScript as a development language? Is there enough tool support for ease of development?
  • What do i have to program from scratch and which frameworks are available, that erase my need of boilerplate code?
  • What about the performance, for example when sophisticated animations are desired?
  • Is my application really cross-platform, when using these technologies, and does it behave exactly the same on every device?

Stay tuned for more.