RSS
 

PhoneGap – Detect if the application runs on mobile or browser using JavaScript before the “deviceready” and document “ready” events are triggered

05 Nov

I spent hours to find out how to do it. And believe me or not, I found nothing on the whole internet about how to solve it.

Actually there is a simple way to do that after the event “deviceready” has been triggered (as described on the PhoneGap’s API Docs), it is simple as:

1
2
3
4
5
6
7
document.addEventListener("deviceready", function(e){
    if ( device ) {
        alert("Running on PhoneGap!");
    } else {
        alert("Running NOT on PhoneGap!");
    }
}, false);


The “deviceready” trigger, tell us when all native components are loaded and ready to use. Which means, that there is no way to determine whether the page loaded from PhoneGap or not using the PhoneGap plugin itself. You can check the UserAgent, but it is not always true, because it is possible to open the page through the mobile’s browser which is the same UserAgent as loaded from PhoneGap.

Let’s give a typical example, that describes the case better. Let’s say I want to perform an action when the device is ready and the document is ready, both together. Of course you can do this using old-fashioned way, like using counters, event inside event or other creative ways.
Well, they will all work, but with a lot of complications and code, and all of them relies on events, which is not what I need.

With a little thinking and testing, I found a difference between the environments. The URL that loading the HTML file from PhoneGap is different from the one loaded not from PhoneGap.

The URL loaded from PhoneGap looks like this:
(iPhone) file:///var/mobile/Applications/.../App.app/www/index.html
(Android) file:///android_asset/www/index.html

The URL that is loaded NOT from PhoneGap looks like this: http://www.myappsite.com/index.html

See the difference? That’s right! the protocols are different.

So, basically it’s easy now, right? The script should be as follows:

1
2
3
4
5
if ( window.location.protocol === "file:" ) {
    alert("Running on PhoneGap!");
} else {
    alert("Running NOT on PhoneGap!");
}

But, there’s another problem. What if I opened an HTML file from some folder on my PC? It opens the file using default browser, and the protocol is also “file:”, but it’s not loaded from PhoneGap, and the script will pass not to the right section, not the one we needed, that’s bad.

However, I mentioned a slight difference between the two URLs, the one is loaded from PhoneGap looks like this: file:///.../index.html, and the one loaded not from PhoneGap looks like this: file://.../index.html or like this file:////.../index.html (depends on the browser).

See the difference again? The number of slashes after the protocol is different. Somehow the local files on the mobile got three slashes compared to two or four on the PC. For me that’s enough to determine who is who and what is what. So, my final script to perform this check is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
 * Determine whether the file loaded from PhoneGap or not
 */

function isPhoneGap() {
    return (cordova || PhoneGap || 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("Running NOT on PhoneGap!");
}

This is very useful, especially if you developing a hybrid application for mobile running PhoneGap, and you not always wish to use the phone emulator/simulator, but Chrome or Safari.

Hope it saved someones time and headache. :-)
Good Luck!

 

Tags: , , , , , , , , , , , , , , , , , , , , , , , ,

Leave a Reply

 

 
  1. Ariel

    November 25, 2012 at 09:37

    Great stuff! very helpful! :)

     
    • Slavik Meltser

      November 26, 2012 at 21:24

      I’m glad.