Building hybrid mobile apps

Tags: windows phone, hybrid, apps, mobile, maintenance, phonegap, xamarin, web standards

Please note: There will be code and fun action below, but we need some background first:

Do we need native apps?

Norwegian public service media provider NRK recently stated that they will be jumping on the web standards train and will not focus on creating native mobile apps in the future. The announcement from NRK is aligned with a recent statement from its Swedish counterpart SVT.

That's not exactly earth shattering news. With the latest moves from Microsoft regarding developing for Windows 8 and Adobe announcing their plans and even Spotify's new app platform, it's obvious that there's a strong movement towards using web standards instead of plugins and native stuff. It's obviously good news, too. As much as you like {insert your platform here}, we can't put ourselves in the maintenance nightmare it means to support native apps for all major operating systems and devices.

But let's not give up apps just yet. People like apps. I like apps. My daughter likes apps so much she's packed the iPad full of hundreds of them, rendering the device almost unusable, unless you really like dressing up princesses.

And apps can definitely provide value for both users and publishers. The YouTube app for Windows Phone is popular to hate since all it does is to open YouTube in the browser. Personally, I'm not sure why that would be a problem as long as the site it opens is responsively designed and does the job, and in this case I think it does. But whatever.

OK, so now there's at least three reasons to create native apps:

  1. Users like apps. They've gotten used to them and they expect them to look and feel native and they don't want to feel that the app is just an internet bookmark.
  2. Companies like to use apps in their marketing. It enables them to push their brand and improve customer experience.
  3. The device sensors, camera, microphone, contacts etc. are not accessible in a regular HTML5 context. If the functionality in an application requires or can be improved by using information from the device, then we have to go native. It's mostly a security issue, wouldn't you agree? You don't want a regular web page to access stuff on your phone just like that.

Hybrid apps

What triggered this blog post was an entry in the advent calendar for developers on MSDN Up North (Norwegian) about creating hybrid apps using the browser control in a native app to enable certain functionality to be used and reused cross platform. I thought I'd highlight the fact that going hybrid does not mean you have to lose anything. As an example of that, let's look at creating a hybrid app where input from the device is used to control the web application.

First, we need something to work on. Perhaps you've seen this example of web standards bouncing balls subject to gravity. The guy who made that is doing a bunch of nerdy fun stuff, so check out the blog too. I want to make it perfectly clear that I stole his code, changed it a little bit and now I'm using it here for demonstration purposes. I deserve no credit for it, and I'd also like to point out that the code is based on the Box2D JS physics engine.

Where were we? Right, I stole that code and modified it a bit. Most notably I made the balls considerably more visually pleasing. Here it is. If you move the browser window around, you'll se the balls reacting to your actions, just as in the original code.

Now, to finally get to the point: By adding a javascript function, I can easily feed the web application with input from the host, for example device sensor information such as the accelerometer data:

    function setAccelerometerDelta(x, y) {
        accelerometerDeltaX = parseInt(x);
        accelerometerDeltaY = parseInt(y);
    }

And as usual when developing for Windows Phone, it's stoopid easy to get my phone app to do what I wan't, which in this case is to feed the web app in the browser control with data:

                    var accelerometer = new Accelerometer();
                    accelerometer.TimeBetweenUpdates = TimeSpan.FromMilliseconds(500);
                    accelerometer.CurrentValueChanged += (sender, ea) =>
                    {
                        var x = Convert.ToInt32(ea.SensorReading.Acceleration.X * 500);
                        var y = Convert.ToInt32(ea.SensorReading.Acceleration.Y * 500);
                        Dispatcher.BeginInvoke(() =>
                        {
                            browserControl.InvokeScript("setAccelerometerDelta", new string[] { x.ToString(), y.ToString() });
                        });
                    };
                    accelerometer.Start();

OK, quick recap: We've built a web application which can be viewed and used on any device (or rather, in any modern browser). We added a javascript hook into the application so that we can feed it with data. Finally, we created a native Windows Phone app which contains pretty much nothing more than the application title (i.e. our own branding) and an embedded web browser control. (Needless to say, it would be easy to create nearly maintenance free native apps for any platform using the same techniques.) The end result is a maintainable, web standards compliant app which preserves the native look and feel on all platforms. Let's check out a video showing the app in the emulator and feeding it with some prerecorded accelerometer data:

(Download video in MP4, WMV, Theora OGV or WebM (vp8) if you'd like.)

A final note: Another way to create native apps for several platforms while still avoiding maintenance hell would be to use PhoneGap. We'll talk about that some other time. In addition, I know a lot of people like Xamarin for cross platform app development. I've never tried it so I guess it's good stuff (and I'm not bashing it), but then you still have to maintain a web app separately.

Get the xap here and download the code (MainPage.xaml and code-behind) here.

A helping hand

Oh, and one more thing. There's a massive gotcha you need to be aware of when going hybrid on Windows Phone. If you set the WebBrowser.Source property before you set the WebBrowser.IsScriptEnabled property, then it won't work. So DON'T DO THIS:

        <!-- If you cut and paste this code into your app, you're asking for trouble -->
        <phone:WebBrowser Source="https://labs.signicat.com/msdnjul" IsScriptEnabled="True" />
        <!-- Don't do it, bro. -->

If you do, then maybe you won't see a thing, maybe you'll get strange errors and maybe you'll get the informative message that "An unknown error has occurred. Error: 80020006." when trying to call your javascript functions. In retrospect it's easy to understand why it happens, but it's really annoying when you're cluelessly experiencing it for the first time.

There's also another gotcha which has to do with caching of web pages visited by the web browser. If nothing you do seems to have any effect, chances are you're suffering from cachingitus. If you do, simply append a nonsense parameter to the source URL and that's it (see MainPage.xaml.cs for an example).

3 Comments

  • Elliot said

    I want to start building hybrid HTML5 mobile apps; build the core functionalities via HTML5, then wrap this with a native layer for iOs, Android, BB.

  • Kris said

    great blog post - although a bit basic. As far as I have understood, hybrid apps are stuck with using only one browser control (due to memory constraints). Playing around with balls sure seems like fun (no pun intended), but making full featured apps using features WP7 is famous for (i.e. panoramic views) becomes a nightmare, if not completely impossible. However, I have heard some rumors flying around that Microsoft are fixing the memory issue in a future release (probably WP8), so hybrid development is truly a good alternative to native coding.

  • maralm said

    Yeah, I don't know, Kris. I kind of changed my mind since I wrote that blog post. Performance is the #1 feature of any app, and hybrid just doesn't cut it. Yet. We'll see.

Add a Comment