Commit 18485ae8 authored by lorinmetzger's avatar lorinmetzger

Merge pull request #78 from christocracy/trigger-activities

Trigger activities
parents 88e618db a85d5b90
...@@ -20,7 +20,9 @@ The plugin creates the object `window.plugins.backgroundGeoLocation` with the me ...@@ -20,7 +20,9 @@ The plugin creates the object `window.plugins.backgroundGeoLocation` with the me
`changePace(true) // engages aggressive monitoring immediately` `changePace(true) // engages aggressive monitoring immediately`
`onStationary(callback, fail)` `getCurrentPosition(success, fail)`
`onMotionChange(callback, fail)`
`addGeofence(config, callback, fail)` `addGeofence(config, callback, fail)`
...@@ -89,7 +91,7 @@ function onDeviceReady() { ...@@ -89,7 +91,7 @@ function onDeviceReady() {
// BackgroundGeoLocation is highly configurable. // BackgroundGeoLocation is highly configurable.
bgGeo.configure(callbackFn, failureFn, { bgGeo.configure(callbackFn, failureFn, {
debug: true, // <-- enable this hear sounds for background-geolocation life-cycle. // Geolocation config
desiredAccuracy: 0, desiredAccuracy: 0,
stationaryRadius: 50, stationaryRadius: 50,
distanceFilter: 50, distanceFilter: 50,
...@@ -99,15 +101,19 @@ function onDeviceReady() { ...@@ -99,15 +101,19 @@ function onDeviceReady() {
fastestLocationUpdateInterval: 5000, fastestLocationUpdateInterval: 5000,
activityRecognitionInterval: 10000, activityRecognitionInterval: 10000,
stopTimeout: 0, stopTimeout: 0,
forceReload: true, // <-- [Android] If the user closes the app **while location-tracking is started** , reboot app (WARNING: possibly distruptive to user) activityType: 'AutomotiveNavigation',
// Application config
debug: true, // <-- enable this hear sounds for background-geolocation life-cycle.
forceReloadOnLocationChange: false, // <-- [Android] If the user closes the app **while location-tracking is started** , reboot app when a new location is recorded (WARNING: possibly distruptive to user)
forceReloadOnMotionChange: false, // <-- [Android] If the user closes the app **while location-tracking is started** , reboot app when device changes stationary-state (stationary->moving or vice-versa) --WARNING: possibly distruptive to user)
forceReloadOnGeofence: false, // <-- [Android] If the user closes the app **while location-tracking is started** , reboot app when a geofence crossing occurs --WARNING: possibly distruptive to user)
stopOnTerminate: false, // <-- [Android] Allow the background-service to run headless when user closes the app. stopOnTerminate: false, // <-- [Android] Allow the background-service to run headless when user closes the app.
startOnBoot: true, // <-- [Android] Auto start background-service in headless mode when device is powered-up. startOnBoot: true, // <-- [Android] Auto start background-service in headless mode when device is powered-up.
activityType: 'AutomotiveNavigation',
/** // HTTP / SQLite config
* HTTP Feature: set an url to allow the native background service to POST locations to your server
*/
url: 'http://posttestserver.com/post.php?dir=cordova-background-geolocation', url: 'http://posttestserver.com/post.php?dir=cordova-background-geolocation',
batchSync: false, // <-- [Default: false] Set true to sync locations to server in 1 HTTP request. batchSync: true, // <-- [Default: false] Set true to sync locations to server in a single HTTP request.
autoSync: true, // <-- [Default: true] Set true to sync each location to server as it arrives. autoSync: true, // <-- [Default: true] Set true to sync each location to server as it arrives.
maxDaysToPersist: 1, // <-- Maximum days to persist a location in plugin's SQLite database when HTTP fails maxDaysToPersist: 1, // <-- Maximum days to persist a location in plugin's SQLite database when HTTP fails
headers: { headers: {
...@@ -132,7 +138,8 @@ function onDeviceReady() { ...@@ -132,7 +138,8 @@ function onDeviceReady() {
A fully-featured [SampleApp](https://github.com/christocracy/cordova-background-geolocation-SampleApp) is available in its own public repo. After first cloning that repo, follow the installation instructions in the **README** there. This SampleApp includes a settings-screen allowing you to quickly experiment with all the different settings available for each platform. A fully-featured [SampleApp](https://github.com/christocracy/cordova-background-geolocation-SampleApp) is available in its own public repo. After first cloning that repo, follow the installation instructions in the **README** there. This SampleApp includes a settings-screen allowing you to quickly experiment with all the different settings available for each platform.
![SampleApp](/resources/sampleapp-ionic-home.png "SampleApp") ![Home](/assets/images/iphone/screenshot-iphone5-geofences-framed.png "Home")
![Settings](/assets/images/iphone/screenshot-iphone5-settings-framed.png "Settings")
## Simple Sample Application ## Simple Sample Application
...@@ -268,6 +275,17 @@ Disable background geolocation tracking. ...@@ -268,6 +275,17 @@ Disable background geolocation tracking.
bgGeo.stop(); bgGeo.stop();
``` ```
####`getCurrentPosition(successFn, failureFn)`
Retrieves the current position. This method instructs the native code to fetch exactly one location using maximum power & accuracy. The native code will persist the fetched location to SQLite just as any other location in addition to POSTing to your configured `#url` (if you've enabled the HTTP features). In addition to your supplied `callbackFn`, the plugin will also execute the `callback` provided to `#configure`. Your provided `successFn` will be executed with the same signature as that provided to `#configure`:
######@param {Object} location The Location data
######@param {Integer} taskId The taskId used to send to bgGeo.finish(taskId) in order to signal completion of your callbackFn
```
bgGeo.changePace(true); // <-- Aggressive GPS monitoring immediately engaged.
bgGeo.changePace(false); // <-- Disable aggressive GPS monitoring. Engages stationary-mode.
```
####`changePace(enabled, successFn, failureFn)` ####`changePace(enabled, successFn, failureFn)`
Initiate or cancel immediate background tracking. When set to ```true```, the plugin will begin aggressively tracking the devices Geolocation, bypassing stationary monitoring. If you were making a "Jogging" application, this would be your [Start Workout] button to immediately begin GPS tracking. Send ```false``` to disable aggressive GPS monitoring and return to stationary-monitoring mode. Initiate or cancel immediate background tracking. When set to ```true```, the plugin will begin aggressively tracking the devices Geolocation, bypassing stationary monitoring. If you were making a "Jogging" application, this would be your [Start Workout] button to immediately begin GPS tracking. Send ```false``` to disable aggressive GPS monitoring and return to stationary-monitoring mode.
...@@ -276,7 +294,29 @@ bgGeo.changePace(true); // <-- Aggressive GPS monitoring immediately engaged. ...@@ -276,7 +294,29 @@ bgGeo.changePace(true); // <-- Aggressive GPS monitoring immediately engaged.
bgGeo.changePace(false); // <-- Disable aggressive GPS monitoring. Engages stationary-mode. bgGeo.changePace(false); // <-- Disable aggressive GPS monitoring. Engages stationary-mode.
``` ```
####`onMotionChange(callbackFn, failureFn)`
Your ```callbackFn``` will be executed each time the device has changed-state between **MOVING** or **STATIONARY. The ```callbackFn``` will be provided with a ```Location``` object as the 1st param, with the usual params (```latitude, longitude, accuracy, speed, bearing, altitude```), in addition to a ```taskId``` used to signal that your callback is finished.
######@param {Boolean} isMoving `false` if entered **STATIONARY** mode; `true` if entered **MOVING** mode.
######@param {Object} location The location at the state-change.
######@param {Integer} taskId The taskId used to send to bgGeo.finish(taskId) in order to signal completion of your callbackFn
```
bgGeo.onMotionChange(function(isMoving, location, taskId) {
if (isMoving) {
console.log('Device has just started MOVING', location);
} else {
console.log('Device has just STOPPED', location);
}
bgGeo.finish(taskId);
})
```
####`onStationary(callbackFn, failureFn)` ####`onStationary(callbackFn, failureFn)`
**DEPRECATED** &mdash; Use [onMotionChange](https://github.com/christocracy/cordova-background-geolocation/tree/trigger-activities#onmotionchangecallbackfn-failurefn) instead.
Your ```callbackFn``` will be executed each time the device has entered stationary-monitoring mode. The ```callbackFn``` will be provided with a ```Location``` object as the 1st param, with the usual params (```latitude, longitude, accuracy, speed, bearing, altitude```), in addition to a ```taskId``` used to signal that your callback is finished. Your ```callbackFn``` will be executed each time the device has entered stationary-monitoring mode. The ```callbackFn``` will be provided with a ```Location``` object as the 1st param, with the usual params (```latitude, longitude, accuracy, speed, bearing, altitude```), in addition to a ```taskId``` used to signal that your callback is finished.
######@param {Object} location The Location data ######@param {Object} location The Location data
...@@ -651,13 +691,29 @@ An interval of 0 is allowed, but not recommended, since location updates may be ...@@ -651,13 +691,29 @@ An interval of 0 is allowed, but not recommended, since location updates may be
the desired time between activity detections. Larger values will result in fewer activity detections while improving battery life. A value of 0 will result in activity detections at the fastest possible rate. the desired time between activity detections. Larger values will result in fewer activity detections while improving battery life. A value of 0 will result in activity detections at the fastest possible rate.
####`@param {Integer millis} minimumActivityRecognitionConfidence`
Each activity-recognition-result returned by the API is tagged with a "confidence" level expressed as a %. You can set your desired confidence to trigger a state-change. Defaults to `80`.
####`@param {String} triggerActivities`
These are the comma-delimited list of [activity-names](https://developers.google.com/android/reference/com/google/android/gms/location/DetectedActivity) returned by the `ActivityRecognition` API which will trigger a state-change from **stationary** to **moving**. By default, this list is set to all five **moving-states**: `"in_vehicle, on_bicycle, on_foot, running, walking"`. If you wish, you could configure the plugin to only engage **moving-mode** for vehicles by providing only `"in_vehicle"`.
####`@param {Integer minutes} stopTimeout` ####`@param {Integer minutes} stopTimeout`
The number of miutes to wait before turning off the GPS after the ActivityRecognition System (ARS) detects the device is ```STILL``` (defaults to 0, no timeout). If you don't set a value, the plugin is eager to turn off the GPS ASAP. An example use-case for this configuration is to delay GPS OFF while in a car waiting at a traffic light. The number of miutes to wait before turning off the GPS after the ActivityRecognition System (ARS) detects the device is ```STILL``` (defaults to 0, no timeout). If you don't set a value, the plugin is eager to turn off the GPS ASAP. An example use-case for this configuration is to delay GPS OFF while in a car waiting at a traffic light.
####`@param {Boolean} forceReload` ####`@param {Boolean} forceReloadOnMotionChange`
If the user closes the application while the background-tracking has been started, location-tracking will continue on if ```stopOnTerminate: false```. You may choose to force the foreground application to reload (since this is where your Javascript runs). `forceReloadOnMotionChange: true` will reload the app only when a state-change occurs from **stationary -> moving** or vice-versa. (**WARNING** possibly disruptive to user).
####`@param {Boolean} forceReloadOnLocationChange`
If the user closes the application while the background-tracking has been started, location-tracking will continue on if ```stopOnTerminate: false```. You may choose to force the foreground application to reload (since this is where your Javascript runs). `forceReloadOnLocationChange: true` will reload the app when a new location is recorded.
####`@param {Boolean} forceReloadOnGeofence`
If the user closes the application while the background-tracking has been started, location-tracking will continue on if ```stopOnTerminate: false```. You may choose to force the foreground application to reload (since this is where your Javascript runs) by setting ```foreceReload: true```. This will guarantee that locations are always sent to your Javascript callback (**WARNING** possibly disruptive to user). If the user closes the application while the background-tracking has been started, location-tracking will continue on if ```stopOnTerminate: false```. You may choose to force the foreground application to reload (since this is where your Javascript runs). `forceReloadOnGeolocation: true` will reload the app only when a geofence crossing event has occurred.
####`@param {Boolean} startOnBoot` ####`@param {Boolean} startOnBoot`
......
...@@ -166,9 +166,45 @@ var app = { ...@@ -166,9 +166,45 @@ var app = {
console.log('BackgroundGeoLocation error'); console.log('BackgroundGeoLocation error');
}; };
// Only ios emits this stationary event // BackgroundGeoLocation is highly configurable.
bgGeo.onStationary(function(location, taskId) { bgGeo.configure(callbackFn, failureFn, {
console.log('[js] BackgroundGeoLocation onStationary ' + JSON.stringify(location)); // Geolocation config
desiredAccuracy: 0,
stationaryRadius: 50,
distanceFilter: 50,
disableElasticity: false, // <-- [iOS] Default is 'false'. Set true to disable speed-based distanceFilter elasticity
locationUpdateInterval: 5000,
minimumActivityRecognitionConfidence: 80, // 0-100%. Minimum activity-confidence for a state-change
fastestLocationUpdateInterval: 5000,
activityRecognitionInterval: 10000,
stopTimeout: 0,
activityType: 'AutomotiveNavigation',
// Application config
debug: true, // <-- enable this hear sounds for background-geolocation life-cycle.
forceReloadOnLocationChange: false, // <-- [Android] If the user closes the app **while location-tracking is started** , reboot app when a new location is recorded (WARNING: possibly distruptive to user)
forceReloadOnMotionChange: false, // <-- [Android] If the user closes the app **while location-tracking is started** , reboot app when device changes stationary-state (stationary->moving or vice-versa) --WARNING: possibly distruptive to user)
forceReloadOnGeofence: false, // <-- [Android] If the user closes the app **while location-tracking is started** , reboot app when a geofence crossing occurs --WARNING: possibly distruptive to user)
stopOnTerminate: false, // <-- [Android] Allow the background-service to run headless when user closes the app.
startOnBoot: true, // <-- [Android] Auto start background-service in headless mode when device is powered-up.
// HTTP / SQLite config
url: 'http://posttestserver.com/post.php?dir=cordova-background-geolocation',
batchSync: true, // <-- [Default: false] Set true to sync locations to server in a single HTTP request.
autoSync: true, // <-- [Default: true] Set true to sync each location to server as it arrives.
maxDaysToPersist: 1, // <-- Maximum days to persist a location in plugin's SQLite database when HTTP fails
headers: {
"X-FOO": "bar"
},
params: {
"auth_token": "maybe_your_server_authenticates_via_token_YES?"
}
});
// Listen to motion-state changes (stationary / moving)
bgGeo.onMotionChange(function(isMoving, location, taskId) {
console.log('[js] BackgroundGeoLocation stationary-state changed ' + isMoving);
console.log('[js] location: ' + JSON.stringify(location));
app.setCurrentLocation(location); app.setCurrentLocation(location);
...@@ -177,6 +213,7 @@ var app = { ...@@ -177,6 +213,7 @@ var app = {
// Center ourself on map // Center ourself on map
app.onClickHome(); app.onClickHome();
if (!isMoving) {
if (!app.stationaryRadius) { if (!app.stationaryRadius) {
app.stationaryRadius = new google.maps.Circle({ app.stationaryRadius = new google.maps.Circle({
fillColor: '#cc0000', fillColor: '#cc0000',
...@@ -189,45 +226,15 @@ var app = { ...@@ -189,45 +226,15 @@ var app = {
var center = new google.maps.LatLng(coords.latitude, coords.longitude); var center = new google.maps.LatLng(coords.latitude, coords.longitude);
app.stationaryRadius.setRadius(radius); app.stationaryRadius.setRadius(radius);
app.stationaryRadius.setCenter(center); app.stationaryRadius.setCenter(center);
}
bgGeo.finish(taskId); bgGeo.finish(taskId);
}); });
// BackgroundGeoLocation is highly configurable. // Listen to Geofence events.
bgGeo.configure(callbackFn, failureFn, { bgGeo.onGeofence(function(params, taskId) {
debug: true, // <-- enable this hear sounds for background-geolocation life-cycle. console.log('[js] Geofence crossed: ', params.action, params.identifier);
desiredAccuracy: 0,
stationaryRadius: 50,
distanceFilter: 50,
disableElasticity: false, // <-- [iOS] Default is 'false'. Set true to disable speed-based distanceFilter elasticity
locationUpdateInterval: 5000,
minimumActivityRecognitionConfidence: 80, // 0-100%. Minimum activity-confidence for a state-change
fastestLocationUpdateInterval: 5000,
activityRecognitionInterval: 10000,
stopTimeout: 0,
forceReload: false, // <-- [Android] If the user closes the app **while location-tracking is started** , reboot app (WARNING: possibly distruptive to user)
stopOnTerminate: true, // <-- [Android] Allow the background-service to run headless when user closes the app.
startOnBoot: false, // <-- [Android] Auto start background-service in headless mode when device is powered-up.
activityType: 'AutomotiveNavigation',
/**
* HTTP Feature: set an url to allow the native background service to POST locations to your server
*/
url: 'http://posttestserver.com/post.php?dir=cordova-background-geolocation',
batchSync: true, // <-- [Default: false] Set true to sync locations to server in a single HTTP request.
autoSync: true, // <-- [Default: true] Set true to sync each location to server as it arrives.
maxDaysToPersist: 1, // <-- Maximum days to persist a location in plugin's SQLite database when HTTP fails
headers: {
"X-FOO": "bar"
},
params: {
"auth_token": "maybe_your_server_authenticates_via_token_YES?"
}
});
bgGeo.onGeofence(function(identifier, taskId) {
alert('Enter Geofence: ' + identifier);
console.log('[js] Geofence ENTER: ', identifier, taskId);
bgGeo.finish(taskId); bgGeo.finish(taskId);
}); });
...@@ -240,7 +247,8 @@ var app = { ...@@ -240,7 +247,8 @@ var app = {
identifier: 'MyGeofence', identifier: 'MyGeofence',
radius: 200, radius: 200,
latitude: e.latLng.lat(), latitude: e.latLng.lat(),
longitude: e.latLng.lng() longitude: e.latLng.lng(),
notifyOnEntry: true
}, function() { }, function() {
app.geofence = new google.maps.Circle({ app.geofence = new google.maps.Circle({
fillColor: '#00cc00', fillColor: '#00cc00',
......
...@@ -28,7 +28,7 @@ import android.media.AudioManager; ...@@ -28,7 +28,7 @@ import android.media.AudioManager;
import android.media.ToneGenerator; 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 = "TSLocationManager";
private static CordovaWebView gWebView; private static CordovaWebView gWebView;
public static Boolean forceReload = false; public static Boolean forceReload = false;
...@@ -36,10 +36,12 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -36,10 +36,12 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
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_ERROR = "error";
public static final String ACTION_ON_PACE_CHANGE = "onPaceChange"; public static final String ACTION_CHANGE_PACE = "changePace";
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";
public static final String ACTION_ON_STATIONARY = "addStationaryRegionListener"; public static final String ACTION_ON_STATIONARY = "addStationaryRegionListener";
public static final String ACTION_ADD_MOTION_CHANGE_LISTENER = "addMotionChangeListener";
public static final String ACTION_ON_MOTION_CHANGE = "onMotionChange";
public static final String ACTION_GET_LOCATIONS = "getLocations"; public static final String ACTION_GET_LOCATIONS = "getLocations";
public static final String ACTION_SYNC = "sync"; public static final String ACTION_SYNC = "sync";
public static final String ACTION_GET_ODOMETER = "getOdometer"; public static final String ACTION_GET_ODOMETER = "getOdometer";
...@@ -49,11 +51,12 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -49,11 +51,12 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
public static final String ACTION_GET_GEOFENCES = "getGeofences"; public static final String ACTION_GET_GEOFENCES = "getGeofences";
public static final String ACTION_ON_GEOFENCE = "onGeofence"; public static final String ACTION_ON_GEOFENCE = "onGeofence";
public static final String ACTION_PLAY_SOUND = "playSound"; public static final String ACTION_PLAY_SOUND = "playSound";
public static final String ACTION_ACTIVITY_RELOAD = "activityReload";
private Boolean isEnabled = false; private Boolean isEnabled = false;
private Boolean stopOnTerminate = false; private Boolean stopOnTerminate = false;
private Boolean isMoving = false; private Boolean isMoving = false;
private Boolean isAcquiringCurrentPosition = false;
private Intent backgroundServiceIntent; private Intent backgroundServiceIntent;
private DetectedActivity currentActivity; private DetectedActivity currentActivity;
...@@ -70,7 +73,9 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -70,7 +73,9 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
private ToneGenerator toneGenerator; private ToneGenerator toneGenerator;
private List<CallbackContext> motionChangeCallbacks = new ArrayList<CallbackContext>();
private List<CallbackContext> geofenceCallbacks = new ArrayList<CallbackContext>(); private List<CallbackContext> geofenceCallbacks = new ArrayList<CallbackContext>();
private List<CallbackContext> currentPositionCallbacks = new ArrayList<CallbackContext>();
public static boolean isActive() { public static boolean isActive() {
return gWebView != null; return gWebView != null;
...@@ -114,7 +119,7 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -114,7 +119,7 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
} else { } else {
callbackContext.error("- Configuration error!"); callbackContext.error("- Configuration error!");
} }
} else if (ACTION_ON_PACE_CHANGE.equalsIgnoreCase(action)) { } else if (ACTION_CHANGE_PACE.equalsIgnoreCase(action)) {
if (!isEnabled) { if (!isEnabled) {
Log.w(TAG, "- Cannot change pace while disabled"); Log.w(TAG, "- Cannot change pace while disabled");
result = false; result = false;
...@@ -142,6 +147,9 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -142,6 +147,9 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
} else if (ACTION_ON_STATIONARY.equalsIgnoreCase(action)) { } else if (ACTION_ON_STATIONARY.equalsIgnoreCase(action)) {
result = true; result = true;
this.stationaryCallback = callbackContext; this.stationaryCallback = callbackContext;
} else if (ACTION_ADD_MOTION_CHANGE_LISTENER.equalsIgnoreCase(action)) {
result = true;
this.addMotionChangeListener(callbackContext);
} else if (ACTION_GET_LOCATIONS.equalsIgnoreCase(action)) { } else if (ACTION_GET_LOCATIONS.equalsIgnoreCase(action)) {
result = true; result = true;
Bundle event = new Bundle(); Bundle event = new Bundle();
...@@ -171,12 +179,53 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -171,12 +179,53 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
resetOdometerCallback = callbackContext; resetOdometerCallback = callbackContext;
EventBus.getDefault().post(event); EventBus.getDefault().post(event);
} else if (ACTION_ADD_GEOFENCE.equalsIgnoreCase(action)) { } else if (ACTION_ADD_GEOFENCE.equalsIgnoreCase(action)) {
result = onAddGeofence(data.getJSONObject(0));
if (result) {
callbackContext.success();
} else {
callbackContext.error("Failed to add geofence");
}
} else if (ACTION_REMOVE_GEOFENCE.equalsIgnoreCase(action)) {
result = onRemoveGeofence(data.getString(0));
if (result) {
callbackContext.success();
} else {
callbackContext.error("Failed to add geofence");
}
} else if (ACTION_ON_GEOFENCE.equalsIgnoreCase(action)) {
result = true;
addGeofenceListener(callbackContext);
} else if (ACTION_GET_GEOFENCES.equalsIgnoreCase(action)) {
result = true;
getGeofencesCallback = callbackContext;
Bundle event = new Bundle();
event.putString("name", action);
event.putBoolean("request", true);
EventBus.getDefault().post(event);
} else if (ACTION_PLAY_SOUND.equalsIgnoreCase(action)) {
result = true; result = true;
playSound(data.getInt(0));
callbackContext.success();
} else if (BackgroundGeolocationService.ACTION_GET_CURRENT_POSITION.equalsIgnoreCase(action)) {
result = true;
onGetCurrentPosition(callbackContext);
}
return result;
}
JSONObject config = data.getJSONObject(0); private void onGetCurrentPosition(CallbackContext callbackContext) {
isAcquiringCurrentPosition = true;
addCurrentPositionListener(callbackContext);
Bundle event = new Bundle();
event.putString("name", BackgroundGeolocationService.ACTION_GET_CURRENT_POSITION);
event.putBoolean("request", true);
EventBus.getDefault().post(event);
}
private Boolean onAddGeofence(JSONObject config) {
try { try {
Bundle event = new Bundle(); Bundle event = new Bundle();
event.putString("name", action); event.putString("name", ACTION_ADD_GEOFENCE);
event.putBoolean("request", true); event.putBoolean("request", true);
event.putFloat("radius", (float) config.getLong("radius")); event.putFloat("radius", (float) config.getLong("radius"));
event.putDouble("latitude", config.getDouble("latitude")); event.putDouble("latitude", config.getDouble("latitude"));
...@@ -188,53 +237,68 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -188,53 +237,68 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
if (config.has("notifyOnExit")) { if (config.has("notifyOnExit")) {
event.putBoolean("notifyOnExit", config.getBoolean("notifyOnExit")); event.putBoolean("notifyOnExit", config.getBoolean("notifyOnExit"));
} }
EventBus.getDefault().post(event); EventBus.getDefault().post(event);
callbackContext.success(); return true;
} catch (JSONException e) { } catch (JSONException e) {
Log.w(TAG, e); Log.w(TAG, e);
callbackContext.error("Failed to add geofence"); return false;
result = false; }
} }
} else if (ACTION_REMOVE_GEOFENCE.equalsIgnoreCase(action)) {
result = true;
try {
Bundle event = new Bundle();
event.putString("name", action);
event.putBoolean("request", true);
event.putString("identifier", data.getString(0));
EventBus.getDefault().post(event); private void addGeofenceListener(CallbackContext callbackContext) {
callbackContext.success(); geofenceCallbacks.add(callbackContext);
Activity activity = this.cordova.getActivity();
Intent launchIntent = activity.getIntent();
if (launchIntent.hasExtra("forceReload") && launchIntent.hasExtra("geofencingEvent")) {
try {
JSONObject geofencingEvent = new JSONObject(launchIntent.getStringExtra("geofencingEvent"));
handleGeofencingEvent(geofencingEvent);
} catch (JSONException e) { } catch (JSONException e) {
Log.w(TAG, e); Log.w(TAG, e);
callbackContext.error("Failed to add geofence");
result = false;
} }
} else if (ACTION_ON_GEOFENCE.equalsIgnoreCase(action)) { }
result = true; }
geofenceCallbacks.add(callbackContext); private void addCurrentPositionListener(CallbackContext callbackContext) {
} else if (ACTION_GET_GEOFENCES.equalsIgnoreCase(action)) { currentPositionCallbacks.add(callbackContext);
result = true; }
getGeofencesCallback = callbackContext; private void addMotionChangeListener(CallbackContext callbackContext) {
motionChangeCallbacks.add(callbackContext);
Activity activity = this.cordova.getActivity();
Intent launchIntent = activity.getIntent();
if (launchIntent.hasExtra("forceReload")) {
if (launchIntent.getStringExtra("name").equalsIgnoreCase(ACTION_ON_MOTION_CHANGE)) {
Bundle event = launchIntent.getExtras();
this.onEventMainThread(event);
}
}
}
private Boolean onRemoveGeofence(String identifier) {
Bundle event = new Bundle(); Bundle event = new Bundle();
event.putString("name", action); event.putString("name", ACTION_REMOVE_GEOFENCE);
event.putBoolean("request", true); event.putBoolean("request", true);
event.putString("identifier", identifier);
EventBus.getDefault().post(event); EventBus.getDefault().post(event);
} else if (ACTION_PLAY_SOUND.equalsIgnoreCase(action)) { return true;
result = true;
playSound(data.getInt(0));
callbackContext.success();
}
return result;
} }
private void setEnabled(boolean value) { private void setEnabled(boolean value) {
isEnabled = value; isEnabled = value;
Activity activity = this.cordova.getActivity(); Intent launchIntent = this.cordova.getActivity().getIntent();
if (launchIntent.hasExtra("forceReload") && launchIntent.hasExtra("location")) {
try {
JSONObject location = new JSONObject(launchIntent.getStringExtra("location"));
onLocationChange(location);
} catch (JSONException e) {
Log.w(TAG, e);
}
}
Activity activity = this.cordova.getActivity();
SharedPreferences settings = activity.getSharedPreferences("TSLocationManager", 0); SharedPreferences settings = activity.getSharedPreferences("TSLocationManager", 0);
SharedPreferences.Editor editor = settings.edit(); SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("enabled", isEnabled); editor.putBoolean("enabled", isEnabled);
...@@ -262,7 +326,6 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -262,7 +326,6 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
SharedPreferences.Editor editor = settings.edit(); SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("activityIsActive", true); editor.putBoolean("activityIsActive", true);
editor.putBoolean("isMoving", isMoving);
if (config.has("distanceFilter")) { if (config.has("distanceFilter")) {
editor.putFloat("distanceFilter", config.getInt("distanceFilter")); editor.putFloat("distanceFilter", config.getInt("distanceFilter"));
...@@ -282,6 +345,9 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -282,6 +345,9 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
if (config.has("minimumActivityRecognitionConfidence")) { if (config.has("minimumActivityRecognitionConfidence")) {
editor.putInt("minimumActivityRecognitionConfidence", config.getInt("minimumActivityRecognitionConfidence")); editor.putInt("minimumActivityRecognitionConfidence", config.getInt("minimumActivityRecognitionConfidence"));
} }
if (config.has("triggerActivities")) {
editor.putString("triggerActivities", config.getString("triggerActivities"));
}
if (config.has("stopTimeout")) { if (config.has("stopTimeout")) {
editor.putLong("stopTimeout", config.getLong("stopTimeout")); editor.putLong("stopTimeout", config.getLong("stopTimeout"));
} }
...@@ -298,8 +364,17 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -298,8 +364,17 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
if (config.has("startOnBoot")) { if (config.has("startOnBoot")) {
editor.putBoolean("startOnBoot", config.getBoolean("startOnBoot")); editor.putBoolean("startOnBoot", config.getBoolean("startOnBoot"));
} }
if (config.has("forceReload")) { if (config.has("forceReloadOnLocationChange")) {
editor.putBoolean("forceReload", config.getBoolean("forceReload")); editor.putBoolean("forceReloadOnLocationChange", config.getBoolean("forceReloadOnLocationChange"));
}
if (config.has("forceReload")) { // @deprecated, alias to #forceReloadOnLocationChange
editor.putBoolean("forceReloadOnLocationChange", config.getBoolean("forceReload"));
}
if (config.has("forceReloadOnMotionChange")) {
editor.putBoolean("forceReloadOnMotionChange", config.getBoolean("forceReloadOnMotionChange"));
}
if (config.has("forceReloadOnGeofence")) {
editor.putBoolean("forceReloadOnGeofence", config.getBoolean("forceReloadOnGeofence"));
} }
if (config.has("url")) { if (config.has("url")) {
editor.putString("url", config.getString("url")); editor.putString("url", config.getString("url"));
...@@ -391,7 +466,7 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -391,7 +466,7 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
} else if (ACTION_RESET_ODOMETER.equalsIgnoreCase(name)) { } else if (ACTION_RESET_ODOMETER.equalsIgnoreCase(name)) {
PluginResult result = new PluginResult(PluginResult.Status.OK); PluginResult result = new PluginResult(PluginResult.Status.OK);
resetOdometerCallback.sendPluginResult(result); resetOdometerCallback.sendPluginResult(result);
} else if (ACTION_ON_PACE_CHANGE.equalsIgnoreCase(name)) { } else if (ACTION_CHANGE_PACE.equalsIgnoreCase(name)) {
PluginResult result = new PluginResult(PluginResult.Status.OK); PluginResult result = new PluginResult(PluginResult.Status.OK);
paceChangeCallback.sendPluginResult(result); paceChangeCallback.sendPluginResult(result);
} else if (ACTION_GET_GEOFENCES.equalsIgnoreCase(name)) { } else if (ACTION_GET_GEOFENCES.equalsIgnoreCase(name)) {
...@@ -405,9 +480,28 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -405,9 +480,28 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
PluginResult result = new PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage()); PluginResult result = new PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage());
runInBackground(getGeofencesCallback, result); runInBackground(getGeofencesCallback, result);
} }
} else if (ACTION_ON_MOTION_CHANGE.equalsIgnoreCase(name)) {
this.onMotionChange(event);
} }
} }
private void onMotionChange(Bundle event) {
PluginResult result;
try {
JSONObject params = new JSONObject();
params.put("location", new JSONObject(event.getString("location")));
params.put("isMoving", event.getBoolean("isMoving"));
params.put("taskId", "android-bg-task-id");
result = new PluginResult(PluginResult.Status.OK, params);
} catch (JSONException e) {
e.printStackTrace();
result = new PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage());
}
result.setKeepCallback(true);
for (CallbackContext callback : motionChangeCallbacks) {
runInBackground(callback, result);
}
}
/** /**
* EventBus listener for ARS * EventBus listener for ARS
* @param {ActivityRecognitionResult} result * @param {ActivityRecognitionResult} result
...@@ -422,19 +516,25 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -422,19 +516,25 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
* @param {Location} location * @param {Location} location
*/ */
public void onEventMainThread(Location location) { public void onEventMainThread(Location location) {
PluginResult result; JSONObject locationData = BackgroundGeolocationService.locationToJson(location, currentActivity);
result = new PluginResult(PluginResult.Status.OK, BackgroundGeolocationService.locationToJson(location, currentActivity)); this.onLocationChange(locationData);
}
private void onLocationChange(JSONObject location) {
PluginResult result = new PluginResult(PluginResult.Status.OK, location);
result.setKeepCallback(true); result.setKeepCallback(true);
if (location instanceof com.transistorsoft.locationmanager.BackgroundGeolocationService.StationaryLocation) {
isMoving = false;
if (stationaryCallback != null) {
runInBackground(stationaryCallback, result);
}
} else {
isMoving = true; isMoving = true;
result.setKeepCallback(true); result.setKeepCallback(true);
runInBackground(locationCallback, result); runInBackground(locationCallback, result);
if (isAcquiringCurrentPosition) {
isAcquiringCurrentPosition = false;
for (CallbackContext callback : currentPositionCallbacks) {
result = new PluginResult(PluginResult.Status.OK, location);
result.setKeepCallback(false);
runInBackground(callback, result);
}
currentPositionCallbacks.clear();
} }
} }
/** /**
...@@ -445,30 +545,18 @@ public class CDVBackgroundGeolocation extends CordovaPlugin { ...@@ -445,30 +545,18 @@ public class CDVBackgroundGeolocation extends CordovaPlugin {
if (!geofenceCallbacks.isEmpty()) { if (!geofenceCallbacks.isEmpty()) {
for (Geofence geofence : geofenceEvent.getTriggeringGeofences()) { for (Geofence geofence : geofenceEvent.getTriggeringGeofences()) {
JSONObject params = new JSONObject(); JSONObject params = BackgroundGeolocationService.geofencingEventToJson(geofenceEvent, geofence);
String action = ""; handleGeofencingEvent(params);
int transitionType = geofenceEvent.getGeofenceTransition();
if (transitionType == Geofence.GEOFENCE_TRANSITION_ENTER) {
action = "ENTER";
} else if (transitionType == Geofence.GEOFENCE_TRANSITION_EXIT) {
action = "EXIT";
} else {
action = "DWELL";
} }
try {
params.put("identifier", geofence.getRequestId());
params.put("action", action);
} catch (JSONException e) {
e.printStackTrace();
} }
}
private void handleGeofencingEvent(JSONObject params) {
PluginResult result = new PluginResult(PluginResult.Status.OK, params); PluginResult result = new PluginResult(PluginResult.Status.OK, params);
result.setKeepCallback(true); result.setKeepCallback(true);
for (CallbackContext callback : geofenceCallbacks) { for (CallbackContext callback : geofenceCallbacks) {
runInBackground(callback, result); runInBackground(callback, result);
} }
} }
}
}
private void playSound(int soundId) { private void playSound(int soundId) {
int duration = 1000; int duration = 1000;
......
...@@ -12,17 +12,20 @@ ...@@ -12,17 +12,20 @@
@property (nonatomic, strong) NSString* syncCallbackId; @property (nonatomic, strong) NSString* syncCallbackId;
@property (nonatomic) UIBackgroundTaskIdentifier syncTaskId; @property (nonatomic) UIBackgroundTaskIdentifier syncTaskId;
@property (nonatomic, strong) NSString* locationCallbackId; @property (nonatomic, strong) NSString* locationCallbackId;
@property (nonatomic, strong) NSMutableArray* currentPositionListeners;
@property (nonatomic, strong) NSMutableArray* geofenceListeners; @property (nonatomic, strong) NSMutableArray* geofenceListeners;
@property (nonatomic, strong) NSMutableArray* stationaryRegionListeners; @property (nonatomic, strong) NSMutableArray* stationaryRegionListeners;
@property (nonatomic, strong) NSMutableArray* motionChangeListeners;
- (void) configure:(CDVInvokedUrlCommand*)command; - (void) configure:(CDVInvokedUrlCommand*)command;
- (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) error:(CDVInvokedUrlCommand*)command;
- (void) onPaceChange:(CDVInvokedUrlCommand*)command; - (void) changePace:(CDVInvokedUrlCommand*)command;
- (void) setConfig:(CDVInvokedUrlCommand*)command; - (void) setConfig:(CDVInvokedUrlCommand*)command;
- (void) addStationaryRegionListener:(CDVInvokedUrlCommand*)command; - (void) addStationaryRegionListener:(CDVInvokedUrlCommand*)command;
- (void) addMotionChangeListener:(CDVInvokedUrlCommand*)command;
- (void) getStationaryLocation:(CDVInvokedUrlCommand *)command; - (void) getStationaryLocation:(CDVInvokedUrlCommand *)command;
- (void) getLocations:(CDVInvokedUrlCommand *)command; - (void) getLocations:(CDVInvokedUrlCommand *)command;
- (void) sync:(CDVInvokedUrlCommand *)command; - (void) sync:(CDVInvokedUrlCommand *)command;
...@@ -32,6 +35,7 @@ ...@@ -32,6 +35,7 @@
- (void) removeGeofence:(CDVInvokedUrlCommand *)command; - (void) removeGeofence:(CDVInvokedUrlCommand *)command;
- (void) getGeofences:(CDVInvokedUrlCommand *)command; - (void) getGeofences:(CDVInvokedUrlCommand *)command;
- (void) onGeofence:(CDVInvokedUrlCommand *)command; - (void) onGeofence:(CDVInvokedUrlCommand *)command;
- (void) getCurrentPosition:(CDVInvokedUrlCommand *)command;
- (void) playSound:(CDVInvokedUrlCommand *)command; - (void) playSound:(CDVInvokedUrlCommand *)command;
@end @end
...@@ -10,16 +10,17 @@ ...@@ -10,16 +10,17 @@
NSDictionary *config; NSDictionary *config;
} }
@synthesize syncCallbackId, syncTaskId, locationCallbackId, geofenceListeners, stationaryRegionListeners; @synthesize syncCallbackId, syncTaskId, locationCallbackId, geofenceListeners, stationaryRegionListeners, motionChangeListeners, currentPositionListeners;
- (void)pluginInitialize - (void)pluginInitialize
{ {
bgGeo = [[TSLocationManager alloc] init]; bgGeo = [[TSLocationManager alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onLocationChanged:) name:@"TSLocationManager.location" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onLocationChanged:) name:@"TSLocationManager.location" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onStationaryLocation:) name:@"TSLocationManager.stationary" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMotionChange:) name:@"TSLocationManager.motionchange" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onEnterGeofence:) name:@"TSLocationManager.geofence" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onEnterGeofence:) name:@"TSLocationManager.geofence" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onSyncComplete:) name:@"TSLocationManager.sync" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onSyncComplete:) name:@"TSLocationManager.sync" object:nil];
} }
/** /**
...@@ -78,10 +79,10 @@ ...@@ -78,10 +79,10 @@
* Change pace to moving/stopped * Change pace to moving/stopped
* @param {Boolean} isMoving * @param {Boolean} isMoving
*/ */
- (void) onPaceChange:(CDVInvokedUrlCommand *)command - (void) changePace:(CDVInvokedUrlCommand *)command
{ {
BOOL moving = [[command.arguments objectAtIndex: 0] boolValue]; BOOL moving = [[command.arguments objectAtIndex: 0] boolValue];
[bgGeo onPaceChange:moving]; [bgGeo changePace:moving];
} }
/** /**
...@@ -90,8 +91,9 @@ ...@@ -90,8 +91,9 @@
- (void)onLocationChanged:(NSNotification*)notification { - (void)onLocationChanged:(NSNotification*)notification {
CLLocation *location = [notification.userInfo objectForKey:@"location"]; CLLocation *location = [notification.userInfo objectForKey:@"location"];
NSDictionary *locationData = [bgGeo locationToDictionary:location];
NSDictionary *params = @{ NSDictionary *params = @{
@"location": [bgGeo locationToDictionary:location], @"location": locationData,
@"taskId": @([bgGeo createBackgroundTask]) @"taskId": @([bgGeo createBackgroundTask])
}; };
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:params]; CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:params];
...@@ -100,18 +102,52 @@ ...@@ -100,18 +102,52 @@
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
[self.commandDelegate sendPluginResult:result callbackId:self.locationCallbackId]; [self.commandDelegate sendPluginResult:result callbackId:self.locationCallbackId];
}]; }];
if ([self.currentPositionListeners count]) {
for (NSString *callbackId in self.currentPositionListeners) {
NSDictionary *params = @{
@"location": locationData,
@"taskId": @([bgGeo createBackgroundTask])
};
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:params];
[result setKeepCallbackAsBool:NO];
[self.commandDelegate runInBackground:^{
[self.commandDelegate sendPluginResult:result callbackId:callbackId];
}];
}
[self.currentPositionListeners removeAllObjects];
}
} }
- (void) onStationaryLocation:(NSNotification*)notification
- (void) onMotionChange:(NSNotification*)notification
{ {
if (![self.stationaryRegionListeners count]) { if (![self.stationaryRegionListeners count] && ![self.motionChangeListeners count]) {
return; return;
} }
BOOL isMoving = [[notification.userInfo objectForKey:@"isMoving"] boolValue];
CLLocation *location = [notification.userInfo objectForKey:@"location"]; CLLocation *location = [notification.userInfo objectForKey:@"location"];
NSDictionary *locationData = [bgGeo locationToDictionary:location]; NSDictionary *locationData = [bgGeo locationToDictionary:location];
// @deprecated stationaryRegionListeners in favour of dual-function motionChangeListeners
if (!isMoving) {
for (NSString *callbackId in self.stationaryRegionListeners) { for (NSString *callbackId in self.stationaryRegionListeners) {
NSLog(@"- CALLBACK: %@", callbackId);
NSDictionary *params = @{ NSDictionary *params = @{
@"isMoving": @(isMoving),
@"location": locationData,
@"taskId": @([bgGeo createBackgroundTask])
};
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:params];
[result setKeepCallbackAsBool:YES];
[self.commandDelegate runInBackground:^{
[self.commandDelegate sendPluginResult:result callbackId:callbackId];
}];
}
}
for (NSString *callbackId in self.motionChangeListeners) {
NSDictionary *params = @{
@"isMoving": @(isMoving),
@"location": locationData, @"location": locationData,
@"taskId": @([bgGeo createBackgroundTask]) @"taskId": @([bgGeo createBackgroundTask])
}; };
...@@ -120,7 +156,6 @@ ...@@ -120,7 +156,6 @@
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
[self.commandDelegate sendPluginResult:result callbackId:callbackId]; [self.commandDelegate sendPluginResult:result callbackId:callbackId];
}]; }];
} }
} }
...@@ -149,6 +184,9 @@ ...@@ -149,6 +184,9 @@
- (void) onSyncComplete:(NSNotification*)notification - (void) onSyncComplete:(NSNotification*)notification
{ {
if (syncCallbackId == nil) {
return;
}
NSDictionary *params = @{ NSDictionary *params = @{
@"locations": [notification.userInfo objectForKey:@"locations"], @"locations": [notification.userInfo objectForKey:@"locations"],
@"taskId": @(syncTaskId) @"taskId": @(syncTaskId)
...@@ -217,6 +255,14 @@ ...@@ -217,6 +255,14 @@
[self.stationaryRegionListeners addObject:command.callbackId]; [self.stationaryRegionListeners addObject:command.callbackId];
} }
- (void) addMotionChangeListener:(CDVInvokedUrlCommand*)command
{
if (self.motionChangeListeners == nil) {
self.motionChangeListeners = [[NSMutableArray alloc] init];
}
[self.motionChangeListeners addObject:command.callbackId];
}
- (void) addGeofence:(CDVInvokedUrlCommand*)command - (void) addGeofence:(CDVInvokedUrlCommand*)command
{ {
NSDictionary *cfg = [command.arguments objectAtIndex:0]; NSDictionary *cfg = [command.arguments objectAtIndex:0];
...@@ -270,6 +316,15 @@ ...@@ -270,6 +316,15 @@
[self.geofenceListeners addObject:command.callbackId]; [self.geofenceListeners addObject:command.callbackId];
} }
- (void) getCurrentPosition:(CDVInvokedUrlCommand*)command
{
if (self.currentPositionListeners == nil) {
self.currentPositionListeners = [[NSMutableArray alloc] init];
}
[self.currentPositionListeners addObject:command.callbackId];
[bgGeo updateCurrentPosition];
}
- (void) playSound:(CDVInvokedUrlCommand*)command - (void) playSound:(CDVInvokedUrlCommand*)command
{ {
int soundId = [[command.arguments objectAtIndex:0] integerValue]; int soundId = [[command.arguments objectAtIndex:0] integerValue];
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
- (UIBackgroundTaskIdentifier) createBackgroundTask; - (UIBackgroundTaskIdentifier) createBackgroundTask;
- (void) stopBackgroundTask:(UIBackgroundTaskIdentifier)taskId; - (void) stopBackgroundTask:(UIBackgroundTaskIdentifier)taskId;
- (void) error:(UIBackgroundTaskIdentifier)taskId message:(NSString*)message; - (void) error:(UIBackgroundTaskIdentifier)taskId message:(NSString*)message;
- (void) onPaceChange:(BOOL)value; - (void) changePace:(BOOL)value;
- (void) setConfig:(NSDictionary*)command; - (void) setConfig:(NSDictionary*)command;
- (NSDictionary*) getStationaryLocation; - (NSDictionary*) getStationaryLocation;
- (void) onSuspend:(NSNotification *)notification; - (void) onSuspend:(NSNotification *)notification;
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
- (void) addGeofence:(NSString*)identifier radius:(CLLocationDistance)radius latitude:(CLLocationDegrees)latitude longitude:(CLLocationDegrees)longitude notifyOnEntry:(BOOL)notifyOnEntry notifyOnExit:(BOOL)notifyOnExit; - (void) addGeofence:(NSString*)identifier radius:(CLLocationDistance)radius latitude:(CLLocationDegrees)latitude longitude:(CLLocationDegrees)longitude notifyOnEntry:(BOOL)notifyOnEntry notifyOnExit:(BOOL)notifyOnExit;
- (BOOL) removeGeofence:(NSString*)identifier; - (BOOL) removeGeofence:(NSString*)identifier;
- (NSArray*) getGeofences; - (NSArray*) getGeofences;
- (void) updateCurrentPosition;
- (void) playSound:(SystemSoundID)soundId; - (void) playSound:(SystemSoundID)soundId;
@end @end
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<dict> <dict>
<key>Headers/TSLocationManager.h</key> <key>Headers/TSLocationManager.h</key>
<data> <data>
++tA66F/FJQ/qMup0fGBER20r9U= JKFHIrez0AKQjHebrRIQXFDiIfQ=
</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>
++tA66F/FJQ/qMup0fGBER20r9U= JKFHIrez0AKQjHebrRIQXFDiIfQ=
</data> </data>
<key>Modules/module.modulemap</key> <key>Modules/module.modulemap</key>
<data> <data>
......
...@@ -83,7 +83,7 @@ module.exports = { ...@@ -83,7 +83,7 @@ module.exports = {
exec(success || function() {}, exec(success || function() {},
failure || function() {}, failure || function() {},
'BackgroundGeoLocation', 'BackgroundGeoLocation',
'onPaceChange', 'changePace',
[isMoving]); [isMoving]);
}, },
/** /**
...@@ -112,6 +112,7 @@ module.exports = { ...@@ -112,6 +112,7 @@ module.exports = {
}, },
/** /**
* Add a stationary-region listener. Whenever the devices enters "stationary-mode", your #success callback will be executed with #location param containing #radius of region * Add a stationary-region listener. Whenever the devices enters "stationary-mode", your #success callback will be executed with #location param containing #radius of region
* @deprecated in favour of dual-function #onMotionChange
* @param {Function} success * @param {Function} success
* @param {Function} failure [optional] NOT IMPLEMENTED * @param {Function} failure [optional] NOT IMPLEMENTED
*/ */
...@@ -136,6 +137,35 @@ module.exports = { ...@@ -136,6 +137,35 @@ module.exports = {
'addStationaryRegionListener', 'addStationaryRegionListener',
[]); []);
}, },
/**
* Add a movement-state-change listener. Whenever the devices enters "stationary" or "moving" mode, your #success callback will be executed with #location param containing #radius of region
* @param {Function} success
* @param {Function} failure [optional] NOT IMPLEMENTED
*/
onMotionChange: function(success, failure) {
var me = this;
success = success || function(isMoving, location, taskId) {
me.finish(taskId);
};
var callback = function(params) {
var isMoving = params.isMoving;
var location = params.location;
var taskId = params.taskId || 'task-id-undefined';
if (!isMoving) {
me.stationaryLocation = location;
}
me._runBackgroundTask(taskId, function() {
success.call(me, isMoving, location, taskId);
}, failure);
};
exec(callback,
failure || function() {},
'BackgroundGeoLocation',
'addMotionChangeListener',
[]);
},
getLocations: function(success, failure) { getLocations: function(success, failure) {
if (typeof(success) !== 'function') { if (typeof(success) !== 'function') {
throw "BackgroundGeolocation#getLocations requires a success callback"; throw "BackgroundGeolocation#getLocations requires a success callback";
...@@ -263,6 +293,31 @@ module.exports = { ...@@ -263,6 +293,31 @@ module.exports = {
[]); []);
}, },
/** /**
* Fetch the current position
*/
getCurrentPosition: function(success, failure) {
var me = this;
success = success || function(location, taskId) {
me.finish(taskId);
};
var mySuccess = function(params) {
var location = params.location || params;
var taskId = params.taskId || 'task-id-undefined';
// Transform timestamp to Date instance.
if (location.timestamp) {
location.timestamp = new Date(location.timestamp);
}
me._runBackgroundTask(taskId, function() {
success.call(this, location, taskId);
});
}
exec(mySuccess || function() {},
failure || function() {},
'BackgroundGeoLocation',
'getCurrentPosition',
[]);
},
/**
* Play a system sound. This is totally experimental. * Play a system sound. This is totally experimental.
* iOS http://iphonedevwiki.net/index.php/AudioServices * iOS http://iphonedevwiki.net/index.php/AudioServices
* Android: * Android:
......
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