Category Archives: Desktop

Tricks for Debugging PhoneGap Applications in Desktop Browsers

I often encourage people to develop as much as possible in desktop browsers when they are building PhoneGap applications.  While there are remote debugging tools such as weinre for remote debugging on devices, the developer experience is still better inside of a desktop browser because it gives you breakpoints and memory inspection capabilities.  In most cases, you can develop the vast majority of your application within the desktop browser, and switch to a physical device when integrating with PhoneGap APIs or for performance testing. Personally, I use Chrome, and take advantage of the Chrome Developer Tools.

However, when developing from the local file system, you will run into a few roadblocks with desktop browsers.  A big issue is the browser security model.  If you try to asynchronusly request files when the application is loaded from the local file system, you’ll like get an error like:

XMLHttpRequest cannot load (filename or url). Origin null is not allowed by Access-Control-Allow-Origin.

Luckily, there are a few tricks you can use to get around this… local HTTP servers and relaxing the browser’s security.  Note: I’m on a Mac, and I don’t know the syntax for these on Windows.

Local HTTP Server

The first option is to use a local web server to host files.   You can fire up a simple HTTP server from any directory in OSX by opening a terminal and using the following command:

python -m SimpleHTTPServer 8000

An HTTP server will start, and you’ll be able to access any content from that directory and child directories from the URL http://localhost:8000/  Thanks to @mesh for this trick.

However, this will only work for static content that is within your directory structure.   If you need dynamic content, you’ll need some sort of application server infrastructure.

Relaxed Browser Security

OK, that’s great, but it doesn’t cover every situation.   What if you don’t want a local application server configuration?  What if you want to develop against services that are remote, and you don’t control them?    Well, you are in luck.

You can disable security restrictions in Chrome to allow you to access these services.   The following command will allow unrestricted access from the file system, and will also allow cross-site requests.   Kill Chrome, then relaunch from a terminal window with the following flags:

open -a /Applications/Google\ Chrome.app --args --allow-file-access-from-files --disable-web-security

Using this configuration, you’ll be able to open an HTML file from the local file system, and that file will be able to make requests to other sites to access data or other resources.

In the screenshot below, you can see that I launched my Census Browser application from the local file system, and it can access services from http://www.tricedesigns.com.   With the default browser security policy, this would not be possible.

Local Application Debugging With Remote Services

WARNING: ONLY USE THIS FOR DEBUGGING!

Do not use this configuration for normal web browsing because it will leave your browser security wide open, and able to be exploited and compromised.  Do not browse the web when you’ve relaxed the security policy.

Thanks to fellow Adobe evangelist Piotr Walczyszyn for introducing me to this trick.

Repurposing PhoneGap Apps as Desktop Apps

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:

US Census Browser in OSX

You can build complete AIR applications using HTML and JavaScript, even with full access to AIR APIs (network, file access, etc.).   You can read more about building AIR apps with HTML and JavaScript at: http://help.adobe.com/en_US/air/build/WS5b3ccc516d4fbf351e63e3d118666ade46-7ecc.html

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.

Here’s my AIR application XML:

[xml]<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://ns.adobe.com/air/application/3.1">
<id>com.tricedesigns.USCensusBrowser</id>
<versionNumber>1.0</versionNumber>
<filename>USCensusBrowser</filename>
<name>US Census Browser</name>
<initialWindow>
<content>www/index.html</content>
<visible>true</visible>
<width>1024</width>
<height>768</height>
<minSize>800 600</minSize>
</initialWindow>
<icon>
<image16x16>icons/icon16.png</image16x16>
<image32x32>icons/icon32.png</image32x32>
<image48x48>icons/icon48.png</image48x48>
<image128x128>icons/icon128.png</image128x128>
</icon>
</application>
[/xml]

Notice that the “content” node just points to my “index.html” file.

Here’s the command to package it:

[bash]adt -package -storetype pkcs12 -keystore sampleCert.pfx HelloWorld.air HelloWorld-app.xml *[/bash]

You can read more about this process in the Adobe AIR documentation.

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:

Enjoy!

Preview: New HTML5/PhoneGap Project

Here’s a quick preview of my new HTML5/PhoneGap data vizualization app. Once released, this will be available on multiple platforms, in multiple app stores, AND it will be completely open source.  Just waiting on app store approvals…

You can expect a full writeup on how this was built after it is released.

Enjoy!


UPDATE:

This application is now available in iOS and Android markets, and full source code is available. See details at http://www.tricedesigns.com/2011/12/05/introducing-the-us-census-browser-application/

A Single Code Base, Lots of Devices

Here’s a quick teaser for a multi-part series I’m working on: 1 code base, 1 application framework, 4 platforms, 7 devices, 5 ecosystems…

Single Code Base, Lots of Devices

Yes, that is correct…

1 codebase, Adobe Flex

1 framework, Adobe AIR

4 platforms

7 devices (these are just devices I have):

5 ecosystems

This is just a teaser, but I’ll soon be releasing details how to take an application idea and deliver it to multiple ecosystems, all with a single toolset. Stay tuned…

AIR 3.0 Captive Runtime

If you hadn’t heard yet, Beta 2 of AIR 3.0 and Flash Player 11 are now availabe on Adobe Labs. The AIR 3.0 beta release is sporting some great new features, including hardware accelerated video playback for mobile, iOS background audio, android licensing support, front-facing camera support, encrypted local storage for mobile, H.264 software encoding for desktop applications, and last, but not least, captive runtime support for desktop and Android applications.

If you are wondering what “captive runtime support” is, then I’ll try to explain… Currently all AIR applications that are deployed on the desktop and in Android require the 3rd-party Adobe AIR runtime. If you are familiar with the process for developing mobile AIR applications for Apple’s iOS devices, then you may already know that these applications don’t require the 3rd-party runtime; they are completely self-contained applications. These AIR applications for iOS already take advantage of the captive runtime. All necessary components of the AIR framework are bundled into a self-contained, compiled distributable application that has no dependence upon other frameworks.

With AIR 3.0, you will have the option to bundle the AIR framework into your applications to eliminate the 3rd-party dependency. However, one thing to keep in mind is that you can only export mac application packages on Macs and Windows EXEs on Windows. You can’t target native installers or bundled runtimes for cross-platform development. You can only have a single app that targets both platforms if you export a .AIR file (which requires the 3rd-party AIR runtime).

Instructions for using the captive runtime:
First, make sure that you extract the AIR runtime SDK from the archive. Instructions for extracting the AIR SDK are located at: http://kb2.adobe.com/cps/495/cpsid_49532.html

Next, add a compiler argument for swf-version=13.

Then use the ADT command line utility to build and package your application. If you run the ADT tool on the command line without passing any arguments, it will show you all of the packaging options.

For the Android captive runtime, you just need to select the target “apk-captive-runtime“, as identified by:
[bash]adt -package -target ( apk | apk-debug | apk-emulator | apk-captive-runtime ) ( CONNECT_OPTIONS? | -listen <port>? ) ( -airDownloadURL <url> )? SIGNING_OPTIONS <output-package> ( <app-desc> PLATFORM-SDK-OPTION? FILE-OPTIONS | <input-package> PLATFORM-SDK-OPTION? )[/bash]

For the desktop captive runtime, you need to select the target “bundle“, as identified by:
[bash]adt -package SIGNING_OPTIONS? -target bundle SIGNING_OPTIONS? <output-package> ( <app-desc> FILE-OPTIONS | <input-package> )[/bash]