Porting an AIR Application to HTML



Check out HTMLCompass.com on your device (see requirements below).

I recently wrote a simple compass application in AIR to demonstrate the use of ANEs (AIR Native Extensions) for accessing sensor data that we don’t have API support for yet. When I heard that iOS 5 brought orientation APIs to mobile Safari, I decided to port the application from AIR to HTML in order to see what the development experience would be like.

The result is HTMLCompass.com. Using Canvas, CSS, and about 600 lines of JavaScript (about half of which are purely for drawing and rendering), I was able to build a fairly nice and functional application with the following features:

  • The UI is dynamically drawn using Canvas with no bitmap assets at all which means it scales perfectly to any size screen (you can test this by resizing your browser window; note how the direction and degree text fields change their size and location based on screen size and orientation). I had to write the scaling code myself which I probably could have mostly gotten for free had I used SVG, so that might be my next experiment.
  • Since it works on any size screen, it will also work with any orientation (although for best results, turn orientation lock on).
  • The needle animation is partially hardware accelerated which makes it very smooth on iOS devices, and pretty smooth on Android (though Android did require some extra work). By "partially hardware accelerated," I mean that there’s an animation loop that uses both JavaScript and CSS transformations for animation and easing.
  • Offline support. Once you’ve gone to HTMLCompass.com, the application is saved for offline use which means you can go back to the URL even if you don’t have an internet connection.
  • Home screen support. If you add the application to your device’s home screen, you will get offline support, a custom icon, and start-up images on iOS (the images that display briefly while your application is loading). In fact, the experience is almost indistinguishable from that of a native application.
  • Desktop testing mode. From the beginning, I architected the application so that it would be functional on the desktop as well as mobile devices. Of course, desktop machines typically don’t have a compass or a gyroscope, so you have to click on the compass dial to set north, but enabling desktop mode allowed me to do about 80% of my development on my Mac where the workflow is much smoother than the workflow between a development machine and a mobile device.

Unfortunately, HTMLCompass won’t work on all devices. Since compasses and gyroscopes are relatively new to phones and tablets, comprehensive orientation APIs aren’t widely supported by browsers yet. On iOS devices, support was just added with iOS 5, and on Android, I found I was able to reliably calculate north using the gyroscope APIs in Honeycomb (specifically Android versions 3.1 and 3.2.2). Here are all the devices I successfully tested on:

  • iPhone 4 with iOS 5.
  • iPad 2 with iOS 5.
  • Motorola Xoom with Android 3.2.2.
  • Galaxy Tab 10.1 with Android 3.1.

Below are some miscellaneous observations I jotted down during development. Let me know in the comments if you have any questions or thoughts.

  • I’m definitely not new to JavaScript programming, however after doing so much ActionScript lately, I did miss the expressiveness (strongly typed variables, function return types, etc.) of ActionScript. I also missed the compilation step from the perspective of finding bugs, however from the perspective of productivity/workflow, I didn’t miss compilation at all. In general, I think I’m happy programming in either ActionScript or JavaScript; they have different strengths and weaknesses which, in my mind, largely balance each other out.
  • I initially did the needle rotation entirely in JavaScript and found that I couldn’t get it very smooth at all. Introducing CSS transformations allowed me to offload most of the animation to the GPU which improved performance immensely. The takeaway: do as much movement/animation with CSS as you can. I’m also looking forward to having more access to hardware rendering in the future.
  • On iOS, I use the incoming orientation events as my rendering/animation loop which works really well. On Android (or at least on my Xoom), the alpha values of the DeviceOrientationEvent are too erratic, resulting in very choppy animation. In order to smooth it out, I created a specific rendering loop which allowed me to average the alpha values out over more time. The animation still isn’t as smooth on Android as it is on iOS, but it’s not bad.
  • I built most of the application while testing almost exclusively in Safari (desktop and mobile) which was a mistake. The first time I tested in Chrome and Android, the app wasn’t even close to working. It’s inconvenient to iterate in several browsers at once, but that’s probably the way to go. When I build my next HTML app, I will test in all the target browsers as I’m developing, and where I find differences, I’ll do my best to encapsulate them right then and there. Waiting until you’re "finished" only find out you’re actually only about half finished is a big disappointment. (I have to say that I was surprised by the number or browser inconsistencies I found — even across WebKit-based browsers. I’m definitely looking forward to this gap narrowing in the future.)
  • Ironically, Apple has done a lot more to enable web applications on mobile devices than Google. I expect that web application support will be more of a focus in future versions of Android, but as of right now, I find web application support to be far superior on iOS (as well as the browser itself).
  • Because of the gyroscope built into MacBooks, Chrome on Mac supports the DeviceOrientationEvent. Since MacBooks don’t have compasses, however, the z rotation cannot be tracked which means the alpha value is null.
  • I still haven’t found an HTML/JavaScript editor/IDE that I’m really happy with. Any suggestions?

I learned quite a lot about developing mobile HTML5 applications — most of it through trial and error — so I’m planning on following up this post with several tutorials and how-tos which will hopefully save others from many of the challenges I encountered.