New! Check out my advanced Ionic tutorials at eliteionic.com

Background Geolocation with Phonegap Build

This is why PhoneGap, and its community, are the best. I do almost all of my mobile app builds exclusively with Sencha Touch and PhoneGap Build, but it seemed that when it came to background Geolocation this wouldn’t be possible.

In the first version of my RunTap application I had used the Geolocation plugin to track users movement, which worked fantastically. The only problem was that when users locked their phone during the run – a perfectly reasonable and expected thing to do – the GPS would stop tracking. No problem I thought, surely there’s some setting to have it run in the background.

No such luck. All of my research seemed to return negative results. The only way people said it was possible through PhoneGap was without PhoneGap Build and to include ‘Background’ Modes in the info.plist. This would required both a Mac and XCode neither of which I have or wish to purchase (no offense to the Mac people out there). The future of RunTap was starting to look grim, until I stumbled across the following third party PhoneGap Build plugin by Christopher Scott of [Transistor Software][1]:

[CDVBackgroundGeoLocation][2]

I didn’t want to jump to any conclusions, but the name alone suggested it might do exactly what I needed. I’ll save you the rest of the story: it works. Here’s how:

1. Include the Background Geolocation Plugin

Of course you’re going to need to add this plugin to your project first. The background plugin includes the normal geolocation plugin as a dependency, so it does not need to be included and you can simply replace this line:

<gap:plugin name="org.apache.cordova.geolocation" />```

with this line:

```html
<gap:plugin name="org.transistorsoft.cordova.background-geolocation" />```

in your config.xml

### 2. Initiate Geolocation as Normal

Whether you're using watchPosition() or getCurrentPosition() you will still need to initiate Geolocation as you normally would. You don't need to change any of your existing configuration to be compatible with the background Geolocation plugin. So in my case, I have watchPosition() set up as follows:

```javascript
var options = {frequency: 3000, enableHighAccuracy: true};
navigator.geolocation.watchPosition(runtap.util.gps.onSuccess, runtap.util.gps.onError, options);

3. Configure Background Geolocation

Configuring the plugin is very simple, we just need to set up some success and failure callback functions in the same way we have for the standard Geolocation. This can be done as follows:

var bgGeo = navigator.plugins.backgroundGeoLocation;

var callbackFn = function(location){
    runtap.util.gps.onBackgroundSuccess(location);
};

var failureFn = function(error){
    alert('Geolocation Error');
};

bgGeo.configure(callbackFn, failureFn, {
    desiredAccuracy: 10,
    stationaryRadius: 10,
    distanceFilter: 30,
    debug: true
});

There is a slight difference here compared to the response of the normal Geolocation. Standard geolocation will receive a position object from which we can retrieve ‘coords’ which will contain both the latitude and longitude values. The background geolocation plugin passes back a location object, which only contains the latitude and longitude values. To handle this slight difference, I just passed the value to a different function called ‘onBackgroundSuccess’ that looks like this:

onBackgroundSuccess: function(location) {

	var R = 6371; // Radius of the earth in km
	var dLat = (location.latitude-this.lastLatitude) * (Math.PI/180);  // deg2rad below
	var dLon = (location.longitude-this.lastLongitude) * (Math.PI/180);
	var a =
	Math.sin(dLat/2) * Math.sin(dLat/2) +
	Math.cos(this.lastLatitude * (Math.PI/180)) * Math.cos(location.latitude * (Math.PI/180)) *
	Math.sin(dLon/2) * Math.sin(dLon/2);
	var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
	var distance = R * c; // Distance in km
	this.lastLatitude = location.latitude;
	this.lastLongitude = location.longitude;

	//Set timer HTML to total distance
	var tracker = Ext.ComponentQuery.query("timer #gps")[0];
	var value = Math.round(runtap.globals.totalDistance * 100) / 100;
	tracker.setHtml(value + "<span style = 'font-size: 18px;'>km</span>");

},

4. Start background geolocation

To start the service you simply need to call:

bgGeo.start();```

and there is also a stop() method that can be executed in the same way. Now if the application is in the foreground it will receive position updates as normal and the 'onSuccess' function will run. But now if the application is in the background it will also receive updates that will be instead sent to 'onBackgroundSuccess' which is essentially the same function, just slightly modified.

### 5. That's it!

I was expecting more steps like having to handle switches between the different services being active but everything just seems to work seamlessly right out of the box.


  

  


 [1]: http://www.transistorsoft.com/
 [2]: https://build.phonegap.com/plugins/513
Check out my latest videos: