This article show the step-by-step development of a Windows Phone 7 HTML5 application using PhoneGap. It also looks at how viable this approach is for cross-platform mobile development.
Introduction ... and Why HTML5?
PhoneGap support for Windows Phone 7 was initiated by Matt Lacey, who created an initial implementation of the PhoneGap APIs. More recently Nitobi (who run PhoneGap), announced an official beta release, which they have worked on in conjunction with Microsoft.
Getting Started With PhoneGap
PhoneGap has a project template which will help you create an initial "Hello World" style application. You can get started by following these steps:
- Download the WP7 PhoneGap from https://github.com/phonegap/phonegap-wp7
- Copy the file GapAppStarter.zip, which contains the project template, to the folder
\My Documents\Visual Studio 2010\Templates\ProjectTemplates\
- Create a new project using the GappAppStart project template. I could not locate this template within the tree of 'Installed Templates', so used the search function. See the image below.
- Add the framework\WP7GapClassLib.csproj project to your solution and add a reference to this project.
- Build and run!
If you followed these steps correctly, you should see the following:
Dissecting the Example App
The example application is a bit more complex than an equivalent Silverlight 'Hello World' app, so we'll look at it in some detail ...
GapSourceDictionary.xml file, this XML file lists all the HTML application resources. When the application starts, this XML file is read, and each file is added to isolated storage so that it can be served by the WebBrowser control:
The MainPage.xaml, which is the Silverlight UI for the application contains an instance of PGView:
"www/index.html" (although this will probably be configurable in future).
index.html file from the template project is shown below (minus a few un-important parts):
The important parts to note here are, firstly the viewport metadata, which relates to the complications that small mobile screens present to layout, resulting in the need for a separate layout viewport and visual viewport, as described in the article "a tale of two viewports". Here the width is set to 320px, so each pixel-width in our HTML is two pixels on screen. I prefer one-to-one correlation, so would change this to the physical phone dimensions. The "user-scalable=no" should prevent the user from being able to pinch-zoom the page, unfortunately on my (mango) phone, this doesn't seem to be working. This is a shame, because it really spoils the illusion of this being an application rather than a web-page.
Creating the Property Search Application
propertySearch.js (adding this to
GapSourceDictionary.xml of course). The HTML has the following markup, a simple form that can be used to input the string to search for:
The event handlers are wired up as follows:
The search properties function is a simple AJAX call to the Nestoria APIs, using the jQuery ajax() function, which manages the JSONP process of dynamically adding a script tag to the DOM which fetches the required data.
NOTE: The application uses the Nestoria UK APIs, so if you are trying it out in your emulator, set your location to somewhere in the UK!
I am using a jQuery templates to render each item. You can render an array of items via the
tmpl() function, however, here I render each one individually, so that I can associate the raw JSON data for each property with the generated element via the jQuery
data() function. This is rather like defining the
DataContext for a Silverlight FrameworkElement.
When a property is clicked, the following function is invoked, which locates the clicked DOM element, then extract the JSON property details via the
data() function described above. This is used in conjunction with another template to render the property details:
The template is shown here:
The navigation between pages is achieved by having the markup for both pages present in the DOM:
The pages are styled to use absolute positioning:
We can then show / hide these pages by simply animating their CSS left property:
It is worth noting that if the IE9 browser supported CSS3 transitions all of the above could have been done declaratively within CSS, unfortunately animations are not in the list of supported features. There is nothing wrong with jQuery animations, they have a very concise and simple syntax. However, CSS3 animation give the browser the option to use GPU acceleration, greatly improving performance. The webkit browsers on Android and iOS support this feature (using the -webkit prefix on the required CSS properties).
The standard style for HTML controls doesn't look that great, however, with a simple bit of CSS it is possible to re-create something similar to the WP7 Metro styles. Here I have copied some of the properties that are present in the Silverlight resource dictionaries:
For a bit of fun I thought I'd try and create a HTML equivalent of the 'trailing dots' WP7 ProgressBar. With a simple bit of markup / CSS:
And some further jQuery animations, this time making use of the easing plugin:
We get something which approximates the WP7 progress bar:
(Note, sometimes the animation goes a bit crazy, try refreshing your browser to reset it!)
Again, my comments regarding CSS3 animations and GPU acceleration apply here also.
As I have discussed in a previous blog post, tombstoning is a tricky task for WP7 developers. When your application is tombstoned you can save application state, page state - and the framework stores your back-stack URIs. It is your responsibility to re-start your application in the same state. Contrary to the belief of some developers I have talked to, Mango does not remove the need to tombstone, it just means that your application is likely to be tombstoned less often, with the suspended state being used to park your application while application switching.
I would be very interested to hear from anyone who has solved this issue!
The Development Process
However, to do this, you need to mock the PhoneGap APIs. For my application, I found the following did the trick:
OK, I know what you are thinking, what about the geolocation code? Where is the mock for these PhoneGap APIs? The answer is that a number of the PhoneGap APIs are designed to exactly match the corresponding HTML5 specification. So for example, the PhoneGap geolocation API is exactly the same as the HTML5 geolocation APIs. For phones such as WP7 where the browser supports this HTML5 feature, PhoneGap does nothing, for phones that do not, PhoneGap provides an implementation (using the native APIs).
If the PhoneGap mock is so simple, you might be wondering, why use PhoneGap at all? Well, PhoenGap is still giving us a mechanism for packaging files into a XAP file in such a way that they can be rendered by the browser.
How cross-platform is this approach?
How viable are HTML5 applications?
Currently, PhoneGap for WP7 is in beta, and it is certainly a little rough around the edges. This will no doubt improve in time. The large list of applications written with PhoneGap, certainly indicate that this is a viable solution for application development.
A larger obstacle for WP7 HTML5 applications is the IE9 browser that runs in the Mango phone. Whilst it has a pretty impressive list of HTML5 features supported, there are a couple of browser features / issues that I cannot resolve. These make it obvious to any user that this is in fact a browser application, totally spoiling the 'illusion'
user-scalable=no- currently this setting seems to be ignored. This means that the user can pinch your application, which makes it feel like a web page. UPDATE Roy, in a comment below pointed out that the viewport parameters should be comma-separated. This almost solves the issue. The user can still pinch the view, which causes it to zoom, but when the pinch finishes, the viewport returns to the original scale. Not perfect, but better than nothing!
- There doesn't seem to be any way to turn of the gray shaded rectangle that appears over links when you click them. With applications that have dynamic content, this can look pretty ridiculous, with a gray rectangle lingering on screen while the page content changes underneath it. With the Android / iPhone browsers this can be turned off in CSS via
Hopefully these limitations will be resolved. When they do, I am quite sure that HTML5 will be a viable technology for creating quality phone applications.
You can download the project sourcecode here: PhoneGapExample.zip
Regards, Colin E.