Using PhoneGap Plug-Ins to Handle Intents

Using PhoneGap Plug-Ins to Handle Intents

We made a commitment earlier regarding not having to write Java code to work with the intents from within PhoneGap, and, despite intents being a native Android OS feature, we are going to be able to keep that promise. This is all thanks to the fact that someone has already done the hard work for us. In this section, we will be making use of a PhoneGap plug-in called WebIntent, which was created by Boris Smus. Boris has written a blog post on his motivations for writing WebIntent and it is well worth a read (see www.borismus.com/android-phonegap-plugins).

Essentially, Boris’s plug-in provides the ability to invoke Android intents from your JavaScript, and also to respond to them if your application has intercepted and responded to an intent. Installation of the plug-in is very simple:

CHAPTER 12: Polishing and Packaging an App for Release

1. Download the WebIntent.java and webintent.js files from the following github repository: https://github.com/borismus/phonegap- plugins/tree/master/Android/WebIntent.

2. Tae the webintent.js file and place that in the assets/www folder of the Moundz PhoneGap project.

3. Take the WebIntent.java file and place that in a new borismus directory in the src/com folder of the PhoneGap project.

Figure 12–17 provides a screenshot of how the application folder should look after completing these steps.

Figure 12–17. Our Moundz PhoneGap project folder after adding the WebIntent plug-in files With the plug-in files in their correct place, it’s time to wire everything up. The first step

in this process is including the phonegap.js file in the project and also adding a script include for the webintent.js file. At the same time, we’ll also move the script include for moundz.js to just before the closing body tag, as this is required for trapping particular events.

Additionally, while we are making modifications to the index.html file, we will remove the body onload event handler, as we now need to start making some PhoneGap- specific modifications to our code.

<!DOCTYPE html> <html> <head>

CHAPTER 12: Polishing and Packaging an App for Release

... <script type="text/javascript" src="phonegap.js"></script> <script type="text/javascript" src="webintent.js"></script> ... <!-- <script type="text/javascript"> function initialize() {

MOUNDZ.init(); } // initialize </script> --> </head> <body> ... <script type="text/javascript" src="moundz.js"></script> </body> </html>

MAINTAINING A SINGLE CODEBASE

Until now we have maintained a single code base for an application version that could be deployed to both the web or a native application using PhoneGap. Now we are starting to make modifications that are specific to a PhoneGap version.

In our sample applications, we will simply be removing and adding code to suit our PhoneGap version, and having that code live in a location separate from our previous web-only version. If you are working on a real-world project, however, and find yourself in a similar situation, then look to alternative solutions that allow you to maintain a single code base while still allowing parts of the code to be customized for certain situations.

One way this could be achieved is through implementing a build process using previously mentioned tools like Ant or Rake. The build script selectively combines particular JavaScript files into a single JavaScript file designed for a particular platform distribution.

Another option is through using detection techniques within your JavaScript code. Given that we do not include phonegap.js in our pure web version of the application, we can make some runtime checks around the availability of PhoneGap within our moundz.js file. This allows us to maintain a single version of our core JavaScript files, and simply requires some small tweaks to the application HTML files (which are likely to differ somewhat anyway).

With the changes to our index.html file done, we now turn our attention to the moundz.js file. Here, we will make some modifications to attach to the custom PhoneGap deviceReady event rather than onload. This will ensure that PhoneGap- dependent code will only run once PhoneGap has been properly initialized. Additionally, we will wire in the WebIntent plug-in to monitor for details that will be passed through if the application is launched using a native intent.

MOUNDZ = (function() { ...

/* private functions */ ...

CHAPTER 12: Polishing and Packaging an App for Release

function parseUrlParams(url) { return {}; } // parseUrlParams

var module = { ... };

// bind to the PhoneGap deviceReady event document.addEventListener('deviceReady', function() {

window.plugins.webintent.getDataString(null, function(dataString) { module.init(parseUrlParams(dataString)); }, function() { module.init(); });

}, false);

return module; })();

In the preceding code, we are making two changes to ensure that we properly handle the PhoneGap initialization:

1. Just before we return the module definition at the end of moundz.js, we add an event listener for the deviceReady event that is triggered by PhoneGap. Within this event handler, we ask the WebIntent plug-in to provide us details on any additional data that it has received.

If the Moundz application has been started directly from the launcher, this call will simply pass a null value through; however, if the application has been called from

a URL in the browser (such as our test page), this will be available to the native application.

2. Once we have successfully retrieved the value passed through, this value is passed through a new function called parseUrlParams before being passed on to our init method. For the moment, this function is just a placeholder and simply returns an empty object literal; however, we will add some meaningful code next.

The code we need to add to our parseUrlParams function will allow our application to translate URL query string parameters into a JavaScript object literal, which will then be interpreted in the MOUNDZ.init module function.

The following is the code required to have parseUrlParams perform that operation: function parseUrlParams(url) {

var matches = /^.*?\?(.*)$/.exec(url), keyPairs = matches ? matches[1].split('&') : [], params = {};

// iterate through the key pairs we found

CHAPTER 12: Polishing and Packaging an App for Release

for (var ii = 0; ii < keyPairs.length; ii++) { // split the pair on the = as we are only going to process these var pair = keyPairs[ii].split('=');

// update the parameters params[pair[0]] = pair.length > 1 ? pair[1] : null;

} // for

return params; } // parseUrlParams

This may not be the most readable code in the world, being littered with regular expressions and ternary operators, but its purpose is simple. As previously stated, parseUrlParams needs to extract that query string parameters from a URL and return them in a JavaScript object literal.

For instance, if we passed the following URL to the function: http://test.com/test.htm?param1=foo¶m2=bar, then the parseUrlParams function would return an object literal of the following:

{ param1: 'foo', param2: 'bar'

} Once we have our query string parameters in that format, we can pass them to a

modified version of our MOUNDZ.init function to be processed intelligently. Our modified init function follows:

MOUNDZ = (function() { ...

var module = { ...

init: function(args) {

// initialize the parameters args = $.extend({

zoomLevel: null }, params);

// initialize the geominer bridge geominer = new GEOMINER.Bridge($.extend({

app: 'moundz', login: '#login', returnUrl: 'content://moundz/'

}, args));

$(geominer).bind('authenticated', function(evt) { $('#splash').hide(); $('.noauth').removeClass('noauth');

// run the app run(args.zoomLevel);

CHAPTER 12: Polishing and Packaging an App for Release

// initialize the screen initScreen();

... return module;

})(); Let’s quickly walk through the modifications we are making here; once we are done,

Moundz will be ready to be packaged up for deployment.

1. We change the init function from taking a zoomLevel parameter to taking a more generic args parameter. This args parameter is then used to pass multiple values through (using an object literal) to the constructor of our GEOMINER.Bridge object. This is particularly useful when combined with our earlier code that converted the url parameters for the current web page into an object literal (as we will see in step 3).

2. Next, we update the initialization of GEOMINER.Bridge to include a returnUrl configuration parameter. This returnUrl parameter will be displayed on the page that Geominer presents as the final step in the Twitter authentication process. So now, rather than attempting to close the window, a link will be displayed that we can then click to return to the Moundz native application.

3. Additionally, we pass through the values specified in the args parameter through to the GEOMINER.Bridge using the $.extend function ($.extend is equivalent to jQuery.extend). This is a concise and effective way of passing parameters that

Download from Wow! eBook <www.wowebook.com>

have been sent to our application as part of the Android intent right through to our JavaScript module code.

4. Finally, we modify our call to the run function to remove the mock location that we have been using up until this point while developing the application.

That’s it. The coding, tweaks, and refinements are all done. It’s now time to package this application up for Android Market distribution.