Bringing F5 (or Command+R) to Hybrid Mobile Apps

hybrid_refresh_header

The most inspiring conference talk I have ever seen was Bret Victor’s 2012 talk “Inventing on Principle”. In it, he talks about the importance of instant feedback during development. Or in his words:

Creators need an immediate connection to what they create… [i]f you make a change, or you make a decision, you need to see the effect of that immediately. There can’t be any delay.”

The web got this right. After changing code, you hit F5 (or command+r) to refresh and see its effect; there is no compile or build step to wait for. Technologies such as LiveReload take this a step further, as they publish changes on every file save. If you haven’t seen LiveReload before, checkout the gif below. In it, I make updates to a CSS file, and every time I save my changes are reflected in Chrome (top) and Firefox (bottom).

Display of LiveReload updating code in two browsers as the file is saved.

Display of LiveReload updating code in two browsers as the file is saved.

As a web developer, I have grown accustomed to this feedback cycle; therefore switching to hybrid app development was an especially jarring experience. Because hybrid apps are native apps, there is no refresh button. Every time you make a change, you must perform a native build, and push that build to a device or emulator to see its effect.

Even when this is automated, it still takes time to see results — and that time adds up quickly. Luckily a number of technologies have sprung up to bring the web’s fast feedback cycle to hybrid apps. In this article you’ll see what tools are available, and how to use them to improve your hybrid development experience.

Companion Apps

The first tool we’ll look at is the companion apps that both PhoneGap and Telerik AppBuilder offer. PhoneGap uses the term “Developer App”, and AppBuilder uses “Companion App”, but the idea behind each is the same: you install an app on your devices, publish your project to that app, and see your project rendered within the companion app.

Let’s look at the specifics behind the PhoneGap and AppBuilder offerings.

PhoneGap Developer App

To start using the PhoneGap Developer App, you need to install the PhoneGap CLI from npm:

$ npm install -g phonegap

Next, create a new PhoneGap project, and run the serve command to start a server on your development machine:

$ phonegap create hello-world
$ cd hello-world
$ phonegap serve
[phonegap] starting app server...
[phonegap] listening on 10.0.0.13:3000
[phonegap]
[phonegap] ctrl-c to stop the server

We’ll get back to this server momentarily. First you need to download the PhoneGap Developer App onto your devices. The app is available for iOS, Android, and Windows Phone in their respective app stores. After you download and install the app(s), start them and you’ll see a screen that looks like this:

developer-app

You need to input the IP address and port of the server you started on your development machine. And that’s really all there is to it.

From here, as you change your code, you’ll see the results live on your device. You can even attach multiple devices. In the gif below, I make changes to the CSS of a PhoneGap project, and see the results reflected live on my iOS, Android, and Windows Phone devices:

phonegap

Fun side note: There are five operating systems running in the image above. I am using Reflector and Droid @ Screen to mirror my iOS and Android devices on my Mac. I’m using Project My Screen to mirror my Windows Phone on a Windows 8.1 VM.

AppBuilder Companion App

The experience for Telerik AppBuilder is relatively similar. Start by installing AppBuilder from the command line with npm, and creating a project with appbuilder create.

$ npm install -g appbuilder
$ appbuilder create hello-world
$ cd hello-world

Next, you’ll need to download the AppBuilder Companion App, which is available for iOS and Android. (A Windows Phone Companion App will be available in a future release.) After that, connect your devices via USB, and run the following commands to deploy to the Companion Apps:

$ appbuilder livesync ios --companion
$ appbuilder livesync android --companion

This pushes the project to the Companion Apps on each device, but it doesn’t listen for changes to the project. For that functionality, you need to add the --watch option, as such:

$ appbuilder livesync ios --companion --watch
$ appbuilder livesync android --companion --watch

Now, any code changes you make are automatically reflected on the device. In the gif below, I make changes to an AppBuilder project, and see those changes reflected live on my iOS and Android devices.

appbuilder-companion

For those that prefer to avoid the command line, AppBuilder also offers QR code-based deployment from its in-browser, Windows Client, and Visual Studio Extension. When using these clients, you can do a three-finger press on your devices to receive code updates.

The PhoneGap Developer App and the AppBuilder Companion App are great because you get the immediate results that you’re used to from the web. However, because your app is running within another app, there are some limitations.

For one, you cannot do native remote debugging on iOS and Android, as neither allow you to debug production apps (which the PhoneGap Developer App and AppBuilder Companion App are). If you need to inspect the DOM, or view network activity, you need to resort to a tool like weinre — which limits what you can do.

Second, although PhoneGap and AppBuilder provide access to core Cordova APIs — such as the camera, accelerometer, and so forth — you cannot use custom Cordova plugins, as these plugins must be built into the app itself.

To overcome these issues you need to deploy your own native app. How do you deploy a native app and still have the ability to refresh? As it turns out, AppBuilder has the tools you need to do that.

AppBuilder LiveSync for Native Apps

The first thing you need to do is build your app and get it onto your devices. With the AppBuilder CLI, you can use the deploy command to do that:

$ appbuilder deploy android
$ appbuilder deploy ios

appbuilder deploy wp8 is not currently supported by AppBuilder, although it’s coming in a future release. You can get a Windows Phone 8 app on your device by running appbuilder build wp8, and then using the Windows Phone Application Deployment tool.

This performs Android and iOS builds of your app in the cloud, and automatically transfers those built apps onto your USB-connected Android and iOS devices. The fact that you can use one line of code to build and deploy an app is pretty awesome, but it gets even better. By default, the same LiveSync technology we used with the Companion Apps is also available in these native apps. After running deploy, all you need to do is run livesync with the --watch option. This code sets up watchers for Android and iOS.

$ appbuilder livesync android --watch
$ appbuilder livesync ios --watch

To show this in action, here I use a Cordova dialog API to show a native alert, then change the button text on my iOS, Android, and Windows Phone devices.

appbuilder-apps

appbuilder livesync wp8 is also not supported yet, but is coming soon. In this image, I have a small script that runs appbuilder cloud-sync on saves, and I’m manually doing a three-finger refresh.

If you think about what this is doing, it’s pretty cool. These dialogs aren’t the same dialogs you see from calling alert() on the web. You’re using Cordova to write JavaScript that interacts with native code (which is why you can change the dialog and button text — something the web can’t do). And because of LiveSync, you can play with a JavaScript API, and see the native code render in real time.

navigator.notification.alert is a Cordova API, so it also works in the AppBuilder Companion App and PhoneGap Developer App, but since you’re in your own app now, you can add custom Cordova plugins and interact with them. Here I use the StatusBar Cordova plugin to interact with the status bar on my iOS device.

appbuilder-status-bar

AppBuilder and Remote Debugging

Remember that the other limitation with of the Companion Apps was the inability to do remote debugging, but now that you’re dealing with your own app, that is no longer a concern. There is one caveat though: to do remote debugging on iOS, you must build your app with a Development provisioning profile — which you can do by specifying the --provision option:

$ appbuilder build ios --provision=Development

You also must create a Development provisioning profile with Apple and import it into AppBuilder using appbuilder import-provision. You can check out the AppBuilder docs for a guide on how to do that.

In the gif below, I use the Chrome Dev Tools and Safari Web Inspector to make changes to my Android and iOS Apps:

appbuilder-dev-tools

For more details on remote debugging for hybrid apps, see our Concise Guide to Remote Debugging on iOS, Android, and Windows Phone.

Wrapping Up

With the recent advancements in tooling, hybrid web development is starting to feel more like traditional web development. There’s no refresh button, but it’s now trivial to setup watchers that replicate the refresh button’s behavior. You can even use the same developer tools from the desktop that you know and love.

All of this helps to improve the feedback cycle during development. Instead of waiting for time-consuming builds to complete, you can focus on building a compelling experience for your users.

Comments