Launch a website as a mobile app using PhoneGap/Apache Cordova


How to launch a website as a mobile app using PhoneGap/Apache Cordova


I spent some time recently trying to find out how to launch my website as a mobile app.  The information was available around the internet but since it took me a while, I thought I'd collate it here in one simple post for anyone who wants to do the same

I decided to use Apache Cordova since it gave me the framework for developing an HTML5 site as a mobile app already, meaning all I really needed to do was plug my website into it.  Their getting started guide has good information on how to create a Cordova project - I used Android but you can use whatever means you wish

A basic Cordova app gives you a way to launch the app with an HTML page that you use to display your app contents.  The trick then is make the page load your website which you can do in one of 3 ways:

1. Package your site inside the app. This means it loads fast and without an internet connection.  The downside is you have to update and re-release the app whenever your website changes. It also needs to use relative paths since the root directory will be the mobile device's root directly, not the root of your site
2. Point the page at your remote website, which means changes are picked up immediately.  The downside is that it won't work if the phone has no internet connection
3. Do both and fall back to the local site if there is no network connection

Option 1 - Package your website inside the app

If you want to do option 1 (package your site with the app) you simply copy your entire site into the assets > www directory which will load your homepage as a local page (I think PhoneGap Build insists this is index.html, but if you're loading from code you just launch Cordova with that page name). Simple. You need not read on unless you're interested in option 2 or 3

Option 2 - launch your external website inside the app

To load a remote site, you need to load your homepage (or any page) using javascript from the html page that Cordova will open in your app.  This is relatively simple using basic javascript
window.location="http://your.website";

The recommended way to run javascript in a Cordova environment is to use Cordova's ondeviceready event which ensures it is loaded, which can be hooked into your page

document.addEventListener("deviceready", onDeviceReady, false);

function onDeviceReady() {

// Now safe to use the Codova API

window.location="http://your.website"; }

This is probably not strictly necessary for this javascript call, which is not using the Cordova API.  However I am using because it is needed for option 3

You also need to tell Cordova that it is safe to load your website in the cordova.xml properties (you can remove the subdomains part if you don't have any)

<access origin="http://your.website" subdomains="true"/>
At this point you are good to go!

Option 3 - launch your external website but fail back to local version

This option requires a little more work but gives you the advantage of displaying a set of files packaged with the app if there is no internet connection

Since you need the html page given by Cordova in assets > www you will need to copy your local site to a subdirectory (I've called it local), and do everything in option 2 to load the remote site

All you need then is to add some logic to decide whether there is an internet connection and act accordingly.  Fortunately Cordova gives us a solution to this

Firstly, add a javascript function to check the connection type

function checkConnection() {
  var networkState = navigator.network.connection.type;
  var states = {};
  states[Connection.UNKNOWN] = 'Unknown connection';
  states[Connection.ETHERNET] = 'Ethernet connection';
  states[Connection.WIFI] = 'WiFi connection';
  states[Connection.CELL_2G] = 'Cell 2G connection';
  states[Connection.CELL_3G] = 'Cell 3G connection';
  states[Connection.CELL_4G] = 'Cell 4G connection';
  states[Connection.NONE] = 'No network connection';
  return networkState;
}

Then add some logic around the window.location call to load the appropriate site

function onDeviceReady() {
  var networkState = checkConnection();
  /* load local files if there is not network connection */
  if (networkState == Connection.NONE) {
    window.location="local/index.html";
  } else {
    window.location="http://your.website";
  }
}

Again, you're good to go!

As an alternative to option 2 or 3 (I'll call it option 2a) you could use the connection type logic to display an error message so you don't attempt to load the external site when there is no connection eg:

function onDeviceReady() {
  var networkState = checkConnection();
  /* load local files if there is not network connection */
  if (networkState == Connection.NONE) {
    navigator.notification.alert('This app requires an internet connection');
  } else {
    window.location="http://your.website";
  }
}

I'm going to wrap a framework around this and release some instructions for non-developers to produce site launchers for mobile devices using PhoneGap build.  Watch this space

Comments

  1. This comment has been removed by a blog administrator.

    ReplyDelete
  2. Trying to do step 2 here, but unsuccessful. Wondering if you could help me out really quick. I would greatly appreciate it.

    ReplyDelete
  3. Got it to work, minus the site styling. Shouldn't it be pulling in all the styling as well (using step 2)?

    ReplyDelete
  4. Hi, yes it should, it's just CSS so the styles should get pulled in from there. Are they hosted externally to your normal site, or in a subdomain? Could be the access origin

    ReplyDelete
  5. Hi,

    Thanks for the great tips. Exactly what i needed when i needed it!

    ReplyDelete
  6. Option 2 open browser and loads website. where did i go wrong?

    ReplyDelete
  7. Hi

    I'd probably need a bit more information than that but it could be that you didn't set the access origin, are pointing your launch file to the remote page instead of the local one, haven't set cordova up properly ... if you can provide your cordova.xml, local html code etc I might be able to help but otherwise that question is too vague

    Antony

    Antony

    ReplyDelete
  8. I have php scripts running back end of my mobile website ,is it possible to deploy my website as an app with option 2
    thanks in advance

    ReplyDelete
  9. Hi, no, cordova doesn't run PHP which is a server-side language I'm afraid
    Antony

    ReplyDelete
  10. These tips are always work for me.. thanks for sharing these info.. i will always take care of these...

    make mobile website

    ReplyDelete
  11. Hi Antony. Great job!. I have a question, cordova.js (at least now) is a different file in iOS than in Android. How do you handle this script inclusion on the 'remote' website?

    Thanks a lot

    Edgar

    ReplyDelete
  12. Hi, I think that depends on what you are trying to do? The remote site doesn't need cordova.js is all you are doing is redirecting to it, only the launch page needs it which is local anyway

    Antony

    ReplyDelete
  13. Thanks for sharing this code, very useful.

    Just want to share a couple of fixes I had to make to get it working with PhoneGap 3. I had to change:

    var networkState = navigator.network.connection.type;

    to

    var networkState = navigator.connection.type;

    And make sure the appropriate plugin was installed on the command prompt:

    phonegap local plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-network-information.git

    Worked after that!

    Again, thanks for sharing .. was a big help.

    - Mark

    Freelance Software Developer

    ReplyDelete
    Replies
    1. navigator.network.connection.type;
      it works in that case if you have installed following plugin:
      cordova-plugin-network-information

      otherwise you are right only navigator.connection.type; will work

      Delete
  14. very nice blog.
    but i have one issue.
    function onDeviceReady()
    {
    document.addEventListener("backbutton", onBackKey, false);
    window.location="../index.jsp";
    }
    once i switch to the index.jsp .i looses the functionality of phonegap
    example :- backbutton event not execute

    ReplyDelete
  15. I was wondering if it is possible to access the PhoneGap/Cordova API from within the mobile app. Basically, I would like to choose option 2. If the mobile site (written in Backbone + Marionette) detects that it is called from the PhoneGap wrapper, it exposes some additional functionality (such as GPS tracking).

    So far I managed to implement the basics of option 2. However, while a call to a arbitrary PhoneGap API method (navigator.connection.type) seems to work from PhoneGap's index.html, I can't manage to call it from my mobile app, even though I included cordova.js. It just doesn't seem to trigger the deviceready event, and navigator.connection is undefined.

    Perhaps related, I'm also getting the error "Uncaught SecurityError: Blocked a frame with origin "http://mysite.com" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match."

    ReplyDelete
  16. This comment has been removed by the author.

    ReplyDelete
  17. thanks for sharing antony!

    @ruben stranders, trying to implement exactly your described problem at the moment...
    can you be more specific on "... I included cordova.js." is cordova.js on the remote mobile website or in the local cordova app? if second (which would be the better solution as far as i can see, to support different corona.js versions for ios/android) could you please describe how to manage to include the cordova.js to your remote mobile website? thanks a lot.

    ReplyDelete
  18. @Ruben, that's exactly the thing I would be interested to know. As far as I have heard, it's not possible but maybe just because ppl didn't try hard enough?

    ReplyDelete
  19. If anybody come across with file to found: www/"http://google.com" error, advice to use window.open("http://google.com"); instead of window.location

    Fahid Mohammad - aka (Volcano)

    ReplyDelete
  20. and for anyone else wondering, if you've whitelisted your remote website, then you can access PhoneGap plugins from your live external site. Of course the plugin needs to be installed in your phonegap app (so the ObjectiveC/Java code part of it is there), but once it's there, any site in your whitelisted sites can access the plugins.

    ReplyDelete
    Replies
    1. Unfortunately this is not working with onclick="window.open('https://www.google.de', '_system');" Its only open inside the webview, not in the browser.

      Do you know a solution?
      Thanks

      Delete
  21. I'm using phonegap for iOS app for my external application. The problem is the resource files like JS, CSS etc. are very large and takes long time to load. Is there any solution to have these resource files local and replace it while page is being loaded from external URL?

    I tried this using native application and i can do that. But didn't find any location to replace the referencing urls using phonegap. Can you help on that?

    ReplyDelete
  22. In case of option number 2, what's the policy of the Apple Store? Is it permitted a solution like this?

    ReplyDelete
  23. Cordova is not accessible from my the remote webpage. I get the error "Can't find variable cordova" when trying to call any corva API like navigator,notification.alert ...
    However it is working in the local page deviceready function.
    I have also whitelisted my website.

    Any idea ?

    ReplyDelete
    Replies
    1. I think you have to include you cordova.js inside you website source

      Delete
    2. For remote webpage:
      Step 1: Create cordova project
      Step 2: Add browser as platform
      Step 3: Add cordova-plugin-dialogs plugin it will automatically add cordova-plugin-dialogs for dialog
      Step 4:build your app and then go to directory under your project like {your project name}\platforms\browser\build there you find package.zip
      Step 5:upload package.zip to your server

      Delete
  24. I am afraid that Apple might reject such apps, "simply web sites bundled as Apps, " as found in http://www.adobe.com/devnet/phonegap/articles/apple-application-rejections-and-phonegap-advice.html

    Did anybody try doing such apps and got their app approved ? Any suggestions ?

    ReplyDelete
  25. I'd guess apple may not be too happy with this. All good on android though :)

    ReplyDelete
  26. Just been trying this on Cordova 3.7.0 - still works :) Admittedly DroidGap is deprecated, but it's still there at the moment, will look at that at some point

    ReplyDelete
  27. I've been trying to get this to work in Monaca + Phonegap, but nothing ever loads in the window. Just stays blank. No errors or anything though. Any ideas?

    ReplyDelete
  28. This message might be helpful: PhoneGap applications typically load their main HTML page from the device; thus, XHR can access both local files or server files. However, if the main HTML page is loaded from a server, then only XHR requests to that server are allowed. This is a security restriction to prevent cross-domain security concerns.

    ReplyDelete
  29. it is from: https://www.ibm.com/developerworks/mydeveloperworks/blogs/94e7fded-7162-445e-8ceb-97a2140866a9/entry/dynamic_page_loading_for_phonegap1?lang=en

    ReplyDelete
  30. have a container div in the index.html and use jquery's ajax to load your form, ui, javascript might overcome your challenge.

    ReplyDelete
  31. Hi,
    Can u send me the whole application using cordova....Im new to this so will use your app as a reference point to strart with...!!!

    ReplyDelete
  32. HI,

    Can u provide me with the whole application so that i can use this as a reference point to start my development. Im new to this development and its exactly the scenario i need to develop.

    ReplyDelete
  33. Thanks very much!
    I chose option 2. It saves a lot of time!

    ReplyDelete
  34. I have tried using option 2. But it opens the link in the chrome browser instead of the application. Anyone know how to solve that ?

    ReplyDelete
  35. Forgot to say that I couldnt find cordova.xml so I added the whitelist thing to config.xml
    ...




    ...

    ReplyDelete
  36. Apparently using google.com as an example was a bad idea cause when I switched to the real site it started working. I had to add the row

    instead of


    Another question. How do I include cordova.js on my online website ? Do I have to find it somewhere and copy it there myself ?

    ReplyDelete
  37. Hi Antony.

    Tried using option 2 with a brand new Phonegap desktop folder, added the code inside my body tags (not sure if its correct) and while testing in localhost it opens my site ok, but when I build it in phonegap build it just shows the icon.

    Any chance I can get in touch other way to send you my code for a quick look? I see a comment above mine and user made it ok.

    ReplyDelete
  38. tried option 2 and it launches my default browser instead outside of the app?

    ReplyDelete
  39. For some Reason I cannot get the external css to load.. it loads the inline css but not the linked css

    ReplyDelete
  40. Great Article that I have been trying to find since last 6 months. Thanks Antony Lee, Also how do we pass values of mobile to web and vice versa!!!

    ReplyDelete
  41. One more thing i want to know is, will it be possible to send Push Notification to android mobile app users if we built app using option-2 . If yes, please suggest some links i can refer to get idea about it.

    ReplyDelete
  42. I've tried option 2, but it has limitations.
    In particular, even if you load cordova.js on the main site (the one you redirect to), a lot of native apis will not work - deviceready will not fire there, I could get backbutton to fire, etc. etc.
    With a redirect, the back button is behaves badly, as it goes back to your Cordova index.html, which in my case is just an empty shell - so the users had to close and restart the app.

    In the end, I've used an iframe covering the whole screen. That way there's no navigation, native events fire correctly, the back button problem is eliminated.

    ReplyDelete
  43. Awesome.. Many thanks to you. I was searching for this topic since last two days. Option 2 was exactly what I was looking for, however Option 3 is what I needed. Superb blog. Once again Thanks a Ton.

    ReplyDelete
  44. Gr8 trick if you want to load site with no cordova/phonegap plugin dependency.
    but worst in case if you want to make use of cordova/phonegap plugin.as if we use external site it wont get access on native device feature..

    ReplyDelete
  45. I had to comment in xml, then it worked.

    ReplyDelete
  46. after window.location="http://mysite.com";
    if there is a lost of Internet connection, then how to show the custom page with lost Internet message..

    ReplyDelete
  47. Excellent.
    It works perfectly.thanks

    ReplyDelete
  48. Every thing works. Issue is the blank window while the url gets loaded. How to show/hide a spinner. Not getting any started/loaded events to control this. Pls Suggest?

    ReplyDelete
  49. I have a problem using this solution. When the back button is pressed then I get error that the page cannot be loaded...message from chrome. Steps to reproduce:
    1. Turn on the mobile data
    2. Access the mobile app => which redirects to my site
    3. Turn off the mobile data
    4. Press phone back button.
    I get the Webpage not available screen.
    2.

    ReplyDelete

Post a Comment

Popular posts from this blog

Installing and using mobilize.js to transform a desktop site to a mobile site

How to manually add Cordova plugins to your app