Background geolocation management

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.

Background geolocation management

Getting ready

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:

Getting ready

Updating your tiapp.xml file

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>

How to do it...

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:

How to do it...

Namespace and app setup

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}
};

Background location options

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";
  1. The 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;
  2. The 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; 
  3. The 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;
  4. The 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;

Building the recipe's UI

The following code snippet describes how to create the UI shown in this recipe's earlier screenshots:

  1. The first step is to create the 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
    });
  2. The next step is to add a 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);
  3. The 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);
  4. The 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);
  5. The 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);

The recipe's assistant methods

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 = {
  1. The 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);
      },
  2. The next method in the 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);
      },
  3. The final method in the 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);
      }
    };

Geolocation events

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);

Background button events

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){
  1. If the module is already active, the recipe will toggle the status to off and stop the module for recording coordinates.
      if(my.bGeo.active(){
        my.bGeo.stop();
      }else{
  2. If the module is off, the recipe will toggle the status to on and start the module for recording coordinates.
        my.bGeo.start();
      }
  3. The startStopButton title is updated to refresh the current status of the module.
      startStopButton.title=((my.bGeo.active()) ? 
      'stop' :'start'),
    });
  4. The click event of refreshButton is used to reload the recorded coordinates to display in the Ti.Map.View.
    refreshButton.addEventListener('click',function(e){
  5. First all map annotations are removed.
      mapView.removeAllAnnotations();
  6. The readCache method is then called to return an array containing all of the recorded coordinates.
      var results = my.bGeo.readCache();
  7. The snippet then loops through the coordinate array using the 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]);
      }
    });
  8. The 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();
    });

iOS app-level events

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:

  1. First check to ensure the recipe is running on an iOS device.
    if(!my.isAndroid){
  2. Next an application-level listener is created on the resumed event. This will be fired when the app is placed in the foreground.
      Ti.App.addEventListener('resumed',function(e){
  3. When the app is moved into the foreground, the recipe checks if the 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();
        }
      });
  4. The next step in managing background services on iOS is to add an application-level event listener to the paused event. The paused event will be fired when the app is placed in the background.
      Ti.App.addEventListener('paused',function(e){
  5. The next snippet demonstrates how to restart the background service, if the Ti.Geo.Background module is active.
        if(my.bGeo.active()){
          my.bGeo.restart();
        }
      });

    Tip

    The restart method must be called when the app is paused, if you wish to continue collecting coordinates in the background.

  6. The following code snippet demonstrates how to stop the 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();
      });
    }

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.159.116