Commit d8c5132b authored by Chris Scott's avatar Chris Scott

Merge pull request #72 from christocracy/geofencing

Geofencing
parents a46e882b d8d4a6b7
...@@ -220,14 +220,17 @@ Configures the plugin's parameters (@see following [Config](https://github.com/c ...@@ -220,14 +220,17 @@ Configures the plugin's parameters (@see following [Config](https://github.com/c
``` ```
bgGeo.configure(function(location, taskId) { bgGeo.configure(function(location, taskId) {
var coords = location.coords, try {
timestamp = location.timestamp var coords = location.coords,
latitude = coords.latitude, timestamp = location.timestamp
longitude = coords.longitude, latitude = coords.latitude,
speed = coords.speed; longitude = coords.longitude,
speed = coords.speed;
console.log("A location has arrived:", timestamp, latitude, longitude, speed);
console.log("A location has arrived:", timestamp, latitude, longitude, speed);
} catch(e) {
console.error("An error occurred in my application code", e);
}
// The plugin runs your callback in a background-thread: // The plugin runs your callback in a background-thread:
// you MUST signal to the native plugin when your callback is finished so it can halt the thread. // you MUST signal to the native plugin when your callback is finished so it can halt the thread.
// IF YOU DON'T, iOS WILL KILL YOUR APP // IF YOU DON'T, iOS WILL KILL YOUR APP
...@@ -281,8 +284,11 @@ Your ```callbackFn``` will be executed each time the device has entered stationa ...@@ -281,8 +284,11 @@ Your ```callbackFn``` will be executed each time the device has entered stationa
``` ```
bgGeo.onStationary(function(location, taskId) { bgGeo.onStationary(function(location, taskId) {
console.log('- Device is stopped: ', location.latitude, location.longitude); try {
console.log('- Device is stopped: ', location.latitude, location.longitude);
} catch(e) {
console.error('An error occurred in my application code', e);
}
// The plugin runs your callback in a background-thread: // The plugin runs your callback in a background-thread:
// you MUST signal to the native plugin when your callback is finished so it can halt the thread. // you MUST signal to the native plugin when your callback is finished so it can halt the thread.
// IF YOU DON'T, iOS WILL KILL YOUR APP // IF YOU DON'T, iOS WILL KILL YOUR APP
...@@ -352,8 +358,11 @@ Adds a geofence event-listener. Your supplied callback will be called when any ...@@ -352,8 +358,11 @@ Adds a geofence event-listener. Your supplied callback will be called when any
``` ```
bgGeo.onGeofence(function(params, taskId) { bgGeo.onGeofence(function(params, taskId) {
console.log('A geofence has been entered: ' + identifier); try {
console.log('A geofence has been entered: ' + identifier);
} catch(e) {
console.error('An error occurred in my application code', e);
}
// The plugin runs your callback in a background-thread: // The plugin runs your callback in a background-thread:
// you MUST signal to the native plugin when your callback is finished so it can halt the thread. // you MUST signal to the native plugin when your callback is finished so it can halt the thread.
// IF YOU DON'T, iOS WILL KILL YOUR APP // IF YOU DON'T, iOS WILL KILL YOUR APP
...@@ -364,9 +373,20 @@ bgGeo.onGeofence(function(params, taskId) { ...@@ -364,9 +373,20 @@ bgGeo.onGeofence(function(params, taskId) {
####`getLocations(callbackFn, failureFn)` ####`getLocations(callbackFn, failureFn)`
Fetch all the locations currently stored in native plugin's SQLite database. Your ```callbackFn`` will receive an ```Array``` of locations in the 1st parameter. Eg: Fetch all the locations currently stored in native plugin's SQLite database. Your ```callbackFn`` will receive an ```Array``` of locations in the 1st parameter. Eg:
The `callbackFn` will be executed with following params:
######@param {Array} locations. The list of locations stored in SQLite database.
######@param {Integer} taskId The background taskId which you must send back to the native plugin via `bgGeo.finish(taskId)` in order to signal the end of your background thread.
``` ```
bgGeo.getLocations(function(locations) { bgGeo.getLocations(function(locations, taskId) {
console.log("locations: ", locations); try {
console.log("locations: ", locations);
} catch(e) {
console.error("An error occurred in my application code");
}
bgGeo.finish(taskId);
}); });
``` ```
...@@ -374,10 +394,22 @@ Fetch all the locations currently stored in native plugin's SQLite database. Yo ...@@ -374,10 +394,22 @@ Fetch all the locations currently stored in native plugin's SQLite database. Yo
If the plugin is configured for HTTP with an ```#url``` and ```#autoSync: false```, this method will initiate POSTing the locations currently stored in the native SQLite database to your configured ```#url```. All records in the database will be DELETED. If you configured ```batchSync: true```, all the locations will be sent to your server in a single HTTP POST request, otherwise the plugin will create execute an HTTP post for **each** location in the database (REST-style). Your ```callbackFn``` will be executed and provided with an Array of all the locations from the SQLite database. If you configured the plugin for HTTP (by configuring an `#url`, your `callbackFn` will be executed after the HTTP request(s) have completed. If the plugin failed to sync to your server (possibly because of no network connection), the ```failureFn``` will be called with an ```errorMessage```. If you are **not** using the HTTP features, ```sync``` is the only way to clear the native SQLite datbase. Eg: If the plugin is configured for HTTP with an ```#url``` and ```#autoSync: false```, this method will initiate POSTing the locations currently stored in the native SQLite database to your configured ```#url```. All records in the database will be DELETED. If you configured ```batchSync: true```, all the locations will be sent to your server in a single HTTP POST request, otherwise the plugin will create execute an HTTP post for **each** location in the database (REST-style). Your ```callbackFn``` will be executed and provided with an Array of all the locations from the SQLite database. If you configured the plugin for HTTP (by configuring an `#url`, your `callbackFn` will be executed after the HTTP request(s) have completed. If the plugin failed to sync to your server (possibly because of no network connection), the ```failureFn``` will be called with an ```errorMessage```. If you are **not** using the HTTP features, ```sync``` is the only way to clear the native SQLite datbase. Eg:
Your callback will be provided with the following params
######@param {Array} locations. The list of locations stored in SQLite database.
######@param {Integer} taskId The background taskId which you must send back to the native plugin via `bgGeo.finish(taskId)` in order to signal the end of your background thread.
``` ```
bgGeo.sync(function(locations) { bgGeo.sync(function(locations, taskId) {
// Here are all the locations from the database. The database is now EMPTY. try {
console.log('synced locations: ', locations); // Here are all the locations from the database. The database is now EMPTY.
console.log('synced locations: ', locations);
} catch(e) {
console.error('An error occurred in my application code', e);
}
// Be sure to call finish(taskId) in order to signal the end of the background-thread.
bgGeo.finish(taskId);
}, function(errorMessage) { }, function(errorMessage) {
console.warn('Sync FAILURE: ', errorMessage); console.warn('Sync FAILURE: ', errorMessage);
}); });
......
...@@ -15,7 +15,8 @@ import com.google.android.gms.location.DetectedActivity; ...@@ -15,7 +15,8 @@ import com.google.android.gms.location.DetectedActivity;
import com.transistorsoft.locationmanager.BackgroundGeolocationService; import com.transistorsoft.locationmanager.BackgroundGeolocationService;
import com.google.android.gms.location.Geofence; import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofencingEvent; import com.google.android.gms.location.GeofencingEvent;
//import com.transistorsoft.locationmanager.BackgroundGeolocationService.StationaryLocation; import android.app.AlertDialog;
import android.content.DialogInterface;
import de.greenrobot.event.EventBus; import de.greenrobot.event.EventBus;
import android.app.Activity; import android.app.Activity;
...@@ -23,6 +24,8 @@ import android.content.Intent; ...@@ -23,6 +24,8 @@ import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.location.Location; import android.location.Location;
import android.util.Log; import android.util.Log;
import android.media.AudioManager;
import android.media.ToneGenerator;
public class CDVBackgroundGeolocation extends CordovaPlugin { public class CDVBackgroundGeolocation extends CordovaPlugin {
private static final String TAG = "BackgroundGeolocation"; private static final String TAG = "BackgroundGeolocation";
...@@ -32,6 +35,7 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -32,6 +35,7 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
public static final String ACTION_START = "start"; public static final String ACTION_START = "start";
public static final String ACTION_STOP = "stop"; public static final String ACTION_STOP = "stop";
public static final String ACTION_FINISH = "finish"; public static final String ACTION_FINISH = "finish";
public static final String ACTION_ERROR = "error";
public static final String ACTION_ON_PACE_CHANGE = "onPaceChange"; public static final String ACTION_ON_PACE_CHANGE = "onPaceChange";
public static final String ACTION_CONFIGURE = "configure"; public static final String ACTION_CONFIGURE = "configure";
public static final String ACTION_SET_CONFIG = "setConfig"; public static final String ACTION_SET_CONFIG = "setConfig";
...@@ -64,6 +68,8 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -64,6 +68,8 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
private CallbackContext paceChangeCallback; private CallbackContext paceChangeCallback;
private CallbackContext getGeofencesCallback; private CallbackContext getGeofencesCallback;
private ToneGenerator toneGenerator;
private List<CallbackContext> geofenceCallbacks = new ArrayList<CallbackContext>(); private List<CallbackContext> geofenceCallbacks = new ArrayList<CallbackContext>();
public static boolean isActive() { public static boolean isActive() {
...@@ -76,6 +82,7 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -76,6 +82,7 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
backgroundServiceIntent = new Intent(this.cordova.getActivity(), BackgroundGeolocationService.class); backgroundServiceIntent = new Intent(this.cordova.getActivity(), BackgroundGeolocationService.class);
toneGenerator = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
// Register for events fired by our IntentService "LocationService" // Register for events fired by our IntentService "LocationService"
} }
...@@ -96,6 +103,10 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -96,6 +103,10 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
} else if (ACTION_FINISH.equalsIgnoreCase(action)) { } else if (ACTION_FINISH.equalsIgnoreCase(action)) {
result = true; result = true;
callbackContext.success(); callbackContext.success();
} else if (ACTION_ERROR.equalsIgnoreCase(action)) {
result = true;
this.onError(data.getString(1));
callbackContext.success();
} else if (ACTION_CONFIGURE.equalsIgnoreCase(action)) { } else if (ACTION_CONFIGURE.equalsIgnoreCase(action)) {
result = applyConfig(data); result = applyConfig(data);
if (result) { if (result) {
...@@ -213,11 +224,7 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -213,11 +224,7 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
EventBus.getDefault().post(event); EventBus.getDefault().post(event);
} else if (ACTION_PLAY_SOUND.equalsIgnoreCase(action)) { } else if (ACTION_PLAY_SOUND.equalsIgnoreCase(action)) {
result = true; result = true;
Bundle event = new Bundle(); playSound(data.getInt(0));
event.putString("name", action);
event.putBoolean("request", true);
event.putInt("soundId", data.getInt(0));
EventBus.getDefault().post(event);
callbackContext.success(); callbackContext.success();
} }
return result; return result;
...@@ -350,8 +357,10 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -350,8 +357,10 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
if (ACTION_GET_LOCATIONS.equalsIgnoreCase(name)) { if (ACTION_GET_LOCATIONS.equalsIgnoreCase(name)) {
try { try {
JSONArray json = new JSONArray(event.getString("data")); JSONObject params = new JSONObject();
PluginResult result = new PluginResult(PluginResult.Status.OK, json); params.put("locations", new JSONArray(event.getString("data")));
params.put("taskId", "android-bg-task-id");
PluginResult result = new PluginResult(PluginResult.Status.OK, params);
runInBackground(getLocationsCallback, result); runInBackground(getLocationsCallback, result);
} catch (JSONException e) { } catch (JSONException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
...@@ -363,8 +372,10 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -363,8 +372,10 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
Boolean success = event.getBoolean("success"); Boolean success = event.getBoolean("success");
if (success) { if (success) {
try { try {
JSONArray json = new JSONArray(event.getString("data")); JSONObject params = new JSONObject();
PluginResult result = new PluginResult(PluginResult.Status.OK, json); params.put("locations", new JSONArray(event.getString("data")));
params.put("taskId", "android-bg-task-id");
PluginResult result = new PluginResult(PluginResult.Status.OK, params);
runInBackground(syncCallback, result); runInBackground(syncCallback, result);
} catch (JSONException e) { } catch (JSONException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
...@@ -459,6 +470,12 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -459,6 +470,12 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
} }
} }
private void playSound(int soundId) {
int duration = 1000;
toneGenerator = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
toneGenerator.startTone(soundId, duration);
}
/** /**
* Run a javascript callback in Background * Run a javascript callback in Background
* @param cb * @param cb
...@@ -474,6 +491,27 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -474,6 +491,27 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
} }
} }
private void onError(String error) {
String message = "BG Geolocation caught a Javascript exception while running in background-thread:\n".concat(error);
Log.e(TAG, message);
SharedPreferences settings = this.cordova.getActivity().getSharedPreferences("TSLocationManager", 0);
// Show alert popup with js error
if (settings.contains("debug") && settings.getBoolean("debug", false)) {
playSound(68);
AlertDialog.Builder builder = new AlertDialog.Builder(this.cordova.getActivity());
builder.setMessage(message)
.setCancelable(false)
.setNegativeButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//do things
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
/** /**
* Override method in CordovaPlugin. * Override method in CordovaPlugin.
* Checks to see if it should turn off * Checks to see if it should turn off
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
@interface CDVBackgroundGeolocation : CDVPlugin @interface CDVBackgroundGeolocation : CDVPlugin
@property (nonatomic, strong) NSString* syncCallbackId; @property (nonatomic, strong) NSString* syncCallbackId;
@property (nonatomic) UIBackgroundTaskIdentifier syncTaskId;
@property (nonatomic, strong) NSString* locationCallbackId; @property (nonatomic, strong) NSString* locationCallbackId;
@property (nonatomic, strong) NSMutableArray* geofenceListeners; @property (nonatomic, strong) NSMutableArray* geofenceListeners;
@property (nonatomic, strong) NSMutableArray* stationaryRegionListeners; @property (nonatomic, strong) NSMutableArray* stationaryRegionListeners;
...@@ -18,6 +19,7 @@ ...@@ -18,6 +19,7 @@
- (void) start:(CDVInvokedUrlCommand*)command; - (void) start:(CDVInvokedUrlCommand*)command;
- (void) stop:(CDVInvokedUrlCommand*)command; - (void) stop:(CDVInvokedUrlCommand*)command;
- (void) finish:(CDVInvokedUrlCommand*)command; - (void) finish:(CDVInvokedUrlCommand*)command;
- (void) error:(CDVInvokedUrlCommand*)command;
- (void) onPaceChange:(CDVInvokedUrlCommand*)command; - (void) onPaceChange:(CDVInvokedUrlCommand*)command;
- (void) setConfig:(CDVInvokedUrlCommand*)command; - (void) setConfig:(CDVInvokedUrlCommand*)command;
- (void) addStationaryRegionListener:(CDVInvokedUrlCommand*)command; - (void) addStationaryRegionListener:(CDVInvokedUrlCommand*)command;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
NSDictionary *config; NSDictionary *config;
} }
@synthesize syncCallbackId, locationCallbackId, geofenceListeners, stationaryRegionListeners; @synthesize syncCallbackId, syncTaskId, locationCallbackId, geofenceListeners, stationaryRegionListeners;
- (void)pluginInitialize - (void)pluginInitialize
{ {
...@@ -149,10 +149,16 @@ ...@@ -149,10 +149,16 @@
- (void) onSyncComplete:(NSNotification*)notification - (void) onSyncComplete:(NSNotification*)notification
{ {
NSArray *locations = [notification.userInfo objectForKey:@"locations"]; NSDictionary *params = @{
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:locations]; @"locations": [notification.userInfo objectForKey:@"locations"],
@"taskId": @(syncTaskId)
};
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:params];
[self.commandDelegate sendPluginResult:result callbackId:syncCallbackId]; [self.commandDelegate sendPluginResult:result callbackId:syncCallbackId];
syncCallbackId = nil;
// Ready for another sync task.
syncCallbackId = nil;
syncTaskId = UIBackgroundTaskInvalid;
} }
/** /**
...@@ -170,10 +176,12 @@ ...@@ -170,10 +176,12 @@
* Fetches current stationaryLocation * Fetches current stationaryLocation
*/ */
- (void) getLocations:(CDVInvokedUrlCommand *)command - (void) getLocations:(CDVInvokedUrlCommand *)command
{ {
NSArray* locations = [bgGeo getLocations]; NSDictionary *params = @{
@"locations": [bgGeo getLocations],
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:locations]; @"taskId": @([bgGeo createBackgroundTask])
};
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:params];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
} }
...@@ -187,10 +195,15 @@ ...@@ -187,10 +195,15 @@
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
return; return;
} }
syncCallbackId = command.callbackId;
// Important to set these before we execute #sync since this fires a *very fast* async NSNotification event!
syncCallbackId = command.callbackId;
syncTaskId = [bgGeo createBackgroundTask];
NSArray* locations = [bgGeo sync]; NSArray* locations = [bgGeo sync];
if (locations == nil) { if (locations == nil) {
syncCallbackId = nil; syncCallbackId = nil;
syncTaskId = UIBackgroundTaskInvalid;
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Sync failed. Is there a network connection?"]; CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Sync failed. Is there a network connection?"];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
} }
...@@ -273,6 +286,17 @@ ...@@ -273,6 +286,17 @@
UIBackgroundTaskIdentifier taskId = [[command.arguments objectAtIndex: 0] integerValue]; UIBackgroundTaskIdentifier taskId = [[command.arguments objectAtIndex: 0] integerValue];
[bgGeo stopBackgroundTask:taskId]; [bgGeo stopBackgroundTask:taskId];
} }
/**
* Called by js to signal a caught exception from application code.
*/
-(void) error:(CDVInvokedUrlCommand*)command
{
UIBackgroundTaskIdentifier taskId = [[command.arguments objectAtIndex: 0] integerValue];
NSString *error = [command.arguments objectAtIndex:1];
[bgGeo error:taskId message:error];
}
/** /**
* If you don't stopMonitoring when application terminates, the app will be awoken still when a * If you don't stopMonitoring when application terminates, the app will be awoken still when a
* new location arrives, essentially monitoring the user's location even when they've killed the app. * new location arrives, essentially monitoring the user's location even when they've killed the app.
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
- (NSArray*) getLocations; - (NSArray*) getLocations;
- (UIBackgroundTaskIdentifier) createBackgroundTask; - (UIBackgroundTaskIdentifier) createBackgroundTask;
- (void) stopBackgroundTask:(UIBackgroundTaskIdentifier)taskId; - (void) stopBackgroundTask:(UIBackgroundTaskIdentifier)taskId;
- (void) error:(UIBackgroundTaskIdentifier)taskId message:(NSString*)message;
- (void) onPaceChange:(BOOL)value; - (void) onPaceChange:(BOOL)value;
- (void) setConfig:(NSDictionary*)command; - (void) setConfig:(NSDictionary*)command;
- (NSDictionary*) getStationaryLocation; - (NSDictionary*) getStationaryLocation;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<dict> <dict>
<key>Headers/TSLocationManager.h</key> <key>Headers/TSLocationManager.h</key>
<data> <data>
D1StsS2xjuq9sRvFuNw3O74hUYA= ++tA66F/FJQ/qMup0fGBER20r9U=
</data> </data>
<key>Info.plist</key> <key>Info.plist</key>
<data> <data>
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
<dict> <dict>
<key>Headers/TSLocationManager.h</key> <key>Headers/TSLocationManager.h</key>
<data> <data>
D1StsS2xjuq9sRvFuNw3O74hUYA= ++tA66F/FJQ/qMup0fGBER20r9U=
</data> </data>
<key>Modules/module.modulemap</key> <key>Modules/module.modulemap</key>
<data> <data>
......
...@@ -16,7 +16,9 @@ module.exports = { ...@@ -16,7 +16,9 @@ module.exports = {
* @property {Object} config * @property {Object} config
*/ */
config: {}, config: {},
/**
* @private {Error} error
*/
configure: function(success, failure, config) { configure: function(success, failure, config) {
var me = this; var me = this;
config = config || {}; config = config || {};
...@@ -32,7 +34,9 @@ module.exports = { ...@@ -32,7 +34,9 @@ module.exports = {
if (location.timestamp) { if (location.timestamp) {
location.timestamp = new Date(location.timestamp); location.timestamp = new Date(location.timestamp);
} }
success.call(this, location, taskId); me._runBackgroundTask(taskId, function() {
success.call(this, location, taskId);
});
} }
exec(mySuccess, exec(mySuccess,
failure || function() {}, failure || function() {},
...@@ -65,6 +69,16 @@ module.exports = { ...@@ -65,6 +69,16 @@ module.exports = {
'finish', 'finish',
[taskId]); [taskId]);
}, },
error: function(taskId, message) {
if (!taskId) {
throw "BackgroundGeolocation#error must now be provided with a taskId as 1st param, eg: bgGeo.finish(taskId). taskId is provided by 2nd param in callback";
}
exec(function() {},
function() {},
'BackgroundGeoLocation',
'error',
[taskId, message]);
},
changePace: function(isMoving, success, failure) { changePace: function(isMoving, success, failure) {
exec(success || function() {}, exec(success || function() {},
failure || function() {}, failure || function() {},
...@@ -79,7 +93,7 @@ module.exports = { ...@@ -79,7 +93,7 @@ module.exports = {
* @param {Integer} timeout * @param {Integer} timeout
*/ */
setConfig: function(success, failure, config) { setConfig: function(success, failure, config) {
this.apply(this.config, config); this._apply(this.config, config);
exec(success || function() {}, exec(success || function() {},
failure || function() {}, failure || function() {},
'BackgroundGeoLocation', 'BackgroundGeoLocation',
...@@ -111,7 +125,10 @@ module.exports = { ...@@ -111,7 +125,10 @@ module.exports = {
taskId = params.taskId || 'task-id-undefined'; taskId = params.taskId || 'task-id-undefined';
me.stationaryLocation = location; me.stationaryLocation = location;
success.call(me, location, taskId);
me._runBackgroundTask(taskId, function() {
success.call(me, location, taskId);
}, failure);
}; };
exec(callback, exec(callback,
failure || function() {}, failure || function() {},
...@@ -124,8 +141,12 @@ module.exports = { ...@@ -124,8 +141,12 @@ module.exports = {
throw "BackgroundGeolocation#getLocations requires a success callback"; throw "BackgroundGeolocation#getLocations requires a success callback";
} }
var me = this; var me = this;
var mySuccess = function(locations) { var mySuccess = function(params) {
success.call(this, me._setTimestamp(locations)); var taskId = params.taskId;
var locations = me._setTimestamp(params.locations);
me._runBackgroundTask(taskId, function() {
success.call(me, locations, taskId);
});
} }
exec(mySuccess, exec(mySuccess,
failure || function() {}, failure || function() {},
...@@ -141,8 +162,13 @@ module.exports = { ...@@ -141,8 +162,13 @@ module.exports = {
throw "BackgroundGeolocation#sync requires a success callback"; throw "BackgroundGeolocation#sync requires a success callback";
} }
var me = this; var me = this;
var mySuccess = function(locations) { var mySuccess = function(params) {
success.call(this, me._setTimestamp(locations)); var locations = me._setTimestamp(params.locations);
var taskId = params.taskId;
me._runBackgroundTask(taskId, function() {
success.call(me, locations, taskId);
});
} }
exec(mySuccess, exec(mySuccess,
failure || function() {}, failure || function() {},
...@@ -215,7 +241,10 @@ module.exports = { ...@@ -215,7 +241,10 @@ module.exports = {
var mySuccess = function(params) { var mySuccess = function(params) {
var taskId = params.taskId || 'task-id-undefined'; var taskId = params.taskId || 'task-id-undefined';
delete(params.taskId); delete(params.taskId);
success.call(me, params, taskId);
me._runBackgroundTask(taskId, function() {
success.call(me, params, taskId);
}, failure);
}; };
exec(mySuccess, exec(mySuccess,
failure || function() {}, failure || function() {},
...@@ -257,7 +286,24 @@ module.exports = { ...@@ -257,7 +286,24 @@ module.exports = {
} }
return rs; return rs;
}, },
apply: function(destination, source) { _runBackgroundTask: function(taskId, callback) {
var me = this;
try {
callback.call(this);
} catch(e) {
console.log("*************************************************************************************");
console.error("BackgroundGeolocation caught a Javascript Exception in your application code");
console.log(" while running in a background thread. Auto-finishing background-task:", taskId);
console.log(" to prevent application crash");
console.log("*************************************************************************************");
console.log("STACK:\n", e.stack);
console.error(e);
// And finally, here's our raison d'etre: catching the error in order to ensure background-task is completed.
this.error(taskId, e.message);
}
},
_apply: function(destination, source) {
source = source || {}; source = source || {};
for (var property in source) { for (var property in source) {
if (source.hasOwnProperty(property)) { if (source.hasOwnProperty(property)) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment