0

I'm working on PhoneGapping a mobile web app I wrote from the ground up, and I'm wondering what everyone's thoughts are on progressive enhancement?

Right now, the PhoneGap app is just pointing at our domain, so whatever code is on the server is what's being run. I'd like to keep it this way as much as possible, but I was wondering if there was some way to detect if the viewer is coming through PhoneGap or not and then enable other functionality based on that (e.g. local contacts, push notifications).

I know PhoneGap requires the phonegap.js file to be present, and it seems that including that across-the-board is going to cause some trouble with non-Phonegap users, so any thoughts here would be excellent. Thanks!

Brad Orego
  • 2,976
  • 3
  • 18
  • 24
  • You could modify the user-agent of your app. – Uncharted Space Dec 13 '13 at 22:08
  • To what, though? I haven't looked at it extensively, but it doesn't look like PG has an incredibly unique User Agent, so I don't know if I'd be able to use something like that. It also seems like having the phonegap.js file on our server isn't helping - `deviceready` is firing but none of the APIs are available :/ – Brad Orego Dec 16 '13 at 16:13
  • Yeah phonegap has the same user agent as the built in browser, but this is pretty easy to modify in Android. Haven't looked into iOS. You could just add some unique string to the end (app name or package or something) then have your server look for that string. If it's there, serve the phonegap code, else the regular. In regard to API's not firing, what version of PG you using? – Uncharted Space Dec 16 '13 at 17:18
  • Hmmm, interesting. We're only building this for Android (we have a native iOS app), but that's not a bad idea. I'm using the latest version of PG - `3.2.0-0.17.1` – Brad Orego Dec 16 '13 at 17:35
  • 1
    `String ua = this.appView.getSettings().getUserAgentString();` `this.appView.getSettings().setUserAgentString(ua + " my-custom-whatever");` As far as API's not being available, you're sure the plugins are installed and js is loading correctly? Remember that in 3.0+, even the standard API's need to be explicitly installed. – Uncharted Space Dec 16 '13 at 18:02
  • Where would be the best place to put the UA-modifying code? Also re: the plugins installed, it should be. I have access to `navigator.contacts` on another app with an identical config.xml file, but I haven't tried with this project and whether or not it's a remote resource or it's local. Let me try that and get back to you – Brad Orego Dec 17 '13 at 19:16
  • Okay, as it turns out, PG has some fallbacks for local files, so if you don't have the API JS in your project directory, it'll look at `/platforms/android/assets` for the `www/plugins` folder, which has the appropriate JS files. If you put this on your web server in the proper spot, it seems to work fine (though I now need to figure out how to detect if it's coming from PG or not) – Brad Orego Dec 17 '13 at 20:13
  • The UA code would go in your activity's `onCreate` method after the `super.loadUrl`. (In the main java file). – Uncharted Space Dec 17 '13 at 21:40
  • Okay, this is really freaking awesome. I'll briefly post an answer to this, but I'll also be writing up a blog post with more details on how/why we're doing this. You deserve just as much props for this, though - thanks a ton for all the help! – Brad Orego Dec 18 '13 at 01:26

1 Answers1

1

I'll post a link to a blog post about this with more details/examples, but essentially this boils down to three things:

  1. Modifying the requests from PhoneGap and then detecting that on your server
  2. Making sure the proper Javascript APIs are in the right place
  3. Detecting when to show/enable PhoneGap-specific functionality

The way I'm currently accomplishing this is as follows:

1) Modifying the requests from PhoneGap

You can add a custom string to the User Agent from your PhoneGap app and then search for that custom string on the server. The easiest way to do that (on Android) is in your platforms/android/src/path/to/your/app/[app_name].java. In the onCreate method, after the super.loadUrl(Config.getStartUrl()); line, add:

String ua = this.appView.getSettings().getUserAgentString();
this.appView.getSettings().setUserAgentString(ua + " your_custom_string");

2) Making sure the proper Javascript APIs are in the right place

When you build a PhoneGap app and run it with a local source, there's a fallback for the actual Javascript APIs PhoneGap uses. If running locally, you don't need the cordova.js or phonegap.js file in your project directory at all. You can find the files you need in platforms/android/assets/www. You're looking for cordova.js, cordova_plugins.js, and the entire plugins/ directory. In your web app, then, you need to make sure the folder you're pointing to for cordova.js also has the plugins/ directory. For example:

<script type="text/javascript" src="/js/cordova.js"></script>

Means everything should be in your webroot/js/ folder.

3) Detecting when to show/enable PhoneGap-specific functionality

This is as easy as reading the User Agent for your_custom_string from earlier and enabling/disabling features. You're not going to want to load the cordova.js script unless the viewer is coming from PhoneGap (things get weird otherwise), and make sure you set up an event listener on the deviceready event, and do any PhoneGap-specific code after that's fired.

The forthcoming blog post will have a simple example using Ionic and PhoneGap's Contacts API.


And that's it! I'm really excited about the potential this opens for progressive enhancement. This lets me support both mobile web and native (Android, and likely iOS) with ~99% of the same codebase, and allows me to only enable features if I know the user has them. It's like hacky feature detection on steroids.

Brad Orego
  • 2,976
  • 3
  • 18
  • 24