I am embarking on a new PhoneGap project that will have to run on many platforms… iOS, Android, BlackBerry, and Windows Phone. This will actually be my first foray into modern Window Phone development. (I did some experimental work with the Windows Mobile platform many years ago, but a lot has changed since then.)
One of the caveats with Windows Phone development is that it has to be done from Windows, just like iOS development has to be done from OS X (normally, although some cross platform technologies enable development via other OS/platforms).
Of course, I did not want to give up OS X, so here’s how I have my environment setup… I have a virtual machine running Windows 7, in which I can run the Visual Studio development tools. I am able to deploy to a physical Windows Phone device using the USB connection.
Windows Phone Development with PhoneGap, on OS X
However, with this configuration you will NOT be able to use the Window Phone emulator, which is a part of the Windows Phone development SDK. The Windows Phone emulator is not supported inside of a VMWare virtual machine because the emulated operating system environment does not meet the minimum requirements (specifically the graphics drivers are not WDDM 1.1 compliant). If you try to use the phone emulator inside the virtual machine, you will just get a blank screen. I spent a few hours trying to find a workaround, to no avail. You can use the Windows Phone emulator if you boot your Mac into Windows using Bootcamp, but I wanted to keep OS X as my primary operating system.
Being able to deploy directly to a device works for me, and is (in my opinion) better than being able to deploy to an emulator, thus I am happy with this workflow. I have heard that other people have had trouble deploying to Windows Phone devices through a VMWare emulator, so here are the details on how I have my environment setup and a few “getting started” links for PhoneGap development on Windows Phone:
Note: All of the project setup work will be done through the Windows virtual machine instance.
There is a detailed “Getting Started” guide for PhoneGap and Windows Phone available at http://phonegap.com/start#wp. This will provide you with all the information that you need to get started with PhoneGap applications for Windows Phone.
As a part of the setup process, you will need to download and install the Windows Phone SDK from http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=27570. This will include a copy of Visual Studio Express 2010 for Windows Phone, as well as additional tools for Windows Phone development.
To be able to deploy an application to a physical Windows Phone device, you will need to register as a Windows Phone developer on MSDN App Hub at http://create.msdn.com/en-US/home/membership. This is a very similar model to Apple’s iOS developer program. There is a $99 annual fee, and once you are registered, you will be able to debug on devices and distribute applications via the Windows Phone Marketplace. However, debug provisioning is much easier. Instead of signing each application with a debug certificate, you just have to register your device as a development device. Once the device is registered, you will be able to deploy to it without any other special steps; this is very similar to the provisioning model for Nook devices.
When linking my AppHub account to my Windows Live account (a required step), I ran into a vague error message “There’s a temporary problem with the service. Please try again. If you continue to get this error message, try again later.” After scouring the web for this error message, I found a few threads that mentioned this error is likely the result of an incomplete profile for your Windows Live account. Sure enough, I went into live.com and filled out my profile (including contact information), and this error went away.
My Setup
Below are the specifics for my setup; I did not have any issues connecting a Windows Phone device with this configuration.
To deploy an application to a Windows Phone device, you just have to use the Windows Phone Developer Registration Tool, and walk through a few simple steps to associate your phone with your developer account. This tool is installed when you install the Windows Phone SDK. You can read full details about debugging Windows Phone applications on MSDN.
As I mentioned above, I have heard that others have encountered problems when trying to deploy applications to Windows Phone devices via a virtual machine on OSX, but I have not had any problems with this configuration.
I was inspired to write this post by several recent conversations. I was in a debate about whether with the Flex/Flash platform you could easily repurpose content to the desktop using Adobe AIR (and vice-versa), but that you couldn’t easily do that with PhoneGap applications. (My stance was that yes, you could repurpose content.)
I wanted to make sure that people were aware that you can repurpose your content, and here’s an example of how.
A while back, I wrote a sample PhoneGap application that allows you to browse information from the 2010 US Census. You can read more about this application and download the source code here. This application supports lots of platforms… iOS, Android, BlackBerry, and web (everything except IE because I was targetting WebKit browsers).
While this application is a mobile app wrapped in the PhoneGap container, I actually didn’t use any PhoneGap-specific libraries, so it was very easy to repurpose as a desktop application. I created an AIR version of this application, which you can download at:
I had to use my Android 2.x branch of the US Census Browser code because the WebKit instance inside of AIR doesn’t support SVG. I also changed the container scrolling to use normal CSS “overflow: auto” instead of using iScroll for touch-based scrolling. There were a few other one-off CSS changes to tweak the layout in the AIR web container, but otherwise the code is identical.
You just need to create an AIR application XML file and point it to your HTML content, and then package it using ADT.
If you were using PhoneGap APIs, you would have to migrate your code to take advantage of AIR APIs, but all other HTML/CSS/JS could be reused with minimal changes.
Even though I used AIR for this example, AIR isn’t the only game in town for HTML-based desktop applications… There’s an open source project called MacGap, you can use HTA for Windows, and it’s not hard to write a HTML/Web View wrapper for any platform. It’s even been reported that you are going to be able to write apps for Windows 8 purely using HTML & JS, and you would be able to repurpose your code for this as well.
You can check out the AIR version of the US Census Browser at:
While looking at the analytics for my blog, I’ve recently started to see a lot of search phrases similar to “what is phonegap?”, “how does a phonegap app look?”, “how to get started in phonegap?”, among many, many others. In this post, I hope to shed some light on some basic questions to help you understand and start working with PhoneGap.
In case you don’t feel like reading the whole thing, here are quicklinks to each question:
PhoneGap is an application framework that enables you to build natively installed applications using HTML and JavaScript. The easiest way to think of PhoneGap is a web view container that is 100% width and 100% height, with a JavaScript programming interface that allows you to access underlying operating system features. You build your user interface using traditional web development skills (HTML, CSS, & JavaScript), and use the PhoneGap container to deploy to different application ecosystems and devices. When packaged for deployment, the PhoneGap application is a binary distributable file that can be distributed by the “normal” application marketplaces (iTunes, Google App Market, Amazon Market, etc…).
PhoneGap can be used to build applications that target multiple platforms, including Apple iOS, Google Android, Windows Phone, BlackBerry, HP WebOS, Symbian, and Bada.
Since the UI rendering engine is the mobile device’s web browser, PhoneGap applications can literally look like anything. You can use standard HTML & CSS to make it look like a normal web page, you can use a UI framework like jQuery UI, Kendo UI, Sencha, Twitter Bootstrap, or Skeleton (or any other HTML/CSS/JS user interface framework). You can also use CSS styles/themes to make your web content look like native apps, such as iUI to mimic iOS or Android, or bbUI to mimic BlackBerry.
PhoneGap applications can have static UIs based on normal HTML, or can have dynamic & interactive experiences developed using JavaScript. It depends upon the specific application, user experience design, target audience, and use cases to dictate how a PhoneGap application will appear.
PhoneGap applications can use pinch/zoom gestures to zoom in & out, or you can lock the viewport scale using the viewport metadata tag. You can have the page scroll using normal browser behaviors, or you can use a library like iScroll to enable touch-based scrolling of specific container elements.
There really are lots of ways to create a user interface with HTML, CSS & JavaScript, so there really isn’t any “typical” look. If you do not apply any CSS styles at all, then all user interface elements will use the operating system/browser default for that specific platform. This includes buttons, links, and color/highlight states. This behaves in the exact same manner as the operating system’s default web browser.
How do I get started in PhoneGap?
Getting started in PhoneGap is easy. For 90% of a PhoneGap application, all you need is a text editor. PhoneGap also integrates with device-specific development environments very easily. You can view “getting started” guides for all application platforms at the links below:
When developing PhoneGap applications, just keep in mind that you are running code inside of a web browser instance. You develop your applications using HTML and JavaScript, not native code, so you don’t need anything special. In fact, I personally do most of my development on the desktop using an HTML editor and the Chrome browser. When I need device-specific functionality, or I need to test on a device, then I switch over the the device-specific environments.
How do you debug PhoneGap applications?
Debugging PhoneGap applications can sometimes be the trickiest part of development. If you are testing on a physical device, you can’t always get access to JavaScript exceptions when they happen. There are a few strategies for debugging PhoneGap applications.
Develop as much as possible on the desktop browser
Since PhoneGap applications are written with HTML, CSS, and JavaScript, you can develop most of them using any HTML editor and debug them within a desktop web browser. The latest versions of all major web browsers (including Chrome, IE, Firefox, Opera and Safari) provide rich debugging features. In the developer tools for the browsers, you can inspect HTML DOM elements, inspect CSS styles, set breakpoints in JavaScript, and introspect into memory & JavaScript variables. You can learn more about the desktop browser development tools at:
Once you build the main aspects of your application using desktop tools, you can switch over to a device-specific environment to add device-specific behavior and integrate with PhoneGap APIs.
It is imperative that you test your applications on actual devices! Actual devices will have different runtime performance than desktop browsers and simulators, and may unearth different bugs/issues including API differences and different UX scenarios.
Debug With debug.phonegap.com
PhoneGap provides a hosted service that allows you to perform remote, on-device debugging through debug.phonegap.com. This uses the Weinre (Web Inspector Remote) debugging tool to allow you to remotely inspect the DOM, resource loading, network usage, timeline, and console output. If you have used any of the developer tools listed above, this will look very familiar. You will not be able to set breakpoints on the mobile device, but it is certainly better than nothing at all.
Remote Web Inspector Through iOS 5
There is a little known undocumented API introduced in iOS5 that allows you to perform remote debugging through the iOS5 Simulator. You just need to enable remote debugging
Then launch the application in the desktop iOS Simulator. Once the app is running, open a local Safari instance to: http://localhost:9999/. This will launch the remote debugger, complete with breakpoints and script introspection.
You generally architect PhoneGap applications the same way that you create mobile web experiences. The difference is that the initial HTML assets are available locally, instead of on a remote server. The PhoneGap application loads the initial HTML, which can then request resources from a server, or from the local environment. Since PhoneGap is based in a browser, it behaves exactly as you would expect a web browser to behave. You can load multiple pages; however, keep in mind that once you load/unload a page you may lose any data that is stored in memory via JavaScript. PhoneGap also supports the single-page web experience model. I strongly suggest using the single-page architecture approach.
Single-Page Architecture
A single-page architecture refers to the practice of having a single HTML page that dynamically updates based upon data and/or user input. You can think of this as closer to a true client/server architecture where there is a client application (written with HTML & JS) and a separate server structure for serving data. All client-side application logic resides in JavaScript. The client application may request data and update its views without reloading the current web page.
Using a Single-Page architecture allows you to maintain data in-memory, in JavaScript, which allows you to have a stateful, yet dynamic user interface. You can read more about single-page architectures at: http://en.wikipedia.org/wiki/Single-page_application
How do you get PhoneGap apps on devices and into application ecosystems?
PhoneGap applications can be deployed using the same guidelines for native applications for each given platform. You must follow the rules of each hardware platform/vendor, and there is no way to get around that. You can compile the executables for each platform yourself using each platform’s specific build process, or you can use build.phonegap.com to compile them for you. build.phonegap.com is a hosted service that will compile platform-specific application distributable files for you. In either case, the output of the build process is a platform-specific binary file: IPA for iOS, APK for Android, etc… You can read more about distributing to various application ecosystems, and each system’s signing/certificate requirements at:
The most fundamental differences between PhoneGap and AIR is that you develop AIR applications using tools rooted in the Flash Platform (Flex, Flash, ActionScript, MXML), and you develop PhoneGap applications using HTML, CSS, & JavaScript. AIR applications use the AIR runtime, which allows you to have a single code base, with the exact same expected behavior across all supported platforms. PhoneGap applications run inside of the native web browser component for each supported platform. For this reason, a PhoneGap codebase may behave slightly different between separate platforms, and you will need to account for this during your development efforts.
Air applications can be built for iOS, Android, BlackBerry Playbook, and the desktop (mac and windows), with future support for Windows Metro (Windows 8 mobile interface). You can read more about AIR’s supported platforms at: http://www.adobe.com/products/air/tech-specs.html
PhoneGap applications can be built for iOS, Android, BlackBerry, Windows Phone 7, HP WebOS, Symbian, and Samsung Bada. You can read more about PhoneGap’s supported platforms at: http://phonegap.com/about/features
ActionScript has strongly-typed objects and supports classical inheritance programming models. AIR applications can also be built using the Flex framework, which allows you to rapidly build enterprise-class applications. Components in AIR applications are logical objects that have behaviors, properties, and a graphics context.
JavaScript-based applications support prototypal inheritance, and have numerous open-source frameworks/tools that can be used. HTML/JS applications are all visualized through HTML DOM elements. HTML interfaces can be created through basic string concatenation or JavaScript templating, but in the end you are really just creating DOM elements that have properties and styles.
There are some fundamental difference in the syntax of building these applications, however the basic concepts of interactive design and interactive development are identical. Both platforms have valid strengths, which I could write about ad nauseum… I’ll save that for another post.
Here’s a silly/fun app I built ‘after hours’ using PhoneGap. It is a children’s drawing app built entirely with the HTML5 Canvas element, using a PhoneGap wrapper, targeting the iPad. I was inspired by magnetic drawing toys that I often use when drawing with my daughter, and this was really, really easy and a lot of fun to build. I used the exact HTML5 Canvas brush image/sketching technique that I have previously demonstrated – the only change is that I added the new UI style elements and added support for multiple touch points. Otherwise, the drawing logic is identical.
Lil’ Doodle is a great new iPad application for entertaining both you and your children! If you know how to use a children’s magnetic drawing toy, then you know how to use Lil’ Doodle. Pick a “pen” shape, and start doodling. Your imagination is your only limit. If you want to erase everything and start over, just use the slider at the bottom. Doodle and have fun!
Using the HTML5 Canvas inside of PhoneGap has great performance on iOS, and building the application using purely HTML, CSS, and JavaScript made it incredibly simple. After I wrote the core drawing engine for a previous blog post, I whipped up the UI in one evening, and then started user testing with my little beta tester. She found some issues that I had overlooked, and a few days later I submitted it to the app store.
…and yes, she really does play with it:
The app is currently available for iPad devices on iTunes – I’m about to start researching/testing performance on other platforms, so maybe soon it will be out in other ecosystems… we’ll see. You can get it now at:
Back in the summer, I was lucky enough to get my hands on some early builds of Stage3D for mobile. I built some simple examples, including basic geometric shapes and simple 3D bubble charts inside of mobile Flex/AIR applications. I have been asked numerous times for the source code, and I’ve finally given in, and am sharing some source code.
I am not posting the full mobile application source code, since Stage3D for mobile is not yet available. However, I have ported the 3D bubble chart example to run in a Flex application targeting the desktop (Flash Player 11). The bubble chart example extends the concepts explored in the basic geometric shapes example.
Before you say “shoot, he didn’t give us the mobile code”, let me explain… When I ported the code from the mobile project to the desktop Flex project, all I changed was code specific to the mobile Flex framework. I changed <s:ViewNavigatorapplication> to <s:Application> and the corresponding architecture changes that were required, and I changed the list item renderers to Spark item renderers based on <s:Group> instead of mobile item renderers. In the mobile item renderers, all my drawing logic was done using the ActionScript drawing API. For simplicity in the port, I just used <s:Rect> to add the colored regions in the desktop variant.
That is all I changed!
The stage3D code between the desktop and mobile implementations is identical. You can see the desktop port in action in the video below:
The source code was intended to be exploratory at best… I was simply experimenting with hardware accelerated content, and how it can be used within your applications. There is one big “gotcha” that you will have to watch out for if you want Stage3D content within a Flex application… Stage3D content shows up behind Flex content on the display list. By default, Flex apps have a background color, and they will hide the Stage3D content. If you want to display any Stage3D content within a Flex application (regardless of web, desktop AIR, or mobile), you must set the background alpha of the Flex application to zero (0). Otherwise you will pull out some hair trying to figure out why it doesn’t show up.
The source code for the web/Flex port of this example is available at:
Recently I’ve been spending a fair amount of time working on HTML-based applications – both mobile web and mobile applications using PhoneGap. Regardless of whether you are targeting a mobile web browser or a mobile app using the PhoneGap container, you are still targeting a mobile web browser instance. If you haven’t noticed, mobile web browsers can often have peculiarities with how content is rendered, or how you interact with that content. This happens regardless of platform – iOS, Android, BlackBerry, etc… All have quirks. Here are a few tips that I have found useful for improving overall interaction and mobile HTML experiences.
Disclaimer: I’ve been targeting iOS and Android primarily, with BlackBerry support on some applications. I don’t have a Windows Phone device to test with, so I can’t comment on support for the Windows platform.
AutoCorrect and AutoCapitalize
First things first: autocorrect and autocapitalize on Apple’s iOS can sometimes drive you to the brink of insanity. This is especially the case if you have a text input where you are typing in a username, and it keeps “correcting” it for you (next thing you know, you are locked out of the app). You can disable these features in web experiences by setting the “autocorrect” and “autocapitalize” attributes of an <input> instance.
Have you ever experienced an an app or web site on a mobile device where you have to enter numeric data, and the default keyboard pops up. Before entering any text, you have you switch to the numeric input. Repeat that for 100 form inputs, and try to tell me that you aren’t frustrated… Luckily, you can manage the keyboard in mobile HTML experiences very easily using HTML5 Form elements.
One way to easily determine that an application is really HTML is that everything on the UI is selectable and can be copied/pasted – Every single piece of text, every image, every link, etc… Not only is this annoying in some scenarios (and very useful in others), but there may be instances where you explicitly don’t want the user to be able to easily copy/paste content. You can disable user selection by applying the following CSS styles. Note: This works on iOS, and partially works on BlackBerry/QNX for the PlayBook. It did not work on Android in my testing.
The -webkit-touch-callout css rule disables the callout, and the -webkit-user-select rule disables the ability to select content within an element. More details on webkit css rules from the Mobile Safari CSS Reference. More detail about disabling copy/paste on iOS is available at StackOverflow.com.
Disable Zoom
If you want your content to feel like an app instead of a web page, then I strongly suggest that you disable gestures for pinch/zoom and panning for all use cases where pinch/zoom is not required. The easiest way to do this is to set the viewport size to device-width and and disable user scaling through the HTML metadata tag.
This technique works on both Android and iOS devices, and I assume other platforms. However, I don’t have the devices to test all of them.
Touch Based Scrolling
Touch-based scrolling is critical to having an application that feels native. I dont mean that the whole page should be able to scroll… Your browser will be able to take care of that alone. Instead I mean that you should be able to scroll individual elements so that they mimic clipped views, lists, or large blocks of content. You should be able to scroll content where it is, and not have to scroll an entire page to reveal something in only one area of the screen. You should minimize scrolling when it may cause poor UX scenarios. This is especially the case in tablet-based applications which have a larger UI than phone-based applications.
“Click” events on HTML elements on mobile devices generally have a delay that is caused by the operating system logic used to capture gestural input based on touch events. Depending on the device, this could be 300-500 MS. While this doesn’t sound like much, it is very noticeable. The workaround is to use touch events instead of mouse events: touchStart, touchMove, touchEnd. You can learn more about touch events from html5rocks.com. There’s also a great script from cubiq that adds touch events for you to optimize the experience for onClick event handlers on iOS devices.
Add To Home Screen
If you want your web app to fee like a real app and take up the full screen without using PhoneGap as an application container, then you can always add it to the device’s home screen. Although this can only be done manually through the mobile browser, there are a few open source scripts to guide the user through this processs: cubiq.org or mobile-bookmark-bubble should get you started.
Use Hardware Acceleration
Animations will generally be smoother and faster if your content is hardware accelerated (and the device supports hardware acceleration). You can make html elements hardware accelerated just by adding the translate3d(x,y,z) css style to the element (be sure to set all three x, y, and z attributes otherwise hardware acceleration may not be applied. If you don’t want any translation changes, you can use the translate3d CSS rule with all zero values: translate3d(0,0,0).
In your development/testing, you can even visualize which content is hardware accelerated in both desktop and mobile Safari using the technique shown at http://mir.aculo.us/.
Make You Apps Fast
Last, but certainly not least, make your apps fast. Follow best practices, and be efficient in code execution and the loading of assets (both local and remote). Here are a few links to get you going in the right direction:
I hope these get you moving in the right direction! If you have read this, and aren’t sure what it all means, check out the Adobe Developer Connection to ramp up on HTML5, or theexpressiveweb.com to see what HTML5 & CSS3 can do.
Did you know that apps built on top of iOS can have a multi-screen workflow? For example in Keynote, you can have an external screen show a presentation while you control it on your iOS device. In the Jimi Hendrix app, you can view the audio player on an external screen, and in Real Racing HD, you can view the game on an external screen while the iOS device becomes your controller. (among others)
Real Racing HD
This is all made possible by the UIWindow and UIScreen APIs in iOS. Even better, on the iPad 2 and iPhone 4Gs, this can be done wirelessly using Airplay with an Apple TV device. On other iOS devices, you can have a second screen using a VGA output.
One of the benefits of using a cross platform solution like PhoneGap or Flex/Air is that you can build apps with an easier to use/more familiar paradigm. However, cross platform runtimes don’t always offer access to every API feature that native development enables.
Out of the box, PhoneGap apps are confined to a single screen. You can use screen mirroring to mirror content on an external screen, but you can’t have a second screen experience. It’s a good thing you can write native plugins/extensions to enable native functionality within your applications.
ExternalScreen Native Plugin For PhoneGap
I recently did exactly that… I created a PhoneGap native plugin that enables second screen capability for PhoneGap applications. The plugin listens for external screen connection notifications, and if an additional screen is available, it creates a new UIWebView for HTML-based content in the external screen – complete with functions for injecting HTML, JavaScript, or URL locations.
Why?
You might be wondering “Why?” you would want this plugin within PhoneGap… this plugin enables the multi-screen experiences described in the apps mentioned above. They extend the interactions and capabilities of the mobile hardware. With this PhoneGap native plugin, you can create rich multi-screen experiences with the ease of HTML and JavaScript. Here are a few ideas of the types of apps that you can build with this approach (scroll down for source code):
Fleet Manager
Let’s first consider a simple Fleet Manager application which allows you monitor vehicles in a mobile app. This is a similar concept which I’ve used in previous examples. The basic functionality allows you to see information on the tablet regarding your fleet. What if this app connected to a larger screen and was able to display information about your vehicles for everyone to see? Watch the video below to see this in real life.
This application example is powered by Google Maps, and all of the data is randomly generated on the client.
Law Enforcement
Let’s next consider a mobile law enforcement application application which gives you details to aid in investigations and apprehension of criminals. Let’s pretend that you are a detective who is searching for a fugitive, and you walk into a crowded bar near the last known location of that fugitive. You connect to the bar’s Apple TV on their big screen TV, pull up images and videos of the suspect, then say “Have you seen this person?”. This could be incredibly powerful. Check out the video below to see a prototype in real life.
This law enforcement demo scenario is a basic application powered by the FBI’s most wanted RSS data feeds.
Tip Of The Iceberg
There are lots of use cases where a second screen experience could be beneficial and create a superior product or application. Using PhoneGap allows you to build those apps faster & with the ease of HTML and JavaScript, using traditional web development paradigms.
The PhoneGap native plugin is written in Objective C, with a JavaScript interface to integrate with the client application. PhoneGap plugins are actually very easy to develop. Basically, you have to write the native code class, write a corresponding JS interface, and add a mapping in your PhoneGap.plist file to expose the new functionality through PhoneGap. There is a great reference on the PhoneGap wiki for native plugins which includes architecture & structure, as well as platform specific authoring and installation of those plugins. Here are quick links to the iOS-specific native plugin content authoring and installation.
The ExternalScreen plugin creates a UIWebView for the the external screen, and exposes methods for interacting with the UIWebView. Note: This is just a normal UIWebView, it does not have support for all PhoneGap libraries… just a standard HTML container.
You can read up on multi-screen programming at iOS from these useful tutorials:
The header file shows the method signatures for the native functionality. The corresponding PGExternalScreen.m contains all of the actual code to make it all work. Note: If you are using ARC (Automatic Reference Counting), you will need to remove the retain/release calls in PGExternalScreen.m.
The PGExternalScreen.js file defines the native methods that are exposed through PhoneGap. You invoke the function, and can add success/fail callback function references.
You can call any of these functions from within your PhoneGap application’s JavaScript just by referencing the exposed method on the PGExternalScreen instance.
// check if an external screen is available
PGExternalScreen.checkExternalScreenAvailable( resultHandler, errorHandler );
//load a local HTML resource
PGExternalScreen.loadHTMLResource( 'secondary.html', resultHandler, errorHandler );
//load a remote HTML resource (requires the URL to be white-listed in PhoneGap)
PGExternalScreen.loadHTMLResource( 'http://www.tricedesigns.com', resultHandler, errorHandler );
//load a HTML string
PGExternalScreen.loadHTML('</pre>
<h1>HTML</h1>
<pre>this is html content', resultHandler, errorHandler );
//invoke a JavaScript (passed as a string)
PGExternalScreen.invokeJavaScript('document.write(\'hello world\')', resultHandler, errorHandler );
The full code for the ExternalScreen PhoneGap native plugin, as well as both client applications and a basic usage example is available on github at:
After spending some time playing around sketching with the HTML5 canvas element earlier this week, I figured “why not add some ‘enterprise’ concepts to this example?”… Next thing you know we’ve got a multi-device shared sketching/collaboration experience.
To keep things straightforward, I chose to demonstrate the near-realtime collaboration using a short-interval HTTP poll. HTTP polling is probably the simplest form of near-realtime data in web applications, however you may experience lag when compared to a socket connection of equivalent functionality. I’ll discuss the various realtime data options you have in Flex/Flash and HTML/JS and their pros & cons further in this post.
What you’ll see in the video below is the sketching example with realtime collaboration added using short-interval data polling of a ColdFusion application server. The realtime collaboration is shown between an iPad 2, a Kindle Fire, and a Macbook Pro.
Before we get into the code for this example, let’s first review some realtime data basics…
First, why/when would you need realtime data in your applications? Here are just a few:
Time sensitive information, where any delay could have major repercussions
Realtime financial information
Emergency services (medical, fire, police)
Military/Intelligence scenarios
Business critical efficiency/performance metrics
Collaboration
Realtime audio/video collaboration
Shared experience (presentations/screen sharing)
Entertainment
Streaming media (audio/video)
Gaming
Regardless of whether you are building applications for mobile, the web, or desktop, using any technology (Flex/Flash, HTML/JS, Java, .NET, Objective C, or C/C++ (among others)), there are basically 3 methods for streaming/realtime data:
Socket Connection
HTTP Polling
HTTP Push
Socket Connections
Socket connectionss are basically end-to-end communications channels between two computer processes. Your computer (a client) connects to a server socket and establishes a persistent connection that is used to pass data between the client and server in near-realtime. Persistent socket connections are generally based upon TCP or UDP and enable asynchronus bidirectional communication. Binary or Text-based messages can be sent in either direction at any point in time, in any sequence, as data is available. In HTML/JS applications you can use web sockets, which I recently discussed, or use a plugin that handles realtime socket communication. Did you also know that the next version of ColdFusion will even have web socket support built in? In Flash/Flex/AIR, this can be achieved using the RTMP protocol (LCDS, Flash Media Server, etc…) or raw sockets (TCP or UDP).
Direct Socket Communications
In general, direct socket based communication is the most efficient means of data transfer for realtime application scenarios. There is less back and forth handshaking and less packet encapsulation required by various protocols (HTTP, etc…), and you are restricted by fewer network protocol rules. However, socket based communications often run on non-standard or restricted ports, so they are more likely to be blocked by IT departments or stopped by network firewalls. If you are using socket based communication within your applications, which are running on non-standard ports, and you don’t govern the network, you may want a fallback to another realtime data implementation for failover cases.
HTTP Polling
HTTP Polling is the process of using standard HTTP requests to periodically check for data updates on the server. The client application requests information from the server. Generally, the client will send a timestamp indicating the last data update time. If there is information available on the server that is newer than the timestamp, that data will be immediately sent back to the client (and the client’s timestamp will be updated). After a period of time, another request will be made, and so forth until the polling is stopped within the application. Using this approach, the application is more-or-less “phoning home” periodically to the server to see if there are any updates. You can achieve near-realtime performance by setting a very short polling interval (less than one second).
Basic Data Poll Sequence
HTTP polling uses standard web protocols and ports, and generally will not be blocked by firewalls. You can poll on top of standard HTTP (port 80) or HTTPS (port 443) without any issue. This can be achieved by polling JSON services, XML Services, AMF, or any other data format on top of a HTTP request. HTTP polling will generally be slower than a direct socket method, and will also utilize more network bandwidth b/c of request/response encapsulation and the periodic requests to the server. It is also important to keep in mind that the HTTP spec only allows for 2 concurrent connections to a server at any point in time. Polling requests can consume HTTP connections, thus slowing load time for other portions of your application. HTTP polling can be employed in HTML/JS, Flex/Flash/AIR, desktop, server, or basically any other type of application using common libraries & APIs.
HTTP Push
HTTP Push technologies fall into 2 general categories depending upon the server-side technology/implementation. This can refer to HTTP Streaming, where a connection is opened between the client and server and kept open using keep-alives. As data is ready to send to the client, it will be pushed across the existing open HTTP connection. HTTP Push can also refer to HTTP Long Polling, where the client will periodically make a HTTP request to the server, and the server will “hold” the connection open until data is available to send to the client (or a timeout occurs). Once that request has a complete response, another request is made to open another connection to wait for more data. Once Again, with HTTP Long Poll there should be a very short polling interval to maintain near-realtime performance, however you can expect some lag.
HTTP Long Poll Sequence
HTTP Streaming & HTTP Long polling can be employed in HTML/JS applications using the Comet approach (supported by numerous backend server technologies) and can be employed in Flex/Flash/AIR using BlazeDS or LCDS.
Collaborative Applications
Now back to the collaborative sketching application shown in the video above… the application builds off of the sketching example from previous blog posts. I added logic to monitor the input sketches and built a HTTP poll-based monitoring service to share content between sessions that share a common ID.
Realtime Collaborative Sketches
In the JavaScript code, I created an ApplicationController class that acts as an observer to the input from the Sketcher class. The ApplicationController encapsulates all logic handling data polling and information sharing between sessions. When the application loads, it sets up the polling sequence.
The polling sequence is setup so that a new request will be made to the server 250MS after receiving a response from the previous request. Note: this is very different from using a 250MS interval using setInterval. This approach guarantees 250MS from response to the next request. If you use a 250MS interval using setInterval, then you are only waiting 250MS between each request, without waiting for a response. If your request takes more than 250 MS, you will can end up have stacked, or “concurrent” requests, which can cause serious performance issues.
When observing the sketch input, the start and end positions and color for each line segment get pushed into a queue of captured transactions that will be pushed to the server. (The code supports multiple colors, even though there is no method to support changing colors in the UI.)
When a poll happens, the captured transactions are sent to the server (a ColdFusion CFC exposed in JSON format) as a HTTP post.
ApplicationController.prototype.poll = function () {
this.pendingTransactions = this.capturedTransactions;
this.capturedTransactions = [];
var data = { "method":"synchronize",
"id":this.id,
"timestamp":this.lastTimeStamp,
"transactions": JSON.stringify(this.pendingTransactions),
"returnformat":"json" };
var url = "services/DataPollGateway.cfc";
$.ajax({
type: 'POST',
url: url,
data:data,
success: this.getRequestSuccessFunction(),
error: this.getRequestErrorFunction()
});
}
The server then stores the pending transactions in memory (I am not persisting these, they are in-ram on the server only). The server checks the transactions that are already in memory against the last timestamp from the client, and it will return all transactions that have taken place since that timestamp.
<cffunction name="synchronize" access="public" returntype="struct">
<cfargument name="id" type="string" required="yes">
<cfargument name="timestamp" type="string" required="yes">
<cfargument name="transactions" type="string" required="yes">
<cfscript>
var newTransactions = deserializeJSON(transactions);
if( ! structkeyexists(this, "id#id#") ){
this[ "id#id#" ] = ArrayNew(1);
}
var existingTransactions = this[ "id#id#" ];
var serializeTransactions = ArrayNew(1);
var numberTimestamp = LSParseNumber( timestamp );
//check existing tranactions to return to client
for (i = 1; i lte ArrayLen(existingTransactions); i++) {
var item = existingTransactions[i];
if ( item.timestamp GT numberTimestamp ) {
ArrayAppend( serializeTransactions, item.content );
}
}
var newTimestamp = GetTickCount();
//add new transactions to server
for (i = 1; i lte ArrayLen(newTransactions); i++) {
var item = {};
if ( structkeyexists( newTransactions[i], "clear" )) {
serializeTransactions = ArrayNew(1);
existingTransactions = ArrayNew(1);
}
item.timestamp = newTimestamp;
item.content = newTransactions[i];
ArrayAppend( existingTransactions, item );
}
var result = {};
result.transactions = serializeTransactions;
result.timestamp = newTimestamp;
this[ "id#id#" ] = existingTransactions;;
</cfscript>
<cfreturn result>
</cffunction>
When a poll request completes, any new transactions are processed and a new poll is requested.
ApplicationController.prototype.getRequestSuccessFunction = function() {
<pre> var self = this;
return function( data, textStatus, jqXHR ) {
var result = eval( "["+data+"]" );
if ( result.length > 0 )
{
var transactions = result[0].TRANSACTIONS;
self.lastTimeStamp = parseInt( result[0].TIMESTAMP );
self.processTransactions( transactions );
}
self.pendingTransactions = [];
self.requestPoll();
}
}
You can access the full client and server application source on Github at:
I’d like to take this opportunity to introduce you to a new project I’ve been working on to showcase enterprise-class data visualization in HTML-based applications. The US Census Browser is an open source application for browsing data from the 2010 US Census.
The app is completely written using HTML and JavaScript, even for the charting/data visualization components. You can check it out in several application ecosystems today:
Support for additional platforms is planned for future development. Future targets include BlackBerry Playbook as well as Android 2.x devices, including the Amazon Kindle Fire and Barnes & Noble Nook Color – Android 2.x does not support SVG graphics in-browser, so I am working on some alternative features.
Update: Kindle Fire and Playbook have been approved, and are now supported. See links above.
Please keep in mind that this application was designed for mobile devices. Internet Explorer in particular does not work well with the Census Browser – use at your own risk. The browser-based application has been tested and works properly in the latest versions of Chrome, Safari, Firefox, and Opera. The US Census Browser application also does not work in Android 2.x and below, due to the fact that these versions of Android do not support SVG graphics in the mobile browser.
APPLICATION OVERVIEW
The application is essentially a single-page web site, which asynchronously loads data from the backend upon request, and displays that data to the user. The main application file is index.html, which loads the UI and appropriate client-side scripts. The main presentation logic is applied via CSS stylesheets, and the application control is handled by the ApplicationController class, inside of application.js. The ApplicationController class handles state changes within the application and updates the UI accordingly. The main data visualization and data formatting logic is all contained within the censusVisualizer class, which the ApplicationController class uses to render content. All DOM manipulation, event handling, and AJAX requests are performed using jQuery.
The data visualization is implemented 100% client-side, using the Highcharts JavaScript library. Highcharts renders vector graphics client-side, based upon the data that is passed into it. Check out the examples at: http://www.highcharts.com/demo/ for a sample of what it is capable of.
The fluid scrolling and swiping between views is implemented using the iScroll JavaScript library. Note: I’m using iScroll-lite.js. This is a great resource for any HTML-mobile, or mobile-web applications.
PHONEGAP USAGE
The client-side runtime does not have any dependencies for access to device-specific functionality. However, PhoneGap is being used as an application container so that the application can be distributed through various mobile “app stores”.
SERVER-SIDE
The back-end of this application is written using ColdFusion. Yep, that’s right. I used CF. In fact, the server side is ridiculously simple. It is only a single ColdFusion Component (CFC), with three remotely exposed methods for accessing data, and relies upon CF’s built in functionality to serialize JSON. CF is incredibly powerful, and made this project very simple and quick to develop.
Get ready for 360|Flex 2012! What better place to network and learn the latest about Flex development for mobile, the desktop, and the browser? 360|Flex is a chance to interact with the community and even get involved in the open-source Apache Flex project. The 360|Flex 2012 schedule is now available, and it’s loaded with great presentations from leaders in the Flex community.
I’m excited to have been chosen for 360|Flex this year, focusing on Multi-Device Best Practices.
Multi-Device Best Practices Ready to bring the “write once, run everywhere” dream to a wonderful reality? In this session we will focus on multi-device deployment considerations and best practices to help bring your applications to as many platforms, devices, and form factors as possible.
Tomorrow (Thurs) I'm presenting an "Introduction to Mobile Development with PhoneGap" at Towson University http://t.co/Qch6pD93 Come on out! 3 hours ago
Recent Comments