Tutorial - Using the HTML5 Geolocation API in PhoneGap Build

It has been nearly a year since my first two posts detailing my struggles with setting up PhoneGap, my frustrations with the sorry state of documentation for the project, and my final resorts towards using PhoneGap Build. You can read all about it here. In that time, plenty of things have changed, but it seems that the documentation for PhoneGap Build is still largely lacking.

I discovered this when attempting to add a bit of geolocation to a new project I was working on within PhoneGap Build. In many ways, this seems very simple. Geolocation is a feature of the latest HTML5 standards, and is such available within any browser that has built support for it, which happens to be pretty much all of them at this point. Each browser's level of support has some variance, but we'll get in to that later. Since PhoneGap is essentially using a mobile browser to display what really boils down to a basic web site, adding in the geolocation feature should be relatively simple. "Should" being the key word there.

The main crux of the complications is that geolocation is a feature that flies in the face of many privacy concerns for web users, and especially for mobile users. The ability to pinpoint exact coordinates of an individual opens up a whole range of questions as to what a particular app or website will be doing with that data. Certainly, nobody wants their precise location broadcast for nefarious purposes.

In fact, the W3 specification for the Geolocation API includes a whole section on security and privacy considerations directly related to this point. I strongly suggest you read this section of the specification if you choose to use geolocation in your apps or websites.

http://www.w3.org/TR/geolocation-API/#security

In order to alleviate some of these privacy concerns, and conform to the standards set out by the W3, browsers have implemented a feature related to the Geolocation API wherein a user is presented with a prompt any time a particular website attempts to access their location information. There's a good chance you've seen this notification on various websites around the web.

Example of geolocation browser request
Example of geolocation browser request

In mobile apps, the ability to use Geolocation is handled in the permissions settings for that app. This varies a bit depending upon the specific platform, but in general the permission set for the app must contain the references to geolocation in order to have access to these features within the app. This makes sure that the user and/or app store reviewers are aware that the app will be using this feature, and can then monitor what the app does with such information. Since PhoneGap apps are considered to be run as native apps, they are required to use these permission settings when defining their access to such features, rather than allowing the user to select an answer at a prompt, as is done in the browser.

Here we get to the crux of the documentation problem in relation to the Geolocation in PhoneGap Build. Knowing that we have to set these permissions in the app's configuration, it is merely a matter of finding out where these settings are modified. In attempting to answer this question, it seems that there is quite a lot of information out there in regards to setting these permissions in the standard installation of PhoneGap, but a lack of info related to PhoneGap Build. Permissions is one area in particular in which PhoneGap Build has a good bit of variance from the standard install. If you happen to take a look around at how these permissions are set in standard PhoneGap, you will notice a lot of platform specific information, with varying config files placed in varying locations. As mentioned in my previous articles, this is due to the fact that while PhoneGap is platform independent, it is not platform agnostic. It is still necessary to create a build specific to the platform you wish to publish on, and each of these different builds will have differing configurations, as specified by the platform's settings.

Now We Get Down To Business


With all of that information out of the way, let's discuss how you actually go about setting up permissions and utilizing HTML5 Geolocation in a PhoneGap Build app.

To start with, make sure that you have the necessary files to create a project for PhoneGap Build. Again, you can reference my previous tutorial on this in order to get yourself set up quickly. This will provide you with the folder structure and basic files needed to begin your project. We're going to start by taking a look at the "config.xml" file, which is located in the "www" directory.

You will find a whole lot of information and settings in this file, and nearly all of it is important to understand at one point or another. Likely future installments of this blog will go in to more detail on some of these preferences. The section we are going to be looking at here is about halfway down the config file, and contains a number of defitions which start with "gap:plugin".

Each of these plugins define different core functionality which can be optionally added in to your PhoneGap Build app. Each of those listed are considered the "Core Plugins", which is those which are included within PhoneGap itself, and not from any third party optional plugins. (Again, this may be discussed at a future date). The problem is that all of these core plugins are included by default, but not all of them will be necessary for your needs. Leaving all of them in will allow you to access them at any time you like, but will trigger a whole slew of app permissions, most of which you will not need. Many users and app store reviewers will look poorly upon an app which requests such broad permissions, especially one which does not actually require all of these permissions. The best method is to only include those which you will be using, and remove any unnecessary plugins.

Of course, when you are just starting out, I recommend commenting out the entire block, and then only uncommenting the specific lines you need. This will ensure that you have the appropriate references to each plugin already in place for quick access. Once you are ready to finalize the app, it would be recommended to clean up the commented out lines, merely for readability and clarity.

So with the whole section commented out, we now need to go in and selectively add back the plugins which we require. Obviously this will be dependent upon your specific needs, but in a presumption of a simple test scenario, we will only be focusing on utilizing the Geolocation features. As such, locate the following line and uncomment it:
<gap:plugin name="org.apache.cordova.geolocation" />
I have had some conflicting information on whether or not a few other plugins are required for inclusion, specifically "device". According to the documentation (as much as we can trust it), this is a reference to the core plugin for PhoneGap. Some have said that since this is the core, it is always required for inclusion. However, in my tests, it seems that this can be omitted without any effect upon the successful compilation and running of your app. It appears that when this line is omitted, PhoneGap Build will automatically include the most recent core plugin that is needed for operation. Instead, it appears that inclusion of this plugin reference has more to do with specifying a particular version of the plugin. While it is not included in any lines of the default config.xml, there is an additional parameter in these settings which allow you to specify version numbers of each plugin. For example:
<gap:plugin name="org.apache.cordova.device" version="0.2.3" />
This would ensure that your app is only using the 0.2.3 version of the "device" core plugin. When this parameter is left out, PhoneGap Build will select the latest version available to it. This can be useful in production apps, to ensure that only tested versions of each plugin are being used, and that each plugin could be upgraded separately, as needed. This is, of course, only in theory, and you will likely find that the core plugins generally need to be upgraded all together, as they are tied in to each very closely. Nonetheless, this knowledge may become important to some of you, and it is assuredly important for utilizing any third party plugins which will have different release cycles than that of the core PhoneGap.

You may notice one other section in the config.xml file which seems to be relevant to our needs:
<preference name="permissions" value="none"/>
While this element does define your app's permissions, it will always be superceded by the needs of any plugins which are included. So enumerating the permissions here will not be necessary so long as we are using the plugins to manage which features the app has access to.

App permissions for geolocation
App permissions for geolocation

I will leave it up to you to review the rest of the information in the config file, and make the appropriate changes pertaining to your app. In particular, you should be updating all of the information prior the "permissions" element, as well as the icon and splash screen image references, as necessary.

Now that we have the information in our config file all set up, we can press forward with getting in to the code which actually access these Geolocation features. It is relatively simple overall, and there are quite a number of good tutorials out there which deal specifically with the Geolocation calls, so I will not spend too much time covering it here, but merely provide you with an overview, and allow you to pursue further research as needed.

The center of the code necessary to get Geolocation information is a single Javascript call.
navigator.geolocation.getCurrentPosition();
That's really (almost) all of it! That simple call will retrieve all of the available geolocation information, and allow you to do with it as you please. If you only execute this line by itself, it will perform the call and gather the information, but does nothing directly with it. In order to access this data, the method receives as an argument a function call. While it is acceptable to use an anonymous function here, I find it best to define the function separately, and reference the function in the argument list. Since the call can sometimes take a few seconds to process, it helps to not tie up the code in that one section, and aids tremendously in readability.

So, we will first define our function that receives this geolocation information, and displays it to the user. The function should define a single input argument, and that argument will contain the object response of the geolocation call. Again, I encourage you to look up other resources to take a look at the complete set of information that is being returned from this call, as there are a number of properties assigned to this object with various values. For our purposes, we will be using the "latitude" and "longitude" properties.

I should quickly note that the response object will have defined properties for the full set of information that is possible to retrieve from the getCurrentPosition call, but not every property will have a value. This will be dependent upon a variety of factors, including support of the system and device for each property. It is best to check each property for a value before you attempt to use, and provide graceful fallback for any values which are not available (contrary to what I am doing in these examples, but hey, they're just short form examples).

Here is the function that we will use:
function disp(pos) {

   $('.lat-view').html(pos.coords.latitude);

   $('.long-view').html(pos.coords.longitude);

}
Again, you will notice that it is pretty simple, but these two calls will access the latitude and longitude values that are retrieved, and display them in two div elements on the page. With the function defined, we can add the reference to this function in to our geolocation call to complete the process.
navigator.geolocation.getCurrentPosition(disp);
You may wish to bind this call to some user action, which will simply require moving it in to the callback of whatever element binding you select for your app.

That about wraps it up. I know this was a particularly long entry, and covered a lot of details you may not immediately see as necessary, but as we all learned in our childhood, Knowledge is Power!

If you want to take a look at a more complete version of these examples, I have a basic app set up on my github page at https://github.com/dstromberg2/getmycoords

Feel free to fork and use as you like.