PhoneGap: Detect if running on desktop browser

PhoneGap: Detect if running on desktop browser

I’m developing a web application that uses PhoneGap:Build for a mobile version and want to have a single codebase for the ‘desktop’ and mobile versions. I want to be able to detect if PhoneGap calls will work (ie, is the user on a mobile device that will support PhoneGap).
I’ve searched and cannot believe there is no simple way of doing this. Many people have offered suggestions;

http://www.sencha.com/forum/showthread.php?144127-Checking-if-running-in-PhoneGap-or-Mobile-Web-Browser
http://groups.google.com/group/phonegap/browse_thread/thread/322e80bd41bb1a54/a421300eb2a2029f?lnk=gst&q=detect+desktop#a421300eb2a2029f
http://groups.google.com/group/phonegap/browse_thread/thread/8a95dfeb0f313792/3ff10d8f35211739?lnk=gst&q=detect+desktop+browser#3ff10d8f35211739

None of which work, unless you remove the PhoneGap Javascript file from the desktop version of the app, which defeats my goal of having one codebase.
So far the only solution I have come up with is browser / user agent sniffing, but this is not robust to say the least. Any better solutions welcome!
EDIT: A marginally better solution is to try calling a PhoneGap function after some small timeout – if it doesn’t work, then assume the user is on a desktop web browser.

Solutions/Answers:

Solution 1:

I use this code:

if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|IEMobile)/)) {
  document.addEventListener("deviceready", onDeviceReady, false);
} else {
  onDeviceReady(); //this is the browser
}

UPDATE

Related:  drawImage() not working

There are many other ways to detect if phonegap is running on a browser or not, here is another great option:

var app = document.URL.indexOf( 'http://' ) === -1 && document.URL.indexOf( 'https://' ) === -1;
if ( app ) {
    // PhoneGap application
} else {
    // Web page
}  

as seen here: Detect between a mobile browser or a PhoneGap application

Solution 2:

I wrote a post about it a few days ago. This is the best solution you can find (until PhoneGap will release something, maybe or maybe not), it’s short, simple and perfect (I’ve checked it in every possible way and platform).

This function will do the job for 98% of the cases.

/**
 * Determine whether the file loaded from PhoneGap or not
 */
function isPhoneGap() {
    return (window.cordova || window.PhoneGap || window.phonegap) 
    && /^file:\/{3}[^\/]/i.test(window.location.href) 
    && /ios|iphone|ipod|ipad|android/i.test(navigator.userAgent);
}

if ( isPhoneGap() ) {
    alert("Running on PhoneGap!");
} else {
    alert("Not running on PhoneGap!");
}

To complete the other 2% of the cases, follow these steps (it involves a slight change on native code):

Create a file called __phonegap_index.html, with the source:

Related:  Trying to use the DOMParser with node js
<!-- __phonegap_index.html -->
<script type="text/javascript">
    function isPhoneGap() {
        //the function's content is as described above
    }

    //ensure the 98% that this file is called from PhoneGap.
    //in case somebody accessed this file directly from the browser.
    if ( isPhoneGap() )
        localStorage.setItem("isPhoneGap","1");

    //and redirect to the main site file.
    window.location = "index.html";
</script>

Now, on native simply change the start page from index.html to __phonegap_index.html on all your PhoneGap platforms. Let’s say my project name is example, the files you need to change are (as for PhoneGap version 2.2.0):

  • iOSCordovaLibApp/AppDelegate.m
  • Androidsrc/org/apache/cordova/example/cordovaExample.java
  • Windows 8example/package.appxmanifest
  • BlackBerrywww/config.xml
  • WebOSframework/appinfo.json
  • Badasrc/WebForm.cpp (line 56)
  • Window Phone 7 – No idea where (somebody still developing on that platform?!)

Finally, you can use it anywhere on your site, if it’s running on PhoneGap or not:

if ( localStorage.getItem("isPhoneGap") ) {
    alert("Running on PhoneGap!");
} else {
    alert("Not running on PhoneGap!");
}

Hope it helps. 🙂

Solution 3:

I know it’s been answered a while ago but “PhoneGap.available” doesn’t exist anymore.
You should use:

if (window.PhoneGap) {
  //do stuff
}

or since 1.7, prefer:

if (window.cordova) {
  //do stuff
}

Solution 4:

The most trustable way we found to tell if we are in a cordova/phonegap application is to modify the cordova application’s user agent using this config AppendUserAgent.

Related:  socket.io: send message to specific room (client side)

In config.xml add:

<preference name="AppendUserAgent" value="Cordova" />

Then call:

var isCordova = navigator.userAgent.match(/Cordova/i))

Why?

  1. window.cordova and document.addEventListener('deviceready', function(){}); are subject to racing conditions
  2. navigator.standalone does not work when <content src="index.html" /> is a website (Ex: <content src="https://www.example.com/index.html" /> or with cordova-plugin-remote-injection)
  3. Trying to whitelist user agents to guess if it is a real browser is very complicated. Android browsers are often custom webviews.

Solution 5:

I think this is simplest:
var isPhoneGap = (location.protocol == "file:")

EDIT
For some people that didn’t work. Then you might try (haven’t tested)

var isPhoneGap = ! /^http/.test(location.protocol);

Solution 6:

This works for me (running 1.7.0)

if (window.device) {
  // Running on PhoneGap
}

Tested on desktop Chrome and Safari.