Saturday, June 11, 2011

Present State of HTML5 in Mobile App Development

“We’re doing our next mobile product in HTML5.”
“Yeah. A lot of people do that these days. I’ve been playing with Appcelerator as well.”
“Uh.. but that’s not what I meant by HTML5.”

I’ve been having a lot of this kind of conversations lately - partly because I’m doing an HTML5 app myself. But like “AJAX” back in 2005, the term “HTML5” is never clearly defined and is quite easy to throw around without considering the actual technical benefits, the trade offs, and the implications in the operations side. If you’re working in a company managed by buzzwords of the day, then Dilbert may very well be sitting by the next cubicle - if you’re lucky.

Two Divergent Roads

When people talk about HTML5 on mobile devices, there are actually two very different things that they may be talking about.

The more intuitive, and technically simpler path is to use the web browser - either embedded to your app (e.g. PhoneGap) or, the app is supposed to be opened from a bookmark icon on your mobile phone (e.g. Financial Times for iPhone and iPad). The usual benefits of this path include being able to reuse existing web design and development talents, products are highly and trivially portable, are easy to debug and fix (e.g. via weinre), and thus, fast iteration. Trade offs are performance and features - features is less of a hassle if you use an embedding architecture like PhoneGap. Performance is the #1 problem for this path.

The not-so-intuitive way is to use the JavaScript engine to control native features directly, ignoring the web browser component on mobile devices. Performance problems in HTML5 apps are mostly caused by HTML/CSS rendering, not JavaScript execution - so this approach can and do give you massively increased performance - if used correctly. Examples of this approach include Appcelerator Titanium, Mobage/ngcore from ngmoco, Game Closure, and whatever PhobosLabs is doing.

Node.js for Client Side

Take PhobosLabs’s project as an example - what they’ve done is take WebKit’s JavaScriptCore component, interface that to OpenGL on the device’s side, and expose an HTML5 canvas API on the developer’s side. What this means is, the developer can be developing and testing his game on a desktop browser with good canvas support, and put that to his mobile device and have his game run with similarly good (and perhaps better-than-desktop) performance. This is very similar to the approach taken by Node.js - take the JavaScript engine and add your own stuff to it for your specific use case.

Appcelerator Titanium expands on that concept and exposes a whole abstraction layer of UI widgets - such that it can be applied to general applications in addition to (instead of?) games. What this means is, an app developer can create buttons from Appcelerator’s UI library in JavaScript, and Appcelerator’s internal logic will translate that to e.g. a native UIButton on iOS. The UIButton on screen will then be completely controllable within JavaScript - the developer, theoretically, won’t need to write any Objective-C.

The trade off to this kind of approach is, while you’re still coding in JavaScript, you’re saying goodbye to the layout logic and declarative style definitions given by HTML and CSS. You’re also saying goodbye to the excellent debugging tools available to normal HTML5 developers. This is a smaller problem, and thus a sensible trade off, for HTML5 gaming APIs like Mobage because canvas exposes a relatively small set of interfaces - so there are less things to go wrong in the first place. But once the interfacing layer gets big, like in Appcelerator’s case - if anything goes wrong, you’d have to go back to Objective-C (or Android API)’s level, and also take the additional complexities added by the interfacing layer into account - while debugging. A lot of the negative reviews for Appcelerator out there can be understood if you take this in mind.

Back to the Browser

The first problem of doing a full-stack HTML5 mobile app is that it’s slow. The second problem is that the tool chains (e.g. broken persistent nav bars in jQuery Mobile, iOS’s innerHTML bug I discussed earlier) out there are still very buggy - which either means you need to reduce your features to avoid the bugs or you spend some time to work around the bugs. Features is only really the third problem - you can get around that with a plugin architecture like PhoneGap.

If you did some experiments yourself with one or two UIWebViews in an iOS app, plus a bit of your own JavaScript - no non-essential libraries added - you’ll find that it’s quite feasible to make a fast, full-stack HTML5 app... With no features. The PhoneGap iOS project template takes only 1 to 2 seconds to launch on an iPhone 3GS - a relatively old phone. What that tells you is, as a baseline, full-stack HTML5 apps can be very fast. So, if you find out your HTML5 app is hanging 10-15 seconds for some operations, or the app is taking 15 seconds to launch - then it’s almost always some JavaScript or UI library’s fault.

Two UI Libraries

What a mobile full-stack HTML5 app developer needs is usually two things: one, a bridging layer between the native platform and the web view; two, a mobile UI library. PhoneGap is pretty much the default choice as the bridging layer these days - it allows you to do things like calling out the camera, accessing the address book, reading and writing files, from JavaScript. The two most popular UI libraries are jQuery Mobile and Sencha Touch.

jQuery Mobile is a project founded late last year so it’s relatively new. It is quite obviously immature to anyone having actually tested it - persistent navigation bars are broken, page switching is noticeably slower than native, no way to incrementally add to lists without refreshing the whole page, high CPU usage when tested on desktop platforms (as of alpha 4), etc. I chose it for my project for its relative simplicity (i.e. hackability), the MIT license, and because it’s based on jQuery - every respectable web developer knows jQuery so it’s easy to train someone in jQuery Mobile.

Sencha Touch is, purportedly, much more mature and is faster. I have an instinctive abhorrence towards things that comes with a higher complexity, because I always have a feeling that there are gonna be a lot of features that I wouldn’t use and end up as dead weights pulling down the overall performance. I may be wrong though - the top featured mobile app on PhoneGap’s apps page is IGN Dominate - it’s extremely fast and it’s based on Sencha Touch - although I’m sure they’ve put in a lot of their own optimizations to do that.

Debugging and Making Changes

But the upside of doing full-stack mobile HTML5 - which a lot of people misses - is that it’s easy to debug and make changes. Any developer who’s worked on any non-trivial project would tell you, debugging and maintaining the project can easily take up 80% of the time, if not more. What this means is, when you see a certain tool chain claiming you can build, e.g. a chat app, in 15 minutes - it’s really telling you it has compressed 20% of your trouble into 15 minutes - the remaining 80% may have been made 3x worse.

This was a tough problem for mobile HTML5 apps because console.log() in a UIWebView normally logs to nowhere. So if anything goes wrong in JavaScript, you would need alert() or you wouldn’t be able to see that. PhoneGap improved this a bit by patching in a console.log() that logs to XCode’s console. But that’s still not enough.

The best solution right now is weinre. It is buggy and slow but it works - with that you can literally debug your mobile app’s UI from Web Inspector on your computer. It is based off WebKit’s Web Inspector with its debugger back end taken out and replaced with a remote back end. I’ve done some investigations into Web Inspector’s code myself two or three weekends ago and found that it’s not really that hard to turn it into a remote debugger. weinre’s development may speed up in the coming months or someone may make a better project replacing it - we’ll see.

This will be the actual big thing in mobile app development for the coming years, because it solves tons of problems in the 80% part of the app developer’s workload. Want to change your UI design in Objective-C? Edit, recompile, run - repeat until you get satisfactory results. This can easily take a whole day if the recompile step is long. Doing that same thing with HTML5? Edit a few CSS attributes in weinre and experiment away - you don’t even need to shut down the app. Yes you can debug an HTML5 mobile app, to some extent, by running it in a desktop browser. But believe me - your app will have a bunch of bugs that happens only on the mobile device, so weinre is absolutely needed.

Unfortunately, people usually tout their toolkits and their features and seldom glorify useful debuggers, so I guess it won’t get talked a lot even though it’ll actually be the thing that mobile HTML5 developers use the most.

The Present State

I hate writing conclusions, but this is a really long blog post, which even myself will need a few points to remind myself - when I read my own posts later.
  1. Two ways to do HTML5 apps on mobile, full-stack or only using the JavaScript engine.
  2. The JS engine approach makes sense for making games. I have reservations for implementing a full UI toolkit on that due to the complexities involved in the interfacing layer - but, we’ll see.
  3. Full-stack HTML5 mobile app is slow and buggy, but can be mitigated with custom optimizations. Not many people have managed to do that but it's possible.
  4. The real benefit of doing HTML5 mobile apps is the possibility of debugging and changing it online. Native app developers will have a hard time matching that kind of development speed advantage - once the team has problem #3 resolved.
  5. Oh yes, porting is easy as well. But I assume everyone gets that automatically.

Thursday, June 2, 2011

How to make the Push Notification prompt reappear during iOS app development

If you're developing an iOS application and your application is using push notifications, chance is, you'd like to be able to test the push notification registration step during debugging.

Problem: the push notification dialog only appears once for your debug application. It doesn't matter that you remove the app and reinstalled it - it won't appear again. This kind of behavior is dangerous for developers because it means it's impossible for you to test the push notification registration step reliably - it might have worked last week but stopped working this week, and you just wouldn't know.

Apple has a technical note dealing with this behavior. What an app developer can do in this case is to uninstall the app and adjust his development phone's clock to 1 day later. If he reinstalls the app after this, the push notification dialog will be allowed to appear again.

But... there's always a better way. It requires jailbreaking your iPhone but who doesn't? :)