PhoneGap is an HTML5 app platform that allows developers to author native applications with web technologies and get access to APIs and app stores. Applications are built as normal HTML pages and packaged up to run as a native application within a UIWebView or WebView (a chromeless browser, referred to hereafter as a webview). Since PhoneGap is frequently used in conjunction with jQuery Mobile, we wanted to offer a few tips and recommendations to help you get staretd.
The initial application document is loaded by the PhoneGap application by a local file:// URL. This means that if you want to pull in pages from your company's remote server (phone home) you will have to refer to them with absolute URLs to your server. Because your document originates from a file:// URL, loading pages or assets from your remote server is considered a cross-domain request that can be blocked in certain scenarios.
Your ability to access cross-domain pages from within a Phone Gap jQuery Mobile application is controlled by two key things: $.support.cors
and $.mobile.allowCrossDomainPages
, and can also be influenced by the white list feature in later builds of PhoneGap.
In jQuery core, there is a $.support.cors boolean that indicates whether or not jQuery thinks the browser supports the W3C "Cross-Origin Resource Sharing" feature to support cross-domain requests.
Since jQuery Mobile relies on jQuery core's $.ajax() functionality, $.support.cors
must be set to true
to tell $.ajax
to load cross-domain pages. We've heard reports that webviews on some platforms, like BlackBerry, support cross-domain loading, but that jQuery core incorrectly sets $.support.cors
value to false
which disables cross-domain $.ajax() requests and will cause the page or assets to fail to load.
If you find that the button down/hover state (lists, buttons, links etc) feels sluggish the $.mobile.buttonMarkup.hoverDelay
setting might be of use. It will decrease the time between the touch event and the application of the relevant class but will also result in a higher chance that the same class will be applied even when the user is scrolling (eg, over a long list of links).
When jQuery Mobile attempts to load an external page, the request runs through $.mobile.loadPage()
. This will only allow cross-domain requests if the $.mobile.allowCrossDomainPages
configuration option is set to true
. Because the jQuery Mobile framework tracks what page is being viewed within the browser's location hash, it is possible for a cross-site scripting (XSS) attack to occur if the XSS code in question can manipulate the hash and set it to a cross-domain URL of its choice. This is the main reason that the default setting for $.mobile.allowCrossDomainPages
is set to false
.
So in PhoneGap apps that must "phone home" by loading assets off a remote server, both the $.support.cors
AND $.mobile.allowCrossDomainPages
must be set to true
. The $.mobile.allowCrossDomainPages
option must be set before any cross-domain request is made so we recommend wrapping this in a mobileinit
handler:
$( document ).bind( "mobileinit", function() {
// Make your jQuery Mobile framework configuration changes here!
$.mobile.allowCrossDomainPages = true;
});
PhoneGap 1.0 introduced the idea of white-listing servers that its internal webview is allowed to make cross-domain requests to. You can find info about it here on the PhoneGap wiki:
However, not all platforms support this white-listing feature so check the PhoneGap documentation for details. Older versions of PhoneGap prior to 1.0 defaulted to allowing cross-domain requests to any server.
Here are a few more tips that aren't specifically related to PhoneGap but are good to know:
We recommend disabling the pushState feature for installed apps because there are edge cases where this feature can cause unexpected navigation behavior and since URLs aren't visible in a webview, it's not worth keeping this active in these situations.
Android enforces a timeout when loading URLs in a webview which may be too short for your needs. You can change this timeout by editing a Java class generated by the Eclipse plugin for Android:
super.setIntegerProperty("loadUrlTimeoutValue", 60000);