Monday, January 18, 2010

Crossing The PhoneGap For Multiplatform Mobile Applications

I had first heard of the PhoneGap open source framework for multiplatform mobile development last year at the FutureRuby conference in Toronto. Honestly, I did not really concentrate on all they were saying at the time, and in the flurry of info including back-to-back mobile sessions with Rhomobile, I did not fully retain a clear picture of what they had to offer. My bad.

It was not until late last year, while working on plans for a very cool mobile application, that I was reminded about PhoneGap by one of my colleagues. After a brief evaluation of their benefits vs. the other multiplatform options, we decided to use PhoneGap on this particular project. We have made some amazing progress with using PhoneGap for mobile development since then, and I thought I would share a few of the lessons learned.

First of all, a quick explanation of how PhoneGap works. Jesse MacFadyen, one of the programmers at Nitobi, the primary developers of PhoneGap, has a good blog post where he breaks down how the PhoneGap framework works on iPhone. Here is my much condensed take on what he is saying.

All of the mobile platforms supported by PhoneGap have some kind of web browser control. A PhoneGap application is a packaged up application which is a webpage or mini-website, that executes inside whatever web browser control is available on that platform. Add in a standard JavaScript API to a wrapper that accesses the device-specific functionality like GPS or the accelerometer, and you can hook up the JavaScript on your "page" to the hardware.

But don't make the mistake of thinking you should just slap together some web pages formatted for mobile. Rather, you can and must think of it as an application that is written in the form of a single web page with a bunch of JavaScript. To access server data, you will need to write some AJAX code to access the remote resources, then update your UI accordingly. The good news is you can use familiar JavaScript libraries such as jQuery to do so. We chose jqTouch to get a very iPhone-like UI.

The PhoneGap framework is under very active development. New code is being committed to their github repo frequently. As such, you really do need to have git installed, and some working knowledge of how to use it, to get things setup.

In fact, the device specific functionality for each platform is contained within the main PhoneGap git repository as a series of git submodules such as phonegap-iphone, phonegap-android, etc. This makes it all but impossible to install the latest and greatest without git. Being a git user myself, this does not pose any problem, and if you are not gitmotized yet, this is an ideal time to become so.

Here are the series of steps I followed to create my own PhoneGap project...

Prerequisites

  • Install iPhone SDK (yes, you must join the iPhone developer program)

  • Install Android SDK (http://www.talkandroid.com/android-sdk-install-guide/ has some good instructions. I am not using Eclipse, so I skipped all that)

  • Install Apache Ant (sudo port install apache-ant)


Install PhoneGap

  • Get latest PhoneGap (git clone git://github.com/phonegap/phonegap.git)

  • Get submodules for iPhone & Android (cd phonegap && git submodule update)

  • Build iPhone Lib and install

  • Build Android libs


Setting Up A New Multiplatform PhoneGap Project

  • Create a new iPhone project using the phonegap-iphone template. The www directory in the new project will be becoming the shared part of your project, with all your UI and application logic

  • Create the Android project using the phonegap-android build script. Use the www directory from the iphone project as the www-dir param. You will be replacing this with a reference to the git submodule

  • Create a new git repo in the www directory in the iPhone project, and commit all the files in the www directory

  • Change directories to the parent of where you want to put the directory for the shared git repo, then clone the repo located at /path/to/iphoneproj/www to /path/to/sharedrepo. You may also want to create a remote branch at this point for the new shared repo

  • Remove the www directory from the iPhone project

  • Create a new git repo in the iphone project directory, then commit all files. You may also want to create a remote branch at this point

  • Put the shared code into the iPhone project by using "git submodule add" to put a reference to the shared repo into /path/to/iphoneproj/www

  • Create a new git repo in the Android project directory, then commit all files. You may also want to create a remote branch at this point, as you probably did for the iPhone project files

  • Remove the /path/to/androidproj/assets/www directory from the Android project, and use "git submodule add" to put a reference to the shared repo at /path/to/androidproj/assets/www


You now should have 3 git repos, with the shared code, the iPhone specific project code, and the Android specific project code, each in their respective places. Much easier and nicer to work on.

Anyhow, I hope this info is useful to any PhoneGap developers that want to get things setup cleanly for multi-platform mobile programming. Please let me know any feedback or improvements that people out there come up with, for this neat open source framework for doing JavaScript-based mobile development.

Tuesday, January 12, 2010

Sparkline Some Interest With Ruby on Rails

Recently, I added some sparkline graphs to a Ruby on Rails application. A sparkline is a very small graphic that displays a large amount of information, typically shown over time, and usually embedded in some other text. Invented by the father of modern infographics Edward Tufte, the sparkline has become a fixture of many online applications that want to visually display some stats in a simple, integrated way.

When it come to adding sparklines into a Ruby on Rails application, there are a couple of different options. You can chart the data on the server, output being an image file. You can also chart the data on the client, with a couple of different JavaScript libraries as available options.

I started my plan, intending to implement my charts on the client-side. The project that appears to have the most flexibility, speed, and options, is an amazing jQuery plugin called jQuery Sparkline. Unfortunately, the project to which I needed to add the sparklines is a bit older, and does not use jQuery. As a result, I was not able to use jQuery Sparkline for this current project.

Another interesting JavaScript sparkline library is lethain's Sparkline.js, but it has not been updated in some time, and is not compatible with current Internet Explorer versions. There is also an interesting looking newer lib topfunky-sparkline-js but I have not tried it out yet.

So that brings us to server-side sparkline generation. If you are using ImageMagick/RMagick then @topfunky once again provides, with the Ruby sparklines gem. This gem provides lots of options for doing all sorts of fancy sparklines.

In my case, I am not using ImageMagick for anything else, so I did not want to install it just for this. What I really wanted was something much lighter-weight, and I was willing to accept a lot fewer options to get it.

It turns out that madrobby has written a library for generating very simple sparklines in pure Ruby code, called spark_pr. The project uses _why's pure Ruby implementation of a PNG generator to do the low-level work.

spark_pr has also spawned an interesting application of it from @technoweenie called Sparkplug, which is a Rack module that generates spaklines from CSV data on the fly, using Rack handlers and Rack caching.

Once I had seen Sparkplug's minimal elegance, it seemed spark_pr was the option for me. I decided to incorporate spark_pr into my application. Given that the app was written with a dedicated approach to keeping a clean RESTful interface, and that the database already contained the time-series data, it was quite easy to incorporate. Here is what I had to do:

Step 1: Put spark_pr.rb file into lib directory. I just grabbed the code from the repo, and dropped it into my project. You may decide to have a more sophisticated way to do it, such as using git submodules.

Step 2:
require "spark_pr"
in your controller

Step 3:
include Spark
in your controller

Step 4: Add PNG format to controller action that was already returning my time-series data, and return the sparkline PNG data:

Note that this controller action is already returning XML or JSON. PNG is just another format to be added, if you have a well-designed RESTful controller action.

Step 5: Put image_tag that requests the sparkline PNG image file into the view where you want it to appear, like this one:


Voila! Refresh that view and you should now be looking at your ultra-hipster-chic sparkline graph. It is surprising how much more information comprehension a person has, when they are seeing a visual representation of their data. Plus it looks cool.