505 lines
18 KiB
Objective-C
Executable File
505 lines
18 KiB
Objective-C
Executable File
//
|
|
// CDVBackgroundGeolocation.h
|
|
//
|
|
// Created by Marian Hello on 04/06/16.
|
|
// Version 2.0.0
|
|
//
|
|
// According to apache license
|
|
//
|
|
// This is class is using code from christocracy cordova-plugin-background-geolocation plugin
|
|
// https://github.com/christocracy/cordova-plugin-background-geolocation
|
|
|
|
#import "CDVBackgroundGeolocation.h"
|
|
#import "MAURConfig.h"
|
|
#import "MAURBackgroundGeolocationFacade.h"
|
|
#import "MAURBackgroundTaskManager.h"
|
|
|
|
static NSString * const TAG = @"CDVBackgroundGeolocation";
|
|
|
|
@implementation CDVBackgroundGeolocation {
|
|
NSString *callbackId;
|
|
MAURConfig *config;
|
|
MAURBackgroundGeolocationFacade* facade;
|
|
|
|
API_AVAILABLE(ios(10.0))
|
|
__weak id<UNUserNotificationCenterDelegate> prevNotificationDelegate;
|
|
}
|
|
|
|
- (void)pluginInitialize
|
|
{
|
|
|
|
facade = [[MAURBackgroundGeolocationFacade alloc] init];
|
|
facade.delegate = self;
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppPause:) name:UIApplicationDidEnterBackgroundNotification object:nil];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppResume:) name:UIApplicationWillEnterForegroundNotification object:nil];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onFinishLaunching:) name:UIApplicationDidFinishLaunchingNotification object:nil];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppTerminate:) name:UIApplicationWillTerminateNotification object:nil];
|
|
}
|
|
|
|
/**
|
|
* configure plugin
|
|
* @param {Number} stationaryRadius
|
|
* @param {Number} distanceFilter
|
|
* @param {Number} locationTimeout
|
|
*/
|
|
- (void) configure:(CDVInvokedUrlCommand*)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"configure");
|
|
[self.commandDelegate runInBackground:^{
|
|
config = [MAURConfig fromDictionary:[command.arguments objectAtIndex:0]];
|
|
|
|
NSError *error = nil;
|
|
CDVPluginResult* result = nil;
|
|
if ([facade configure:config error:&error]) {
|
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
|
|
} else {
|
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self errorToDictionary:error]];
|
|
}
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
}];
|
|
}
|
|
|
|
/**
|
|
* Turn on background geolocation
|
|
* in case of failure it calls error callback from configure method
|
|
* may fire two callback when location services are disabled and when authorization failed
|
|
*/
|
|
- (void) start:(CDVInvokedUrlCommand*)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"start");
|
|
[self.commandDelegate runInBackground:^{
|
|
NSError *error = nil;
|
|
|
|
[facade start:&error];
|
|
if (error == nil) {
|
|
[self sendEvent:@"start"];
|
|
} else {
|
|
[self sendError:error];
|
|
}
|
|
}];
|
|
}
|
|
|
|
/**
|
|
* Turn it off
|
|
*/
|
|
- (void) stop:(CDVInvokedUrlCommand*)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"stop");
|
|
[self.commandDelegate runInBackground:^{
|
|
NSError *error = nil;
|
|
|
|
[facade stop:&error];
|
|
if (error == nil) {
|
|
[self sendEvent:@"stop"];
|
|
} else {
|
|
[self sendError:error];
|
|
}
|
|
}];
|
|
}
|
|
|
|
/**
|
|
* Change
|
|
* @param {Number} operation mode BACKGROUND/FOREGROUND
|
|
*/
|
|
- (void) switchMode:(CDVInvokedUrlCommand *)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"switchMode");
|
|
[self.commandDelegate runInBackground:^{
|
|
MAUROperationalMode mode = [[command.arguments objectAtIndex: 0] intValue];
|
|
[facade switchMode:mode];
|
|
}];
|
|
}
|
|
|
|
- (void) getConfig:(CDVInvokedUrlCommand*)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"getConfig");
|
|
[self.commandDelegate runInBackground:^{
|
|
MAURConfig *config = [facade getConfig];
|
|
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[config toDictionary]];
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
}];
|
|
}
|
|
|
|
- (void) checkStatus:(CDVInvokedUrlCommand *)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"checkStatus");
|
|
[self.commandDelegate runInBackground:^{
|
|
BOOL isRunning = [facade isStarted];
|
|
BOOL locationServicesEnabled = [facade locationServicesEnabled];
|
|
NSInteger authorizationStatus = [facade authorizationStatus];
|
|
|
|
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:3];
|
|
[dict setObject:[NSNumber numberWithBool:isRunning] forKey:@"isRunning"];
|
|
[dict setObject:[NSNumber numberWithBool:locationServicesEnabled] forKey:@"hasPermissions"]; // @deprecated
|
|
[dict setObject:[NSNumber numberWithBool:locationServicesEnabled] forKey:@"locationServicesEnabled"];
|
|
[dict setObject:[NSNumber numberWithInteger:authorizationStatus] forKey:@"authorization"];
|
|
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:dict];
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
}];
|
|
}
|
|
|
|
/**
|
|
* Fetches current stationaryLocation
|
|
*/
|
|
- (void) getStationaryLocation:(CDVInvokedUrlCommand *)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"getStationaryLocation");
|
|
[self.commandDelegate runInBackground:^{
|
|
CDVPluginResult* result = nil;
|
|
|
|
MAURLocation* stationaryLocation = [facade getStationaryLocation];
|
|
if (stationaryLocation) {
|
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[stationaryLocation toDictionary]];
|
|
} else {
|
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:NO];
|
|
}
|
|
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
}];
|
|
}
|
|
|
|
- (void) isLocationEnabled:(CDVInvokedUrlCommand*)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"isLocationEnabled");
|
|
[self.commandDelegate runInBackground:^{
|
|
BOOL isLocationEnabled = [facade locationServicesEnabled];
|
|
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:isLocationEnabled];
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
}];
|
|
}
|
|
|
|
- (void) showAppSettings:(CDVInvokedUrlCommand*)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"showAppSettings");
|
|
[self.commandDelegate runInBackground:^{
|
|
[facade showAppSettings];
|
|
}];
|
|
}
|
|
|
|
- (void) showLocationSettings:(CDVInvokedUrlCommand*)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"showLocationSettings");
|
|
[self.commandDelegate runInBackground:^{
|
|
[facade showLocationSettings];
|
|
}];
|
|
}
|
|
|
|
- (void) getLocations:(CDVInvokedUrlCommand*)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"getLocations");
|
|
[self.commandDelegate runInBackground:^{
|
|
NSArray *locations = [facade getLocations];
|
|
NSMutableArray* dictionaryLocations = [[NSMutableArray alloc] initWithCapacity:[locations count]];
|
|
for (MAURLocation* location in locations) {
|
|
[dictionaryLocations addObject:[location toDictionaryWithId]];
|
|
}
|
|
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:dictionaryLocations];
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
}];
|
|
}
|
|
|
|
- (void) getValidLocations:(CDVInvokedUrlCommand*)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"getValidLocations");
|
|
[self.commandDelegate runInBackground:^{
|
|
NSArray *locations = [facade getValidLocations];
|
|
NSMutableArray* dictionaryLocations = [[NSMutableArray alloc] initWithCapacity:[locations count]];
|
|
for (MAURLocation* location in locations) {
|
|
[dictionaryLocations addObject:[location toDictionaryWithId]];
|
|
}
|
|
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:dictionaryLocations];
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
}];
|
|
}
|
|
|
|
- (void) deleteLocation:(CDVInvokedUrlCommand*)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"deleteLocation");
|
|
[self.commandDelegate runInBackground:^{
|
|
NSError *error = nil;
|
|
int locationId = [[command.arguments objectAtIndex: 0] intValue];
|
|
BOOL success = [facade deleteLocation:[[NSNumber alloc] initWithInt:locationId] error:&error];
|
|
CDVPluginResult* result;
|
|
if (success) {
|
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
|
|
} else {
|
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self errorToDictionary:error]];
|
|
}
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
}];
|
|
}
|
|
|
|
- (void) deleteAllLocations:(CDVInvokedUrlCommand*)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"deleteAllLocations");
|
|
[self.commandDelegate runInBackground:^{
|
|
NSError *error = nil;
|
|
BOOL success = [facade deleteAllLocations:&error];
|
|
CDVPluginResult* result;
|
|
if (success) {
|
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
|
|
} else {
|
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self errorToDictionary:error]];
|
|
}
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
}];
|
|
}
|
|
|
|
- (void) getCurrentLocation:(CDVInvokedUrlCommand*)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"getCurrentLocation");
|
|
[self.commandDelegate runInBackground:^{
|
|
NSError *error = nil;
|
|
NSArray *args = command.arguments;
|
|
int timeout = [args objectAtIndex: 0] == [NSNull null] ? INT_MAX : [[args objectAtIndex: 0] intValue];
|
|
long maximumAge = [args objectAtIndex: 1] == [NSNull null] ? LONG_MAX : [[args objectAtIndex: 1] longValue];
|
|
BOOL enableHighAccuracy = [args objectAtIndex: 2] == [NSNull null] ? NO : [[args objectAtIndex: 2] boolValue];
|
|
|
|
MAURLocation *location = [facade getCurrentLocation:timeout maximumAge:maximumAge enableHighAccuracy:enableHighAccuracy error:&error];
|
|
CDVPluginResult* result;
|
|
if (location != nil) {
|
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[location toDictionary]];
|
|
} else {
|
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self errorToDictionary:error]];
|
|
}
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
}];
|
|
}
|
|
|
|
- (void) getLogEntries:(CDVInvokedUrlCommand*)command
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"getLogEntries");
|
|
[self.commandDelegate runInBackground:^{
|
|
NSArray *args = command.arguments;
|
|
NSInteger limit = [args objectAtIndex: 0] == [NSNull null]
|
|
? 0 : [[args objectAtIndex: 0] integerValue];
|
|
NSInteger entryId = [args objectAtIndex: 1] == [NSNull null]
|
|
? 0 : [[args objectAtIndex: 1] integerValue];
|
|
NSString *minLogLevel = [args objectAtIndex: 2] == [NSNull null]
|
|
? @"DEBUG" : [args objectAtIndex: 2];
|
|
|
|
NSArray *logs = [facade getLogEntries:limit fromLogEntryId:entryId minLogLevelFromString:minLogLevel];
|
|
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:logs];
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
}];
|
|
}
|
|
|
|
- (void) startTask:(CDVInvokedUrlCommand*)command
|
|
{
|
|
NSUInteger taskKey = [[MAURBackgroundTaskManager sharedTasks] beginTask];
|
|
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsNSUInteger:taskKey];
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
}
|
|
|
|
- (void) endTask:(CDVInvokedUrlCommand*)command
|
|
{
|
|
int taskKey = [[command.arguments objectAtIndex: 0] intValue];
|
|
[[MAURBackgroundTaskManager sharedTasks] endTaskWithKey:taskKey];
|
|
}
|
|
|
|
- (void) forceSync:(CDVInvokedUrlCommand*)command
|
|
{
|
|
[facade forceSync];
|
|
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
}
|
|
|
|
- (void) addEventListener:(CDVInvokedUrlCommand*)command
|
|
{
|
|
callbackId = command.callbackId;
|
|
}
|
|
|
|
- (void) removeEventListener:(CDVInvokedUrlCommand*)command
|
|
{
|
|
callbackId = nil;
|
|
}
|
|
|
|
-(void) sendEvent:(NSString*)name
|
|
{
|
|
if (callbackId == nil) {
|
|
return;
|
|
}
|
|
|
|
NSDictionary *message = [[NSDictionary alloc] initWithObjectsAndKeys:[NSString stringWithFormat:@"%@", name], @"name", nil];
|
|
CDVPluginResult* cordovaResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:message];
|
|
[cordovaResult setKeepCallbackAsBool:YES];
|
|
[self.commandDelegate sendPluginResult:cordovaResult callbackId:callbackId];
|
|
}
|
|
|
|
-(void) sendEvent:(NSString*)name resultAsNumber:(NSNumber*)result
|
|
{
|
|
if (callbackId == nil) {
|
|
return;
|
|
}
|
|
|
|
NSDictionary *message = [[NSDictionary alloc] initWithObjectsAndKeys:
|
|
[NSString stringWithFormat:@"%@", name], @"name",
|
|
result, @"payload",
|
|
nil];
|
|
CDVPluginResult* cordovaResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:message];
|
|
[cordovaResult setKeepCallbackAsBool:YES];
|
|
[self.commandDelegate sendPluginResult:cordovaResult callbackId:callbackId];
|
|
}
|
|
|
|
-(void) sendEvent:(NSString*)name result:(id)result
|
|
{
|
|
if (callbackId == nil) {
|
|
return;
|
|
}
|
|
|
|
NSDictionary *message = [[NSDictionary alloc] initWithObjectsAndKeys:
|
|
[NSString stringWithFormat:@"%@", name], @"name",
|
|
result, @"payload",
|
|
nil];
|
|
CDVPluginResult* cordovaResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:message];
|
|
[cordovaResult setKeepCallbackAsBool:YES];
|
|
[self.commandDelegate sendPluginResult:cordovaResult callbackId:callbackId];
|
|
}
|
|
|
|
- (void) sendError:(NSError*)error
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"onError");
|
|
if (callbackId == nil) {
|
|
return;
|
|
}
|
|
|
|
CDVPluginResult* cordovaResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self errorToDictionary:error]];
|
|
[cordovaResult setKeepCallbackAsBool:YES];
|
|
[self.commandDelegate sendPluginResult:cordovaResult callbackId:callbackId];
|
|
}
|
|
|
|
- (NSDictionary*) errorToDictionary:(NSError*)error
|
|
{
|
|
NSDictionary *userInfo = [error userInfo];
|
|
NSString *errorMessage = [error localizedDescription];
|
|
if (errorMessage == nil) {
|
|
errorMessage = [[userInfo objectForKey:NSUnderlyingErrorKey] localizedDescription];
|
|
}
|
|
return @{ @"code": [NSNumber numberWithLong:error.code], @"message": errorMessage};
|
|
}
|
|
|
|
- (void) onAuthorizationChanged:(MAURLocationAuthorizationStatus)authStatus
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"onAuthorizationChanged");
|
|
[self sendEvent:@"authorization" resultAsNumber:[NSNumber numberWithInt:authStatus]];
|
|
}
|
|
|
|
- (void) onLocationChanged:(MAURLocation*)location
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"onLocationChanged");
|
|
[self sendEvent:@"location" result:[location toDictionaryWithId]];
|
|
}
|
|
|
|
- (void) onStationaryChanged:(MAURLocation*)location
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"onStationaryChanged");
|
|
[self sendEvent:@"stationary" result:[location toDictionaryWithId]];
|
|
}
|
|
|
|
- (void) onLocationPause
|
|
{
|
|
NSLog(@"%@ %@", TAG, @"location updates paused");
|
|
[self sendEvent:@"stop"];
|
|
}
|
|
|
|
- (void) onLocationResume
|
|
{
|
|
NSLog(@"%@ %@", TAG, @"location updates resumed");
|
|
[self sendEvent:@"start"];
|
|
}
|
|
|
|
- (void) onActivityChanged:(MAURActivity *)activity
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"onActivityChanged");
|
|
[self sendEvent:@"activity" result:[activity toDictionary]];
|
|
}
|
|
|
|
- (void) onError:(NSError*)error
|
|
{
|
|
NSLog(@"%@ #%@", TAG, @"onError");
|
|
[self sendError:error];
|
|
}
|
|
|
|
-(void) onAppResume:(NSNotification *)notification
|
|
{
|
|
NSLog(@"%@ %@", TAG, @"resumed");
|
|
[facade switchMode:MAURForegroundMode];
|
|
}
|
|
|
|
-(void) onAppPause:(NSNotification *)notification
|
|
{
|
|
NSLog(@"%@ %@", TAG, @"paused");
|
|
[facade switchMode:MAURBackgroundMode];
|
|
}
|
|
|
|
-(void) onAbortRequested
|
|
{
|
|
NSLog(@"%@ %@", TAG, @"abort requested by the server");
|
|
[self sendEvent:@"abort_requested"];
|
|
}
|
|
|
|
- (void) onHttpAuthorization {
|
|
NSLog(@"%@ %@", TAG, @"http authorization requested by the server");
|
|
[self sendEvent:@"http_authorization"];
|
|
}
|
|
|
|
/**@
|
|
* on UIApplicationDidFinishLaunchingNotification
|
|
*/
|
|
-(void) onFinishLaunching:(NSNotification *)notification
|
|
{
|
|
if (@available(iOS 10, *)) {
|
|
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
|
|
center.delegate = self;
|
|
}
|
|
|
|
NSDictionary *dict = [notification userInfo];
|
|
|
|
MAURConfig *config = [facade getConfig];
|
|
if (config.isDebugging)
|
|
{
|
|
if (@available(iOS 10, *))
|
|
{
|
|
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
|
|
prevNotificationDelegate = center.delegate;
|
|
center.delegate = self;
|
|
}
|
|
}
|
|
|
|
if ([dict objectForKey:UIApplicationLaunchOptionsLocationKey]) {
|
|
NSLog(@"%@ %@", TAG, @"started by system on location event.");
|
|
MAURConfig *config = [facade getConfig];
|
|
if (![config stopOnTerminate]) {
|
|
[facade start:nil];
|
|
[facade switchMode:MAURBackgroundMode];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
|
willPresentNotification:(UNNotification *)notification
|
|
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
|
|
{
|
|
if (prevNotificationDelegate && [prevNotificationDelegate respondsToSelector:@selector(userNotificationCenter:willPresentNotification:withCompletionHandler:)])
|
|
{
|
|
// Give other delegates (like FCM) the chance to process this notification
|
|
|
|
[prevNotificationDelegate userNotificationCenter:center willPresentNotification:notification withCompletionHandler:^(UNNotificationPresentationOptions options) {
|
|
completionHandler(UNNotificationPresentationOptionAlert);
|
|
}];
|
|
}
|
|
else
|
|
{
|
|
completionHandler(UNNotificationPresentationOptionAlert);
|
|
}
|
|
}
|
|
|
|
-(void) onAppTerminate:(NSNotification *)notification
|
|
{
|
|
NSLog(@"%@ %@", TAG, @"appTerminate");
|
|
[facade onAppTerminate];
|
|
}
|
|
|
|
@end
|