Cordova-plugin-background-geolocation: Background Location Storage

Created on 27 Jun 2016  路  26Comments  路  Source: mauron85/cordova-plugin-background-geolocation

Hello,

i always get the same error when trying to call getLocations().

Retrieving locations failed code: 21: message: library routine called out of sequence

Here my config

this.backgroundGeolocation.configure(callbackFn, failureFn, {
                desiredAccuracy: 10,
                stationaryRadius:5,
                distanceFilter: 5,
                activityType: 'Other',
                debug: true, 
                stopOnTerminate: false 
            });
            this.backgroundGeolocation.start();
discussion

Most helpful comment

After some thinking I came to this. Hopefully you will agree on this.

If option.url is not defined, all locations updates are recorded in local db. When App is in foreground or background in addition to storing location in local db, location callback function is triggered. Number of location stored in db is limited by option.maxLocations a never exceeds this number. Instead old locations are replaced by new ones.

When option.url is defined. Location updates are also stored in local db. In addition, each location is also immediately posted to url defined by option.url. If post is successful, the location is marked as deleted in local db. All failed to post locations will be coalesced and send in some time later in one single batch. Batch sync takes place only as per interval defined in IntervalForBatchSync config option..

Is almost same as your suggestion. The difference is that location is stored into db at all times and also when url is set it is also immediately posted to server. Failed to post locations are coalesced and posted as single batch sync.

All 26 comments

Hi, are you using latest version 2.1.2? And did you installed next version in some time before?

Hi, yes unfortunally i was on 2.0.0. I'm now on 2.1.2 and database creation works as expected. But when i switch to Background mode and simulate some locations they aren't stored in the db. You may have any adwise?

Locations are only saved when url option is provided and there is response from server. You can give fake url to test it.

@mauron85 Are you saying that if url option is not defined, then no locations will be saved in local db?

exactly

I can add config option to persist location at all times. If you guys need it.

@mauron85 This is how I would like the plugin to work:

  1. If Url option is not defined, all locations updates when App is killed/Background/Foreground are recorded in local db. When App is in foreground or background in addition to storing location in local db, location callback function is triggered. User would be able to do whatever he wants in the callback func. _(Currently, as far as I know location updates are only stored in local db when App is killed.)_
  2. When Url option is defined. Location updates would still be stored in local db as defined in point 1. In addition, all locations stored in local db would be sent in http post to Url defined. If the response is 200 or successful the stored locations in local db are deleted. Http post takes place only as per interval defined in IntervalForPost config option. Incase, there are no locations in local db no Http Post takes place.

In both above points, user still can utilize backgroundGeolocation.getLocations and delete locations stored in db with backgroundGeolocation.deleteAllLocations

Hope this makes sense.

Now coming to my question earlier, I would like to know whether locations are stored in db when Url option is not defined?

Yes, it does make sense.

Currently, as far as I know location updates are only stored in local db when App is killed.

Now coming to my question earlier, I would like to know whether locations are stored in db when Url option is not defined?

common answer to this is that behaviour was changed in 2.x to only save locations when url is set and http post fail.

Ohk and that is why I was having trouble with locations not being stored in local db when App was killed. Is there a quick fix to this? I would like the plugin to store locations in db when url is not set.

Currently no. Sorry. But I will probably release update soon.

If Url option is not defined, all locations updates when App is killed/Background/Foreground are recorded in local db. When App is in foreground or background in addition to storing location in local db, location callback function is triggered.

ok, it will be possible as soon I implement row limit on location table, so old location records will be replaced by newer ones. Without this db can grow very large, because people might tend to forget clean up db with deleteAllLocations....

After some thinking I came to this. Hopefully you will agree on this.

If option.url is not defined, all locations updates are recorded in local db. When App is in foreground or background in addition to storing location in local db, location callback function is triggered. Number of location stored in db is limited by option.maxLocations a never exceeds this number. Instead old locations are replaced by new ones.

When option.url is defined. Location updates are also stored in local db. In addition, each location is also immediately posted to url defined by option.url. If post is successful, the location is marked as deleted in local db. All failed to post locations will be coalesced and send in some time later in one single batch. Batch sync takes place only as per interval defined in IntervalForBatchSync config option..

Is almost same as your suggestion. The difference is that location is stored into db at all times and also when url is set it is also immediately posted to server. Failed to post locations are coalesced and posted as single batch sync.

Sounds reasonable to me.

@mauron85

If I understand correctly, the difference is when url is defined, locations updates are immediately sent to server, incase of a failed post it is stored in database. These stored locations are then posted to server based on a defined time interval.

I have 2 issues:

  1. Suggestion: Considering case, http post only on interval defined: When a location update is received it stores the location in db. When the interval is hit, the plugin would check if there are any locations in local db to be sent to server -> if yes -> http post locations -> delete locations if successful. This would make the plugin code simple, yet effective in comparison to posting on location updates as well as on defined time interval. (Ppl who may require immediate http post on location update can set a short time interval)
  2. I think http posts on location updates may have scalebility issues. When there are many phones sending locations on update, it may create a load which cannot be judged upfront. However, when http posts are defined as per a minimum time interval we can atleast judge the load.

Basically I've grabbed your description. The very small differences are:

  1. stored into db at all times vs. App is killed/Background/Foreground are recorded in local db
  2. location is immediately posted to server vs. Http post takes place only as per interval defined in IntervalForPos
  3. Failed to post locations are coalesced and posted as single batch sync.

I had just updated my comment. Sorry, took sometime to figure out the difference and posting the edit.

Re-posting last comment, when it was being edited while @mauron85 commented. May have missed this.

If I understand correctly, the difference is when url is defined, locations updates are immediately sent to server, incase of a failed post it is stored in database. These stored locations are then posted to server based on a defined time interval.

I have 2 issues:

Suggestion: Considering case, http post only on interval defined: When a location update is received it stores the location in db. When the interval is hit, the plugin would check if there are any locations in local db to be sent to server -> if yes -> http post locations -> delete locations if successful. This would make the plugin code simple, yet effective in comparison to posting on location updates as well as on defined time interval. (Ppl who may require immediate http post on location update can set a short time interval)

I think http posts on location updates may have scalebility issues. When there are many phones sending locations on update, it may create a load which cannot be judged upfront. However, when http posts are defined as per a minimum time interval we can atleast judge the load.

So once again. My new proposal:

All locations updates are recorded in local db at all times. When App is in foreground or background in addition to storing location in local db, location callback function is triggered. Number of location stored in db is limited by option.maxLocations a never exceeds this number. Instead old locations are replaced by new ones.

  1. When option.url is defined, each location is also immediately posted to url defined by option.url. If post is successful, the location is marked as deleted in local db. All failed to post locations will be coalesced and send in some time later in one single batch. Batch sync takes place only when number of failed to post locations reaches option.syncTreshold.
    Optionally different url for batch sync can be defined by option.syncUrl. If option.syncUrl is not set then option.url will be used instead.
  2. When only option.syncUrl is defined. Locations are send only in single batch, when number of locations reaches option.syncTreshold. (No individual location will be send)

option.syncTreshold - Specifies how many locations will be sent to server at once (default: 100)

All this is implemented in IOS except point 2.

Timed interval location sending will be probably implemented later as it needs significantly more work to implement correctly (at least on iOS).

@mauron85 Is this implemented in 2.2.0?

Yes, it is. Might be some bugs though.

@mauron85 Document suggests that maxLocations, syncThreshold and syncUrl is only available in IOS. Is this an oversight or Android implementation is still under work?

Thanks for pointing out. Will update docs. It's implemented also for Android

@mauron85 cordova plugin add [email protected] doesn't seem to work

That is intentional. Install:

cordova plugin add [email protected]
  1. If option.syncUrl is not set then option.url will be used instead. This needs to be included in the doc I guess.
  2. What happens if after syncThreshold limit post to server fails? I guess plugin takes care that it doesn't post one after other if previous post fails.
  3. Moreover, I don't think getLocations and deleteAllLocations functions makes sense after 2.2.0 with url and syncThreshold set. Or am I missing something?
  1. true. will update docs
  2. basically yes. There is little difference between iOS and Android. On iOS sync locations are prepared in advance so all of them will be eventually posted. Android is not that restrictive, so sync data is prepared just before sync (when network is available). If sync fail, another batch will be created later. Hopefully you can imagine implications of this. Actually this part needs bit real life testing to hunt down all possible bugs.
  3. I was thinking same in the very beginning. But after some time getLocations starts making sense again. You can for example render history of movement on app start. Of course deleteAllLocation has very little sense. Will consider removing in next version.

Hi @mauron85 @shyamal890 ,

I am using the v2.2.5

My "callbackFn" is not calling.
I don't want to send the location to server directly, i want to save it in my local db table.
Then i send those location records to server, whenever device gets internet using one time interval method.

What i am doing wrong here ?
```
function onDeviceReady() {
backgroundGeolocation.configure(callbackFn, failureFn, {
desiredAccuracy: 70,
stationaryRadius: 20,
distanceFilter: 30,
// url: 'http://192.168.81.15:3000/locations',
// httpHeaders: { 'X-FOO': 'bar' },
// maxLocations: 1000,
// Android only section
locationProvider: backgroundGeolocation.provider.ANDROID_ACTIVITY_PROVIDER,
// interval: 60000,
// fastestInterval: 5000,
// activitiesInterval: 10000,
notificationTitle: 'Background tracking',
notificationText: 'Enabled',
notificationIconColor: '#FEDD1E',
notificationIconLarge: 'mappointer_large',
//notificationIconSmall: 'mappointer_small'
});

callbackFn = function(location) {
//alert("inside callback fun "+ location.latitude + ',' + location.longitude);
console.log('[js] BackgroundGeolocation callback: ' + location.latitude + ',' + location.longitude);

var latitude = location.latitude;
var longitude = location.longitude;
var altitude = location.altitude;
var accuracy = location.accuracy;
var altitude_accuracy = null;
var heading = null;
var speed = location.speed;
var timestamp = convertTimestamp(location.time);
var at_logged_on = null;

//This method to save these values in local db table
saveGeoTrackingValues(latitude,longitude,altitude,accuracy,altitude_accuracy,heading,speed,timestamp,at_logged_on);

// backgroundGeolocation.finish();
};

failureFn = function(error) {
    alert('BackgroundGeolocation error');
    console.log('BackgroundGeolocation error');
};

}

$(document).on('click', '#livetrack_start', function(e) {
//alert("outside the service");
backgroundGeolocation.isLocationEnabled(function (enabled) {
if (enabled) {
// alert("location enabled");
backgroundGeolocation.start(

  function () {
    // service started successfully 
    // you should adjust your app UI for example change switch element to indicate 
    // that service is running 

    //  alert("service started");



  },
  function (error) {
    // Tracking has not started because of error 
    // you should adjust your app UI for example change switch element to indicate 
    // that service is not running 



    alert("Error occured : Background Tracking is not started");

    if (error.code === 2) {
      if (window.confirm('Not authorized for location updates. Would you like to open app settings?')) {
        backgroundGeolocation.showAppSettings();
      }
    } else {
      window.alert('Start failed: ' + error.message);  
    }
  }
);

} else {
// Location services are disabled
if (window.confirm('Location is disabled. Would you like to open location settings?')) {
backgroundGeolocation.showLocationSettings();
}
}
});
```

Was this page helpful?
0 / 5 - 0 ratings

Related issues

frankzhangxd picture frankzhangxd  路  6Comments

Ritzlgrmft picture Ritzlgrmft  路  6Comments

vlafranca picture vlafranca  路  6Comments

mahmed-ntd picture mahmed-ntd  路  10Comments

mauron85 picture mauron85  路  4Comments