Using URL Schemes in PhoneGap Build Apps

Edit 2/27/2014 — There’s a new 3rd Party Plugin on PhoneGap Build that is probably a much better way to do this.   I haven’t personally tried it yet, but check out the Customer URL Scheme plugin: https://build.phonegap.com/plugins/433 

I love PhoneGap Build.  It makes the whole process of building a hybrid app easy.  No messing around with build servers for each type of device, no installing of patches when PhoneGap versions come out, and they have an API for automating builds.  But the hidden cost is the inability to modify the native code when you want to.  You are stuck with the options Build offers you.  One of these limitations is in URL schemes.

iOS has always supported URL Schemes.  This allows your app to respond to a URL.  You’ve probably noticed that any url that starts with “mailto://” opens the Mail app and “maps://” opens the Maps app.  You can register your own scheme so that “myapp://” opens your app and you can see any information passed in that URL.  It’s a great way to make web pages link to your app and to have two apps talk to each other.

But while recent versions of PhoneGap have some built-in support for URL schemes, setting it up requires registering the scheme in your info.plist file.  It’s a straightforward entry where you set CFBundleURLName and CFBundleURLSchemes (nice tutorial for iOS devs here).  But since PhoneGap Build does not let you alter the info.plist file and the config.xml file does not support setting these values, you’re out of luck.  There are requests to get this support added, but Adobe has not added it yet.

Never fear – I found a great workaround.  Yes, it’s something of a hack, but it works.  The secret is to use the officially supported FacebookConnect plugin.  This plug in is meant to give access to Facebook for Single Sign On.  We don’t need that functionality, but when the plugin is included in your project, it does setup the info.plist with a URL scheme.

Here are the steps to make this work:

  • Go to https://developers.facebook.com/apps and register your application.  This will give you an APP_ID that you’ll need.  (For testing this out you don’t actually need a registered APP_ID – you just need to choose one that is unique on your device.  But registering with Facebook will ensure uniqueness when you’re app goes public)
  • Add the following <script> tags to index.html:
<script src="cdv-plugin-fb-connect.js"></script>

<script src="facebook-js-sdk.js"></script>
  • Add the gap:plugin tag to config.xml, replacing the APP_ID value with your APP_ID:
<gap:plugin name="FacebookConnect">
   <param name="APP_ID" value="123456" />
 </gap:plugin>
  • In your JavaScript, define a global function handleOpenURL(url).  This will be called whenever your app is already running and another app invokes your URL scheme.  Note that you need to have non-blocking code in this function – a timeout gets around this problem:
function handleOpenURL(url) {
    window.setTimeout(function () {
        window.alert('handleOpenURL: ' + url);       
    }, 1000);
}
  • When your app is not already running and an app invokes your URL scheme, PhoneGap will set a global variable on the window object named “invokeString.”  Somewhere in your launch code, after PhoneGap is initialized, you should check to see if this exists and handle it.
document.addEventListener("deviceready", onDeviceReady, false);

function onDeviceReady() {
    if ('invokeString' in window) {
        window.alert('onDeviceReady: ' + invokeString);
    } else {
        window.alert('onDeviceReady: no invokeString');
    }    
}
  • PhoneGap Build will set up the URL scheme for you.  It will be registered using your bundle identifer (the “id” in the “widget” section of your config.xml) and the scheme will be “fb” + your APP_ID.  If you were to look at the info.plist you’d see:
<key>CFBundleURLTypes</key>
<array>
   <dict>
       <key>CFBundleTypeRole</key>
       <string>None</string>
       <key>CFBundleURLName</key>
       <string>com.unboxedtechnology.ComcastAssistant</string>
       <key>CFBundleURLSchemes</key>
       <array>
           <string>fb123456</string>
       </array>
   </dict>
</array>
  • To have a web link or another app launch or activate your app, they just use the URL scheme before the “://” and any data you want after it.  You can test it by just putting the URL in Mobile Safari:

url_scheme

  • Your app will activate and you’ll see the alert you requested.

url_scheme_alert

Limitations

  • The URL scheme will always be “fb” + APP_ID.  This isn’t as friendly as you’d ideally make your scheme.  You could make your APP_ID something other than numeric so you get a scheme like “fbMyApp” (it works), but now you’re really hacking the plugin.
  • Including the FacebookConnect Plugin addes about 1.5 mb to your install file size.
  • I haven’t tried this with an app that really needs to connect to Facebook.  Sending a custom message through this URL scheme could potentially interfere with what the plugin really wants to do.
  • This was all tested in a PhoneGap 2.2.0 app.  I suspect it will work in later versions but have not tried it.

Conclusion

Hopefully PhoneGap Build will eventually support URL Scheme information in the plist file without having to add the overhead of this plug in.  But for now, this seems like a pretty workable solution with very few lines of code.

Advertisements

4 thoughts on “Using URL Schemes in PhoneGap Build Apps

  1. Great!
    What if user don’t have installed app and type the mentioned url in browser? Is there a way to redirect him to app store to download the app first?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s