Background geolocation is an important feature of many enterprise applications. The ability to monitor the device's whereabouts while in the background is a powerful feature that can be used for a wide range of activities from personal security to mileage tracking.
The following recipe demonstrates how to use the Ti.Geo.Background
framework to enable background geolocation monitoring. The following screenshots illustrate this recipe running on both an iPhone and an Android device.
This recipe uses a series of CommonJS modules. These modules can be downloaded from the source code provided by the book, or individually through the links provided in the See also section at the end of this recipe. Simply copy the bGeo
folder into the Resources
folder of your project as shown in the following screenshot:
This recipe requires a few updates to your project's tiapp.xml
file. The first update is to provide background geolocation support for iOS devices. The following highlighted UIBackgroundModes
section illustrates the entry required by this recipe:
<ios> <min-ios-ver>5.0</min-ios-ver> <plist> <dict> <key>UIBackgroundModes</key> <array> <string>location</string> </array> <key>NSLocationUsageDescription</key> <string>Demo Geo App</string> </dict> </plist> </ios>
This recipe uses an Android service as a keep alive. The following highlighted section is required for the recipe to create an internal service:
<android xmlns:android= "http://schemas.android.com/apk/res/android"> <services> <service url="bGeo/Ti.Geo.Timer.js" type="interval"/> </services> </android>
The Ti.Geo.Background
CommonJS module utilizes both location manager distance filtering and a keep-alive geo timer. This ensures that a location is recorded both when the device travels a specific distance, or a specified period of time elapses. The Ti.Geo.Background
module manages all geolocation operations and maintains a distance filter so that coordinates are recorded when the device moves pass a specific threshold distance.
The Ti.Geo.Timer
performs two activities. First provides a keep-alive loop required to keep an iOS application active, and second, on a scheduled interval the service records the device's current coordinates. This ensures that coordinates are recorded even if the individual hasn't moved.
The following diagram illustrates the interaction between the different Ti.Geo.Background
components:
Once you have added native and CommonJS modules to your project, you need to create your application namespaces in the app.js
file and use require
to import the modules into your code as the following code snippet demonstrates:
var my = { bGeo : require('bGeo/Ti.Geo.Background'), isAndroid : Ti.Platform.osname === 'android', session:{started:false} };
The Ti.Geo.Background
module provides a series of optional configuration parameters that allow you to tailor the module to your needs. The first configuration parameter is purpose
. This is used by iOS when presenting the location services access prompt to your users.
my.bGeo.purpose = "Demo Background Recipe";
distanceFilter
is a value in meters on how often you wish to have the location manager fire an alert that the location has changed. The following sample is set to 100
and will fire a location-changed event every time the user travels more than 100 meters.my.bGeo.distanceFilter = 100;
trackSignificantLocationChange
setting indicates that the significant location-change tracking should be used on iOS. This method of geolocation reduces battery impact by only firing events when a network change such as a cell tower switch is performed.my.bGeo.trackSignificantLocationChange = true;
minAge
configuration is a threshold of the minimum frequency, in minutes; you wish to receive location updates. In the following example, you will not receive updates any more frequently than every 3 minutes, no matter the distance the individual is moving.my.bGeo.minAge = 3;
maxAge
configuration is a threshold of the maximum amount of time in minutes you wish to go without receiving an update. This is also the threshold used by the Ti.Geo.Timer
to perform a coordinate lookup.my.bGeo.maxAge = 30;
The following code snippet describes how to create the UI shown in this recipe's earlier screenshots:
Ti.UI.Window
upon which all visual elements will be attached.var win = Ti.UI.createWindow({ backgroundColor: '#fff', title: 'Background Geo Recipe', barColor:'#000',fullscreen:false });
Ti.Map.View
to the recipe's Ti.UI.Window
. This will be used to display the coordinates collected while Ti.Geo.Background
is running.var mapView = Ti.Map.createView({ top:80, bottom:0, left:5, right:5, userLocation:false }); win.add(mapView);
startStopButton
is then added to the Ti.UI.Window
. This button will be used to start and stop the Ti.Geo.Background
process.var startStopButton = Ti.UI.createButton({ title:((my.bGeo.active()) ? 'stop' :'start'), top:30, height:40,left:5, width:75 }); win.add(startStopButton);
clearButton
is then added to the Ti.UI.Window
. This button will be used to remove all coordinate information recorded by the Ti.Geo.Background
process.var clearButton = Ti.UI.createButton({ title:'Clear', top:30, height:40,left:85, width:75 }); win.add(clearButton);
refreshButton
is then added to the Ti.UI.Window
. This button will be used to refresh the Ti.Map.View
with the coordinates recorded by the Ti.Geo.Background
process.var refreshButton = Ti.UI.createButton({ title:'Refresh', top:30, height:40,left:165, width:75 }); win.add(refreshButton);
This recipe implements an assistant
object, which contains helper functions to work with and display coordinates collected by the Ti.Geo.Background
module.
var assistant = {
addToMap
is the first method in the assistant
object. This method adds a map pin for each of the coordinate points collected by the Ti.Geo.Background
module.addToMap : function(e){ var pin = Ti.Map.createAnnotation({ latitude:e.latitude, longitude:e.longitude }); mapView.addAnnotation(pin); var region = {latitude:e.latitude, longitude:e.longitude, latitudeDelta:0.04, longitudeDelta:0.04}; mapView.setLocation(region); },
assistant
object is the locationChangeCallback
method. This method is provided as the callback method for the Ti.Geo.Background
module's change
event. The change coordinates are provided to the method's e
parameter. The locationChangeCallback
method then calls the addToMap
method to display the newly gathered coordinate information.locationChangeCallback : function(e){ assistant.addToMap(e); },
assistant
object is the locationErrorCallback
method. This method is provided as the callback method for the Ti.Geo.Background
module's error
event. Error information is provided to the method's e
parameter.locationErrorCallBack : function(e){ alert('Error due to ' + e.message); } };
The Ti.Geo.Background
module has several events. The events used in this recipe are detailed in this section. The change
event is the primary method used in this recipe. This event is fired whenever a location change is generated. The following example demonstrates how to subscribe to this change
event providing the callback method assistant.locationChangeCallback
:
my.bGeo.addEventListener('change', assistant.locationChangeCallback);
The error
event is also used in this recipe to provide an alert to the user when an error has occurred in the module. The following example demonstrates how to subscribe to the error
event providing the callback method assistant.locationErrorCallback
:
my.bGeo.addEventListener('error', assistant.locationErrorCallBack);
This recipe uses a series of buttons to demonstrate how to call the Ti.Geo.Background
module's methods. The startStopButton
click event demonstrates how to start and stop the Ti.Geo.Background
process.
startStopButton.addEventListener('click',function(e){
off
and stop the module for recording coordinates.if(my.bGeo.active(){ my.bGeo.stop(); }else{
on
and start the module for recording coordinates.my.bGeo.start(); }
startStopButton
title is updated to refresh the current status of the module.startStopButton.title=((my.bGeo.active()) ? 'stop' :'start'), });
click
event of refreshButton
is used to reload the recorded coordinates to display in the Ti.Map.View
.refreshButton.addEventListener('click',function(e){
mapView.removeAllAnnotations();
readCache
method is then called to return an array containing all of the recorded coordinates.var results = my.bGeo.readCache();
assistant.addToMap
method to create map pins on the recipe's Ti.Map.View
.for (iLoop=0;iLoop < results.length;iLoop++){ assistant.addToMap(results[iLoop]); } });
click
event of clearButton
is used to remove all recorded coordinate information and clear the Ti.Map.View
of all annotations as the following code snippet demonstrates:clearButton.addEventListener('click',function(e){ my.bGeo.clearCache(); mapView.removeAllAnnotations(); });
The iOS platform does not allow for background services to run while the app is in the foreground. The following block of code demonstrates how to handle this iOS specific scenario:
if(!my.isAndroid){
Ti.App.addEventListener('resumed',function(e){
Ti.Geo.Background
module is active. If active, the module's paused
method must be called to disable the Ti.App.iOS.BackgroundService
, while leaving the location manager active.if(my.bGeo.active()){ my.bGeo.paused(); } });
paused
event. The paused
event will be fired when the app is placed in the background.Ti.App.addEventListener('paused',function(e){
Ti.Geo.Background
module is active.if(my.bGeo.active()){ my.bGeo.restart(); } });
Ti.Geo.Background
module when the application is closed. This also provides a clean shutdown to the background processes and avoids iOS terminating them after approximately 10 minutes.Ti.App.addEventListener('close',function(e){ my.bGeo.stop(); }); }
Ti.Geo.Background
module was used in this recipe to provide cross-platform background location services. For licensing, source code, and to learn more about this project please visit https://github.com/benbahrenburg/Ti.Geo.Background.3.145.179.225