diff --git a/BackgroundGeolocation/MAURBackgroundGeolocationFacade.m b/BackgroundGeolocation/MAURBackgroundGeolocationFacade.m index 31db9b8..0c1ebda 100644 --- a/BackgroundGeolocation/MAURBackgroundGeolocationFacade.m +++ b/BackgroundGeolocation/MAURBackgroundGeolocationFacade.m @@ -45,7 +45,7 @@ FMDBLogger *sqliteLogger; -@interface MAURBackgroundGeolocationFacade () +@interface MAURBackgroundGeolocationFacade () @end @implementation MAURBackgroundGeolocationFacade { @@ -87,6 +87,7 @@ - (instancetype) init logger->setEnabled(YES); postLocationTask = [[MAURPostLocationTask alloc] init]; + postLocationTask.delegate = self; localNotification = [[UILocalNotification alloc] init]; localNotification.timeZone = [NSTimeZone defaultTimeZone]; @@ -599,4 +600,22 @@ + (MAURLocationTransform _Nullable) locationTransform return [MAURPostLocationTask locationTransform]; } +#pragma mark - MAURPostLocationTaskDelegate + +- (void) postLocationTaskRequestedAbortUpdates:(MAURPostLocationTask *)task +{ + if (_delegate && [_delegate respondsToSelector:@selector(onAbortRequested)]) + { + // We have a delegate, tell it that there's a request. + // It will decide whether to stop or not. + [_delegate onAbortRequested]; + } + else + { + // No delegate, we may be running in the background. + // Let's just stop. + [self stop:nil]; + } +} + @end diff --git a/BackgroundGeolocation/MAURBackgroundSync.h b/BackgroundGeolocation/MAURBackgroundSync.h index eaef62b..a256656 100644 --- a/BackgroundGeolocation/MAURBackgroundSync.h +++ b/BackgroundGeolocation/MAURBackgroundSync.h @@ -10,11 +10,22 @@ #import +@class MAURBackgroundSync; + +@protocol MAURBackgroundSyncDelegate + +@optional +- (void)backgroundSyncRequestedAbortUpdates:(MAURBackgroundSync * _Nonnull)task; + +@end + @interface MAURBackgroundSync : NSObject +@property (nonatomic, weak) id _Nullable delegate; + - (instancetype) init; - (NSString*) status; -- (void) sync:(NSString*)url withTemplate:(id)locationTemplate withHttpHeaders:(NSMutableDictionary*)httpHeaders; +- (void) sync:(NSString * _Nonnull)url withTemplate:(id)locationTemplate withHttpHeaders:(NSMutableDictionary * _Nullable)httpHeaders; - (void) cancel; @end diff --git a/BackgroundGeolocation/MAURBackgroundSync.m b/BackgroundGeolocation/MAURBackgroundSync.m index a20394f..af41d34 100644 --- a/BackgroundGeolocation/MAURBackgroundSync.m +++ b/BackgroundGeolocation/MAURBackgroundSync.m @@ -54,7 +54,7 @@ - (void)cancel } } -- (void) sync:(NSString*)url withTemplate:(id)locationTemplate withHttpHeaders:(NSMutableDictionary*)httpHeaders +- (void) sync:(NSString * _Nonnull)url withTemplate:(id)locationTemplate withHttpHeaders:(NSMutableDictionary * _Nullable)httpHeaders { MAURSQLiteLocationDAO* locationDAO = [MAURSQLiteLocationDAO sharedInstance]; NSArray *locations = [locationDAO getLocationsForSync]; @@ -132,12 +132,28 @@ - (NSString*)status #pragma mark - -- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error { - DDLogInfo(@"Finished uploading task %zu %@: %@ %@, HTTP %ld", (unsigned long)[task taskIdentifier], task.originalRequest.URL, error ?: @"Success", task.response, (long)[(id)task.response statusCode]); + NSInteger statusCode = [(NSHTTPURLResponse *)task.response statusCode]; + + DDLogInfo(@"Finished uploading task %zu %@: %@ %@, HTTP %ld", (unsigned long)[task taskIdentifier], task.originalRequest.URL, error ?: @"Success", task.response, (long)statusCode); + [tasks removeObject:task]; NSURL *fullPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:task.taskDescription]]; [[NSFileManager defaultManager] removeItemAtURL:fullPath error:NULL]; + + if (statusCode == 285) + { + // Okay, but we don't need to continue sending these + DDLogDebug(@"Locations were uploaded to the server, and received an \"HTTP 285 Updates Not Required\""); + + dispatch_async(dispatch_get_main_queue(), ^{ + if (_delegate && [_delegate respondsToSelector:@selector(backgroundSyncRequestedAbortUpdates:)]) + { + [_delegate backgroundSyncRequestedAbortUpdates:self]; + } + }); + } } - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data @@ -145,7 +161,7 @@ - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)data DDLogInfo(@"Response:: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); } -- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error +- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error { DDLogError(@"Autosync failed :( %@", error); } diff --git a/BackgroundGeolocation/MAURPostLocationTask.h b/BackgroundGeolocation/MAURPostLocationTask.h index 656a1c5..3940045 100644 --- a/BackgroundGeolocation/MAURPostLocationTask.h +++ b/BackgroundGeolocation/MAURPostLocationTask.h @@ -12,11 +12,21 @@ #import "MAURConfig.h" #import "MAURLocation.h" +@class MAURPostLocationTask; + +@protocol MAURPostLocationTaskDelegate + +@optional +- (void)postLocationTaskRequestedAbortUpdates:(MAURPostLocationTask * _Nonnull)task; + +@end + @interface MAURPostLocationTask : NSObject -@property (nonatomic, weak) MAURConfig *config; +@property (nonatomic, weak) MAURConfig * _Nullable config; +@property (nonatomic, weak) id _Nullable delegate; -- (void) add:(MAURLocation*)location; +- (void) add:(MAURLocation * _Nonnull)location; - (void) start; - (void) stop; - (void) sync; diff --git a/BackgroundGeolocation/MAURPostLocationTask.m b/BackgroundGeolocation/MAURPostLocationTask.m index eb592f6..1fc4610 100644 --- a/BackgroundGeolocation/MAURPostLocationTask.m +++ b/BackgroundGeolocation/MAURPostLocationTask.m @@ -17,6 +17,12 @@ static NSString * const TAG = @"MAURPostLocationTask"; +@interface MAURPostLocationTask() +{ + +} +@end + @implementation MAURPostLocationTask { Reachability *reach; @@ -37,6 +43,7 @@ - (instancetype) init hasConnectivity = YES; uploader = [[MAURBackgroundSync alloc] init]; + uploader.delegate = self; reach = [Reachability reachabilityWithHostname:@"www.google.com"]; reach.reachableBlock = ^(Reachability *_reach) { @@ -65,7 +72,7 @@ - (void) stop [reach stopNotifier]; } -- (void) add:(MAURLocation*)inLocation +- (void) add:(MAURLocation * _Nonnull)inLocation { // Take this variable on the main thread to be safe MAURLocationTransform locationTransform = s_locationTransform; @@ -130,12 +137,30 @@ - (BOOL) post:(MAURLocation*)location toUrl:(NSString*)url withTemplate:(id)loca NSHTTPURLResponse* urlResponse = nil; [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:outError]; - if ([urlResponse statusCode] == 200 || [urlResponse statusCode] == 201) { + NSInteger statusCode = urlResponse.statusCode; + + if (statusCode == 285) + { + // Okay, but we don't need to continue sending these + + DDLogDebug(@"Location was sent to the server, and received an \"HTTP 285 Updated Not Required\""); + + dispatch_async(dispatch_get_main_queue(), ^{ + if (_delegate && [_delegate respondsToSelector:@selector(postLocationTaskRequestedAbortUpdates:)]) + { + [_delegate postLocationTaskRequestedAbortUpdates:self]; + } + }); + } + + // All 2xx statuses are okay + if (statusCode >= 200 && statusCode < 300) + { return YES; } if (*outError == nil) { - DDLogDebug(@"%@ Server error while posting locations responseCode: %ld", TAG, [urlResponse statusCode]); + DDLogDebug(@"%@ Server error while posting locations responseCode: %ld", TAG, (long)statusCode); } else { DDLogError(@"%@ Error while posting locations %@", TAG, [*outError localizedDescription]); } @@ -162,4 +187,14 @@ + (MAURLocationTransform _Nullable) locationTransform return s_locationTransform; } +#pragma mark - MAURBackgroundSyncDelegate + +- (void)backgroundSyncRequestedAbortUpdates:(MAURBackgroundSync *)task +{ + if (_delegate && [_delegate respondsToSelector:@selector(postLocationTaskRequestedAbortUpdates:)]) + { + [_delegate postLocationTaskRequestedAbortUpdates:self]; + } +} + @end diff --git a/BackgroundGeolocation/MAURProviderDelegate.h b/BackgroundGeolocation/MAURProviderDelegate.h index e855e2f..4f9d8c8 100644 --- a/BackgroundGeolocation/MAURProviderDelegate.h +++ b/BackgroundGeolocation/MAURProviderDelegate.h @@ -43,6 +43,7 @@ typedef NS_ENUM(NSInteger, MAUROperationalMode) { - (void) onLocationPause; - (void) onLocationResume; - (void) onActivityChanged:(MAURActivity*)activity; +- (void) onAbortRequested; - (void) onError:(NSError*)error; @end