Commit 2bb78b13 authored by Chris Scott's avatar Chris Scott

when creating a stationary-region, sample 5 gps pings and select the most accurate

parent 14acd263
...@@ -16,17 +16,24 @@ ...@@ -16,17 +16,24 @@
NSTimer *backgroundTimer; NSTimer *backgroundTimer;
BOOL isMoving; BOOL isMoving;
NSNumber *maxBackgroundHours; NSNumber *maxBackgroundHours;
CLLocationManager *locationManager; CLLocationManager *locationManager;
CDVLocationData *locationData; CDVLocationData *locationData;
NSMutableArray *locationCache; NSMutableArray *locationCache;
NSDate *suspendedAt; NSDate *suspendedAt;
CLCircularRegion *myRegion; BOOL isAcquiringStationaryLocation;
CLLocation *bestStationaryLocation;
NSInteger stationaryLocationAttempts;
CLCircularRegion *stationaryRegion;
NSInteger stationaryRadius; NSInteger stationaryRadius;
NSInteger distanceFilter; NSInteger distanceFilter;
NSInteger locationTimeout; NSInteger locationTimeout;
NSInteger desiredAccuracy; NSInteger desiredAccuracy;
} }
- (void)pluginInitialize - (void)pluginInitialize
...@@ -36,6 +43,8 @@ ...@@ -36,6 +43,8 @@
locationManager = [[CLLocationManager alloc] init]; locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self; locationManager.delegate = self;
bestStationaryLocation = nil;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onSuspend:) name:UIApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onSuspend:) name:UIApplicationDidEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onResume:) name:UIApplicationWillEnterForegroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onResume:) name:UIApplicationWillEnterForegroundNotification object:nil];
...@@ -82,7 +91,7 @@ ...@@ -82,7 +91,7 @@
break; break;
} }
myRegion = nil; stationaryRegion = nil;
NSLog(@"CDVBackgroundGeoLocation configure"); NSLog(@"CDVBackgroundGeoLocation configure");
NSLog(@" - token: %@", token); NSLog(@" - token: %@", token);
...@@ -164,7 +173,7 @@ ...@@ -164,7 +173,7 @@
[self setPace: isMoving]; [self setPace: isMoving];
} }
} }
/** /**@
* Resume. Turn background off * Resume. Turn background off
*/ */
-(void) onResume:(NSNotification *) notification -(void) onResume:(NSNotification *) notification
...@@ -180,6 +189,8 @@ ...@@ -180,6 +189,8 @@
{ {
NSLog(@"- CDVBackgroundGeoLocation didUpdateLocations (isMoving: %hhd)", isMoving); NSLog(@"- CDVBackgroundGeoLocation didUpdateLocations (isMoving: %hhd)", isMoving);
CLLocation *newLocation = [locations lastObject];
// Handle location updates as normal, code omitted for brevity. // Handle location updates as normal, code omitted for brevity.
// The omitted code should determine whether to reject the location update for being too // The omitted code should determine whether to reject the location update for being too
// old, too close to the previous one, too inaccurate and so forth according to your own // old, too close to the previous one, too inaccurate and so forth according to your own
...@@ -188,6 +199,27 @@ ...@@ -188,6 +199,27 @@
UIApplication *app = [UIApplication sharedApplication]; UIApplication *app = [UIApplication sharedApplication];
// test the age of the location measurement to determine if the measurement is cached
// in most cases you will not want to rely on cached measurements
NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
if (locationAge > 5.0) return;
// test that the horizontal accuracy does not indicate an invalid measurement
if (newLocation.horizontalAccuracy < 0) return;
// test the measurement to see if it is more accurate than the previous measurement
if (isAcquiringStationaryLocation) {
NSLog(@"- Acquiring stationary location, accuracy: %f", newLocation.horizontalAccuracy);
if (![self isBestStationaryLocation:newLocation]) {
return;
}
[locationManager stopUpdatingLocation];
isAcquiringStationaryLocation = NO;
[locationManager startMonitoringSignificantLocationChanges];
[self startMonitoringStationaryRegion:bestStationaryLocation];
}
// Bail out if there's already a background-task in-effect. // Bail out if there's already a background-task in-effect.
if (bgTask != UIBackgroundTaskInvalid) { if (bgTask != UIBackgroundTaskInvalid) {
NSLog(@" Abort: found existing background-task"); NSLog(@" Abort: found existing background-task");
...@@ -199,9 +231,23 @@ ...@@ -199,9 +231,23 @@
}]; }];
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
[self sync:[locations lastObject]]; [self sync:newLocation];
}]; }];
} }
-(BOOL) isBestStationaryLocation:(CLLocation*)location {
stationaryLocationAttempts++;
if (stationaryLocationAttempts == 5) {
return true;
}
if (bestStationaryLocation == nil || bestStationaryLocation.horizontalAccuracy > location.horizontalAccuracy) {
// store the location as the "best effort"
bestStationaryLocation = location;
if (location.horizontalAccuracy <= 5.0) {
return true;
}
}
return false;
}
/** /**
* We are running in the background if this is being executed. * We are running in the background if this is being executed.
* We can't assume normal network access. * We can't assume normal network access.
...@@ -225,11 +271,6 @@ ...@@ -225,11 +271,6 @@
// Build a resultset for javascript callback. // Build a resultset for javascript callback.
CDVPluginResult* result = nil; CDVPluginResult* result = nil;
if (!isMoving) {
if (!myRegion) {
[self startMonitoringStationaryRegion:location];
}
}
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:returnInfo]; result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:returnInfo];
[result setKeepCallbackAsBool:YES]; [result setKeepCallbackAsBool:YES];
...@@ -269,7 +310,7 @@ ...@@ -269,7 +310,7 @@
/** /**
* 1. Turn off significantChanges ApI * 1. Turn off significantChanges ApI
* 2. turn on std. location services * 2. turn on std. location services
* 3. nullify myRegion * 3. nullify stationaryRegion
*/ */
- (void)locationManagerDidResumeLocationUpdates:(CLLocationManager *)manager - (void)locationManagerDidResumeLocationUpdates:(CLLocationManager *)manager
{ {
...@@ -281,18 +322,25 @@ ...@@ -281,18 +322,25 @@
*/ */
- (void)setPace:(BOOL)value - (void)setPace:(BOOL)value
{ {
NSLog(@"- CDVBackgroundGeoLocation setPace %d, myRegion? %d", value, myRegion!=nil); NSLog(@"- CDVBackgroundGeoLocation setPace %d, stationaryRegion? %d", value, stationaryRegion!=nil);
isMoving = value; isMoving = value;
if (value == YES) { if (value == YES) {
if (myRegion != nil) { if (stationaryRegion != nil) {
[locationManager stopMonitoringForRegion:myRegion]; [locationManager stopMonitoringForRegion:stationaryRegion];
myRegion = nil; stationaryRegion = nil;
} }
[locationManager stopMonitoringSignificantLocationChanges]; [locationManager stopMonitoringSignificantLocationChanges];
locationManager.distanceFilter = distanceFilter;
locationManager.desiredAccuracy = desiredAccuracy;
[locationManager startUpdatingLocation]; [locationManager startUpdatingLocation];
} else { } else {
[locationManager stopUpdatingLocation]; // Crank up the GPS power temporarily to get a good fix on our current staionary location in order to set up region-monitoring.
[locationManager startMonitoringSignificantLocationChanges]; bestStationaryLocation = nil;
isAcquiringStationaryLocation = YES;
stationaryLocationAttempts = 0;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
} }
} }
/** /**
...@@ -302,12 +350,12 @@ ...@@ -302,12 +350,12 @@
CLLocationCoordinate2D coord = [location coordinate]; CLLocationCoordinate2D coord = [location coordinate];
NSLog(@"- CDVBackgroundGeoLocation createStationaryRegion (%f,%f)", coord.latitude, coord.longitude); NSLog(@"- CDVBackgroundGeoLocation createStationaryRegion (%f,%f)", coord.latitude, coord.longitude);
if (myRegion != nil) { if (stationaryRegion != nil) {
[locationManager stopMonitoringForRegion:myRegion]; [locationManager stopMonitoringForRegion:stationaryRegion];
} }
myRegion = [[CLCircularRegion alloc] initWithCenter: coord radius:stationaryRadius identifier:@"BackgroundGeoLocation stationary region"]; stationaryRegion = [[CLCircularRegion alloc] initWithCenter: coord radius:stationaryRadius identifier:@"BackgroundGeoLocation stationary region"];
myRegion.notifyOnExit = YES; stationaryRegion.notifyOnExit = YES;
[locationManager startMonitoringForRegion:myRegion]; [locationManager startMonitoringForRegion:stationaryRegion];
} }
// If you don't stopMonitorying when application terminates, the app will be awoken still when a // If you don't stopMonitorying when application terminates, the app will be awoken still when a
...@@ -316,8 +364,8 @@ ...@@ -316,8 +364,8 @@
- (void)applicationWillTerminate:(UIApplication *)application { - (void)applicationWillTerminate:(UIApplication *)application {
[locationManager stopMonitoringSignificantLocationChanges]; [locationManager stopMonitoringSignificantLocationChanges];
[locationManager stopUpdatingLocation]; [locationManager stopUpdatingLocation];
if (myRegion != nil) { if (stationaryRegion != nil) {
[locationManager stopMonitoringForRegion:myRegion]; [locationManager stopMonitoringForRegion:stationaryRegion];
} }
} }
......
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