summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Bounds <jesse@rebounds.net>2016-02-24 18:01:48 -0800
committerJesse Bounds <jesse@rebounds.net>2016-02-26 14:19:04 -0800
commit09c91008910746667b26d04eca679dfa5bb6b03b (patch)
tree710fead6e631c61f955887afbcfa47a282664d17
parentb3adb96e4a34123a337027f5d3ecc377e33397c3 (diff)
downloadqtlocation-mapboxgl-09c91008910746667b26d04eca679dfa5bb6b03b.tar.gz
Introduce MGLLocation Manager
https://github.com/mapbox/mapbox-gl-native/pull/4115 This change makes background data gathering more efficient by disabling standard location updates when the device has been stationary for at least five minutes. It also establishes region monitoring and significant location change monitoring so that if the device appears to be in motion again then background telemetry data collection can resume. All of this reduces the amount of time required for telemetry data collection to the time the device is in motion only. It also only applies to host apps that already run in the background and have the always location permission from their users. This also includes some changes to make the internal pause/resume API of the MGLMapboxEvents class less complex and autonomous. The side effects of the map view waking or sleeping are no longer required for mapbox events to work as intended.
-rw-r--r--gyp/platform-ios.gypi2
-rw-r--r--platform/ios/src/MGLLocationManager.h25
-rw-r--r--platform/ios/src/MGLLocationManager.m159
-rw-r--r--platform/ios/src/MGLMapView.mm1
-rw-r--r--platform/ios/src/MGLMapboxEvents.h6
-rw-r--r--platform/ios/src/MGLMapboxEvents.m172
6 files changed, 236 insertions, 129 deletions
diff --git a/gyp/platform-ios.gypi b/gyp/platform-ios.gypi
index e2c840581b..dc1c082edd 100644
--- a/gyp/platform-ios.gypi
+++ b/gyp/platform-ios.gypi
@@ -48,6 +48,8 @@
'../platform/ios/src/MGLMapboxEvents.m',
'../platform/ios/src/MGLAPIClient.h',
'../platform/ios/src/MGLAPIClient.m',
+ '../platform/ios/src/MGLLocationManager.h',
+ '../platform/ios/src/MGLLocationManager.m',
'../platform/ios/src/MGLMapView.mm',
'../platform/ios/src/MGLAccountManager_Private.h',
'../platform/ios/src/MGLAccountManager.m',
diff --git a/platform/ios/src/MGLLocationManager.h b/platform/ios/src/MGLLocationManager.h
new file mode 100644
index 0000000000..ea23801813
--- /dev/null
+++ b/platform/ios/src/MGLLocationManager.h
@@ -0,0 +1,25 @@
+#import <Foundation/Foundation.h>
+#import <CoreLocation/CoreLocation.h>
+
+@protocol MGLLocationManagerDelegate;
+
+@interface MGLLocationManager : NSObject <CLLocationManagerDelegate>
+
+@property (nonatomic, weak) id<MGLLocationManagerDelegate> delegate;
+
+- (void)startUpdatingLocation;
+- (void)stopUpdatingLocation;
+
+@end
+
+@protocol MGLLocationManagerDelegate <NSObject>
+
+@optional
+
+- (void)locationManager:(MGLLocationManager *)locationManager didUpdateLocations:(NSArray *)locations;
+- (void)locationManagerDidStartLocationUpdates:(MGLLocationManager *)locationManager;
+- (void)locationManagerBackgroundLocationUpdatesDidTimeout:(MGLLocationManager *)locationManager;
+- (void)locationManagerBackgroundLocationUpdatesDidAutomaticallyPause:(MGLLocationManager *)locationManager;
+- (void)locationManagerDidStopLocationUpdates:(MGLLocationManager *)locationManager;
+
+@end
diff --git a/platform/ios/src/MGLLocationManager.m b/platform/ios/src/MGLLocationManager.m
new file mode 100644
index 0000000000..7a3f8de4ff
--- /dev/null
+++ b/platform/ios/src/MGLLocationManager.m
@@ -0,0 +1,159 @@
+#import "MGLLocationManager.h"
+#import <UIKit/UIKit.h>
+
+static const NSTimeInterval fiveMinuteTimeInterval = 300.0;
+static const NSTimeInterval fiveSecondTimeInterval = 5.0;
+static const CLLocationDistance regionRadiusLocationDistance = 300.0;
+static NSString * const MGLLocationManagerRegionIdentifier = @"MGLLocationManagerRegionIdentifier.fence.center";
+
+@interface MGLLocationManager ()
+
+@property (nonatomic) CLLocationManager *standardLocationManager;
+@property (nonatomic) BOOL hostAppHasBackgroundCapability;
+@property (nonatomic, getter=isUpdatingLocation) BOOL updatingLocation;
+@property (nonatomic) NSDate *backgroundLocationServiceTimeoutAllowedDate;
+@property (nonatomic) NSTimer *backgroundLocationServiceTimeoutTimer;
+
+@end
+
+@implementation MGLLocationManager
+
+- (instancetype)init {
+ self = [super init];
+ if (self) {
+ NSArray *backgroundModes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIBackgroundModes"];
+ _hostAppHasBackgroundCapability = [backgroundModes containsObject:@"location"];
+ }
+ return self;
+}
+
+- (void)startUpdatingLocation {
+ if ([self isUpdatingLocation]) {
+ return;
+ }
+
+ [self configurePassiveStandardLocationManager];
+ [self startLocationServices];
+}
+
+- (void)stopUpdatingLocation {
+ if ([self isUpdatingLocation]) {
+ [self.standardLocationManager stopUpdatingLocation];
+ [self.standardLocationManager stopMonitoringSignificantLocationChanges];
+ self.updatingLocation = NO;
+ if ([self.delegate respondsToSelector:@selector(locationManagerDidStopLocationUpdates:)]) {
+ [self.delegate locationManagerDidStopLocationUpdates:self];
+ }
+ }
+}
+
+#pragma mark - Utilities
+
+- (void)configurePassiveStandardLocationManager {
+ if (!self.standardLocationManager) {
+ CLLocationManager *standardLocationManager = [[CLLocationManager alloc] init];
+ standardLocationManager.delegate = self;
+ standardLocationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
+ standardLocationManager.distanceFilter = 1;
+ self.standardLocationManager = standardLocationManager;
+ }
+}
+
+- (void)startLocationServices {
+ if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized ||
+ [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse) {
+
+ // If the host app can run in the background with `always` location permissions then allow background
+ // updates and start the significant location change service and background timeout timer
+ if (self.hostAppHasBackgroundCapability && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized) {
+ [self.standardLocationManager startMonitoringSignificantLocationChanges];
+ [self startBackgroundTimeoutTimer];
+ // On iOS 9 and above also allow background location updates
+ if ([self.standardLocationManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)]) {
+ self.standardLocationManager.allowsBackgroundLocationUpdates = YES;
+ }
+ }
+
+ [self.standardLocationManager startUpdatingLocation];
+ self.updatingLocation = YES;
+ if ([self.delegate respondsToSelector:@selector(locationManagerDidStartLocationUpdates:)]) {
+ [self.delegate locationManagerDidStartLocationUpdates:self];
+ }
+ }
+}
+
+- (void)timeoutAllowedCheck {
+ if (self.backgroundLocationServiceTimeoutAllowedDate == nil) {
+ return;
+ }
+
+ if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive ||
+ [UIApplication sharedApplication].applicationState == UIApplicationStateInactive ) {
+ [self startBackgroundTimeoutTimer];
+ return;
+ }
+
+ NSTimeInterval timeIntervalSinceTimeoutAllowed = [[NSDate date] timeIntervalSinceDate:self.backgroundLocationServiceTimeoutAllowedDate];
+ if (timeIntervalSinceTimeoutAllowed > 0) {
+ [self.standardLocationManager stopUpdatingLocation];
+ self.backgroundLocationServiceTimeoutAllowedDate = nil;
+ if ([self.delegate respondsToSelector:@selector(locationManagerBackgroundLocationUpdatesDidTimeout:)]) {
+ [self.delegate locationManagerBackgroundLocationUpdatesDidTimeout:self];
+ }
+ }
+}
+
+- (void)startBackgroundTimeoutTimer {
+ [self.backgroundLocationServiceTimeoutTimer invalidate];
+ self.backgroundLocationServiceTimeoutAllowedDate = [[NSDate date] dateByAddingTimeInterval:fiveMinuteTimeInterval];
+ self.backgroundLocationServiceTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:fiveSecondTimeInterval target:self selector:@selector(timeoutAllowedCheck) userInfo:nil repeats:YES];
+}
+
+- (void)establishRegionMonitoringForLocation:(CLLocation *)location {
+ CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:location.coordinate radius:regionRadiusLocationDistance identifier:MGLLocationManagerRegionIdentifier];
+ region.notifyOnEntry = NO;
+ region.notifyOnExit = YES;
+ [self.standardLocationManager startMonitoringForRegion:region];
+}
+
+#pragma mark - CLLocationManagerDelegate
+
+- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
+ switch (status) {
+ case kCLAuthorizationStatusAuthorized: // Also handles kCLAuthorizationStatusAuthorizedAlways
+ case kCLAuthorizationStatusAuthorizedWhenInUse:
+ [self startUpdatingLocation];
+ break;
+ default:
+ [self stopUpdatingLocation];
+ break;
+ }
+}
+
+- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
+ CLLocation *location = locations.lastObject;
+ if (location.speed > 0.0) {
+ [self startBackgroundTimeoutTimer];
+ }
+ if (self.standardLocationManager.monitoredRegions.count == 0 || location.horizontalAccuracy < regionRadiusLocationDistance) {
+ [self establishRegionMonitoringForLocation:location];
+ }
+ if ([self.delegate respondsToSelector:@selector(locationManager:didUpdateLocations:)]) {
+ [self.delegate locationManager:self didUpdateLocations:locations];
+ }
+}
+
+- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
+ [self startBackgroundTimeoutTimer];
+ [self.standardLocationManager startUpdatingLocation];
+}
+
+- (void)locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager {
+ if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
+ if ([self.delegate respondsToSelector:@selector(locationManagerBackgroundLocationUpdatesDidAutomaticallyPause:)]) {
+ [self.delegate locationManagerBackgroundLocationUpdatesDidAutomaticallyPause:self];
+ }
+ }
+}
+
+@end
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index 78ab235332..458221fd69 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -997,7 +997,6 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
self.dormant = NO;
[self createGLView];
- [MGLMapboxEvents validate];
self.glSnapshotView.hidden = YES;
diff --git a/platform/ios/src/MGLMapboxEvents.h b/platform/ios/src/MGLMapboxEvents.h
index 9809bca503..9d90bd967e 100644
--- a/platform/ios/src/MGLMapboxEvents.h
+++ b/platform/ios/src/MGLMapboxEvents.h
@@ -39,17 +39,13 @@ extern NSString *const MGLEventGesturePitchStart;
typedef NS_DICTIONARY_OF(NSString *, id) MGLMapboxEventAttributes;
typedef NS_MUTABLE_DICTIONARY_OF(NSString *, id) MGLMutableMapboxEventAttributes;
-@interface MGLMapboxEvents : NSObject <NSURLSessionDelegate>
+@interface MGLMapboxEvents : NSObject
+ (nullable instancetype)sharedManager;
// You must call these methods from the main thread.
//
-+ (void)pauseMetricsCollection;
-+ (void)resumeMetricsCollection;
+ (void)pushEvent:(NSString *)event withAttributes:(MGLMapboxEventAttributes *)attributeDictionary;
-+ (void)pushDebugEvent:(NSString *)event withAttributes:(MGLMapboxEventAttributes *)attributeDictionary;
-+ (void)validate;
+ (void)ensureMetricsOptoutExists;
+ (void)flush;
+ (BOOL)checkPushEnabled;
diff --git a/platform/ios/src/MGLMapboxEvents.m b/platform/ios/src/MGLMapboxEvents.m
index 7f4b632e8f..9097c5b10a 100644
--- a/platform/ios/src/MGLMapboxEvents.m
+++ b/platform/ios/src/MGLMapboxEvents.m
@@ -6,6 +6,7 @@
#import "NSBundle+MGLAdditions.h"
#import "NSException+MGLAdditions.h"
#import "MGLAPIClient.h"
+#import "MGLLocationManager.h"
#include <mbgl/platform/darwin/reachability.h>
#include <sys/sysctl.h>
@@ -89,15 +90,12 @@ const NSTimeInterval MGLFlushInterval = 60;
@end
-@interface MGLMapboxEvents () <CLLocationManagerDelegate>
+@interface MGLMapboxEvents () <MGLLocationManagerDelegate>
@property (nonatomic) MGLMapboxEventsData *data;
@property (nonatomic, copy) NSString *appBundleId;
@property (nonatomic, copy) NSString *instanceID;
@property (nonatomic, copy) NSString *dateForDebugLogFile;
-@property (nonatomic, copy) NSData *digicertCert;
-@property (nonatomic, copy) NSData *geoTrustCert;
-@property (nonatomic, copy) NSData *testServerCert;
@property (nonatomic) NSDateFormatter *rfc3339DateFormatter;
@property (nonatomic) MGLAPIClient *apiClient;
@property (nonatomic) BOOL usesTestServer;
@@ -106,7 +104,7 @@ const NSTimeInterval MGLFlushInterval = 60;
@property (nonatomic) NS_MUTABLE_ARRAY_OF(MGLMapboxEventAttributes *) *eventQueue;
@property (nonatomic) dispatch_queue_t serialQueue;
@property (nonatomic) dispatch_queue_t debugLogSerialQueue;
-@property (nonatomic) CLLocationManager *locationManager;
+@property (nonatomic) MGLLocationManager *locationManager;
@property (nonatomic) NSTimer *timer;
@end
@@ -147,6 +145,8 @@ const NSTimeInterval MGLFlushInterval = 60;
NSString *uniqueID = [[NSProcessInfo processInfo] globallyUniqueString];
_serialQueue = dispatch_queue_create([[NSString stringWithFormat:@"%@.%@.events.serial", _appBundleId, uniqueID] UTF8String], DISPATCH_QUEUE_SERIAL);
+ _locationManager = [[MGLLocationManager alloc] init];
+ _locationManager.delegate = self;
_paused = YES;
[self resumeMetricsCollection];
NSBundle *resourceBundle = [NSBundle mgl_frameworkBundle];
@@ -177,6 +177,7 @@ const NSTimeInterval MGLFlushInterval = 60;
} else {
self.canEnableDebugLogging = YES;
}
+
// Watch for changes to telemetry settings by the user
__weak MGLMapboxEvents *weakSelf = self;
@@ -186,8 +187,11 @@ const NSTimeInterval MGLFlushInterval = 60;
usingBlock:
^(NSNotification *notification) {
MGLMapboxEvents *strongSelf = weakSelf;
- [strongSelf validate];
+ [strongSelf pauseOrResumeMetricsCollectionIfRequired];
}];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pauseOrResumeMetricsCollectionIfRequired) name:UIApplicationDidEnterBackgroundNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pauseOrResumeMetricsCollectionIfRequired) name:UIApplicationWillEnterForegroundNotification object:nil];
}
return self;
}
@@ -201,19 +205,9 @@ const NSTimeInterval MGLFlushInterval = 60;
}
static dispatch_once_t onceToken;
static MGLMapboxEvents *_sharedManager;
- void (^setupBlock)() = ^{
- dispatch_once(&onceToken, ^{
- _sharedManager = [[self alloc] init];
- });
- };
- if ( ! [[NSThread currentThread] isMainThread]) {
- dispatch_sync(dispatch_get_main_queue(), ^{
- setupBlock();
- });
- }
- else {
- setupBlock();
- }
+ dispatch_once(&onceToken, ^{
+ _sharedManager = [[self alloc] init];
+ });
return _sharedManager;
}
@@ -222,50 +216,22 @@ const NSTimeInterval MGLFlushInterval = 60;
[self pauseMetricsCollection];
}
-+ (void)validate {
- [[MGLMapboxEvents sharedManager] validate];
-}
-
-- (void)validate {
- BOOL enabledInSettings = [[self class] isEnabled];
+- (void)pauseOrResumeMetricsCollectionIfRequired {
+ // Prevent blue status bar when host app has `when in use` permission only and it is not in foreground
+ if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse &&
+ [UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
+ [self pauseMetricsCollection];
+ return;
+ }
+ // Toggle pause based on current pause state and current settings state
+ // Practically, a pause only occurs because of a change to an NSUserDefaultsDidChangeNotification
+ BOOL enabledInSettings = [[self class] isEnabled];
if (self.paused && enabledInSettings) {
[self resumeMetricsCollection];
} else if (!self.paused && !enabledInSettings) {
[self pauseMetricsCollection];
}
-
- [self validateUpdatingLocation];
-}
-
-- (void)validateUpdatingLocation {
- if (self.paused) {
- [self stopUpdatingLocation];
- } else {
- switch ([CLLocationManager authorizationStatus]) {
- case kCLAuthorizationStatusNotDetermined:
- case kCLAuthorizationStatusRestricted:
- case kCLAuthorizationStatusDenied:
- [self stopUpdatingLocation];
- break;
- case kCLAuthorizationStatusAuthorized:
- // Also handles kCLAuthorizationStatusAuthorizedAlways
- [self startUpdatingLocation];
- break;
- case kCLAuthorizationStatusAuthorizedWhenInUse:
- if (UIApplication.sharedApplication.applicationState == UIApplicationStateBackground) {
- // Prevent blue status bar when app is not in foreground
- [self stopUpdatingLocation];
- } else {
- [self startUpdatingLocation];
- }
- break;
- }
- }
-}
-
-+ (void)pauseMetricsCollection {
- [[MGLMapboxEvents sharedManager] pauseMetricsCollection];
}
- (void)pauseMetricsCollection {
@@ -279,22 +245,7 @@ const NSTimeInterval MGLFlushInterval = 60;
[self.eventQueue removeAllObjects];
self.data = nil;
- [self validateUpdatingLocation];
-}
-
-- (void)stopUpdatingLocation {
[self.locationManager stopUpdatingLocation];
-
- // -[CLLocationManager stopMonitoringVisits] is only available in iOS 8+.
- if ([self.locationManager respondsToSelector:@selector(stopMonitoringVisits)]) {
- [self.locationManager stopMonitoringVisits];
- }
-
- self.locationManager = nil;
-}
-
-+ (void)resumeMetricsCollection {
- [[MGLMapboxEvents sharedManager] resumeMetricsCollection];
}
- (void)resumeMetricsCollection {
@@ -305,28 +256,7 @@ const NSTimeInterval MGLFlushInterval = 60;
self.paused = NO;
self.data = [[MGLMapboxEventsData alloc] init];
- [self validateUpdatingLocation];
-}
-
-- (void)startUpdatingLocation {
- if (self.locationManager || self.paused) {
- NSAssert(!(self.locationManager && self.paused),
- @"MGLMapboxEvents should not have a CLLocationManager while paused.");
- return;
- }
-
- CLLocationManager *locationManager = [[CLLocationManager alloc] init];
- locationManager.delegate = self;
- locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
- locationManager.distanceFilter = 10;
- [locationManager startUpdatingLocation];
-
- // -[CLLocationManager startMonitoringVisits] is only available in iOS 8+.
- if ([locationManager respondsToSelector:@selector(startMonitoringVisits)]) {
- [locationManager startMonitoringVisits];
- }
-
- self.locationManager = locationManager;
+ [self.locationManager startUpdatingLocation];
}
+ (void)pushEvent:(NSString *)event withAttributes:(MGLMapboxEventAttributes *)attributeDictionary {
@@ -403,7 +333,7 @@ const NSTimeInterval MGLFlushInterval = 60;
}
[strongSelf.apiClient postEvent:turnstileEventAttributes completionHandler:^(NSError * _Nullable error) {
if (error) {
- [MGLMapboxEvents pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription: @"Network error",
+ [strongSelf pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription: @"Network error",
@"error": error}];
return;
}
@@ -435,7 +365,7 @@ const NSTimeInterval MGLFlushInterval = 60;
self.timer = nil;
}
- [MGLMapboxEvents pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription:@"flush"}];
+ [self pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription:@"flush"}];
}
// Called implicitly from public use of +flush.
@@ -450,11 +380,11 @@ const NSTimeInterval MGLFlushInterval = 60;
__strong __typeof__(weakSelf) strongSelf = weakSelf;
[self.apiClient postEvents:events completionHandler:^(NSError * _Nullable error) {
if (error) {
- [MGLMapboxEvents pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription: @"Network error",
+ [strongSelf pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription: @"Network error",
@"error": error}];
return;
}
- [MGLMapboxEvents pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription: @"post",
+ [strongSelf pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription: @"post",
@"debug.eventsCount": @(events.count)}];
}];
});
@@ -609,43 +539,39 @@ const NSTimeInterval MGLFlushInterval = 60;
}
}
-#pragma mark CLLocationManagerDelegate
+#pragma mark CLLocationManagerUtilityDelegate
-- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
- // Iterate through locations to pass all data
+- (void)locationManager:(MGLLocationManager *)locationManager didUpdateLocations:(NSArray *)locations {
for (CLLocation *loc in locations) {
- [MGLMapboxEvents pushEvent:MGLEventTypeLocation withAttributes:@{
- MGLEventKeyLatitude: @(loc.coordinate.latitude),
- MGLEventKeyLongitude: @(loc.coordinate.longitude),
- MGLEventKeySpeed: @(loc.speed),
- MGLEventKeyCourse: @(loc.course),
- MGLEventKeyAltitude: @(round(loc.altitude)),
- MGLEventKeyHorizontalAccuracy: @(round(loc.horizontalAccuracy)),
- MGLEventKeyVerticalAccuracy: @(round(loc.verticalAccuracy))
- }];
+ [MGLMapboxEvents pushEvent:MGLEventTypeLocation
+ withAttributes:@{MGLEventKeyLatitude: @(loc.coordinate.latitude),
+ MGLEventKeyLongitude: @(loc.coordinate.longitude),
+ MGLEventKeySpeed: @(loc.speed),
+ MGLEventKeyCourse: @(loc.course),
+ MGLEventKeyAltitude: @(round(loc.altitude)),
+ MGLEventKeyHorizontalAccuracy: @(round(loc.horizontalAccuracy)),
+ MGLEventKeyVerticalAccuracy: @(round(loc.verticalAccuracy))}];
}
}
-- (void)locationManager:(CLLocationManager *)manager didVisit:(CLVisit *)visit {
- [MGLMapboxEvents pushEvent:MGLEventTypeVisit withAttributes:@{
- MGLEventKeyLatitude: @(visit.coordinate.latitude),
- MGLEventKeyLongitude: @(visit.coordinate.longitude),
- MGLEventKeyHorizontalAccuracy: @(round(visit.horizontalAccuracy)),
- MGLEventKeyArrivalDate: [[NSDate distantPast] isEqualToDate:visit.arrivalDate] ? [NSNull null] : [_rfc3339DateFormatter stringFromDate:visit.arrivalDate],
- MGLEventKeyDepartureDate: [[NSDate distantFuture] isEqualToDate:visit.departureDate] ? [NSNull null] : [_rfc3339DateFormatter stringFromDate:visit.departureDate]
- }];
+- (void)locationManagerBackgroundLocationUpdatesDidAutomaticallyPause:(MGLLocationManager *)locationManager {
+ [self pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription:@"locationManager.locationManagerAutoPause"}];
}
-- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
- [self validateUpdatingLocation];
+- (void)locationManagerBackgroundLocationUpdatesDidTimeout:(MGLLocationManager *)locationManager {
+ [self pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription:@"locationManager.locationManagerTimeout"}];
}
-#pragma mark MGLMapboxEvents Debug
+- (void)locationManagerDidStartLocationUpdates:(MGLLocationManager *)locationManager {
+ [self pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription:@"locationManager.locationManagerStartUpdates"}];
+}
-+ (void)pushDebugEvent:(NSString *)event withAttributes:(MGLMapboxEventAttributes *)attributeDictionary {
- [[MGLMapboxEvents sharedManager] pushDebugEvent:event withAttributes:attributeDictionary];
+- (void)locationManagerDidStopLocationUpdates:(MGLLocationManager *)locationManager {
+ [self pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription: @"locationManager.locationManagerStopUpdates"}];
}
+#pragma mark MGLMapboxEvents Debug
+
- (void)pushDebugEvent:(NSString *)event withAttributes:(MGLMapboxEventAttributes *)attributeDictionary {
if (![self debugLoggingEnabled]) {
return;