From 5d01bd2e2286d595d906b2e0ae06d6669ad6af61 Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Wed, 20 Jan 2016 20:04:12 -0500 Subject: [PATCH 1/3] [ios] Refactor location services Pause location services when the app goes to sleep. --- platform/ios/src/MGLMapView.mm | 86 +++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 748bfc7414c..65d39aabefb 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -179,6 +179,7 @@ @interface MGLMapView () pause(); [self.glView deleteDrawable]; + + if (self.locationManager) + { + [self disableLocationServices]; + self.shouldReenableLocationServicesOnWake = YES; + } } } @@ -1000,6 +1007,12 @@ - (void)wakeGL:(__unused NSNotification *)notification _mbglMap->resume(); _displayLink.paused = NO; + + if (self.shouldReenableLocationServicesOnWake) + { + [self enableLocationServices]; + self.shouldReenableLocationServicesOnWake = NO; + } } } @@ -2997,6 +3010,44 @@ - (void)annotationImageNeedsRedisplay:(MGLAnnotationImage *)annotationImage #pragma mark - User Location - +- (void)enableLocationServices +{ + self.locationManager = [[CLLocationManager alloc] init]; + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)]) + { + BOOL hasLocationDescription = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"] || [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]; + if (!hasLocationDescription) + { + [NSException raise:@"Missing Location Services usage description" format: + @"In iOS 8 and above, this app must have a value for NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription in its Info.plist."]; + } + + if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]) + { + [self.locationManager requestAlwaysAuthorization]; + } + else if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) + { + [self.locationManager requestWhenInUseAuthorization]; + } + } +#endif + + self.locationManager.headingFilter = 5.0; + self.locationManager.delegate = self; + [self.locationManager startUpdatingLocation]; +} + +- (void)disableLocationServices +{ + [self.locationManager stopUpdatingLocation]; + [self.locationManager stopUpdatingHeading]; + self.locationManager.delegate = nil; + self.locationManager = nil; +} + - (void)setShowsUserLocation:(BOOL)showsUserLocation { if (showsUserLocation == _showsUserLocation || _isTargetingInterfaceBuilder) return; @@ -3014,42 +3065,11 @@ - (void)setShowsUserLocation:(BOOL)showsUserLocation self.userLocationAnnotationView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); - self.locationManager = [CLLocationManager new]; - -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 - // enable iOS 8+ location authorization API - // - if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)]) - { - BOOL hasLocationDescription = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"] || - [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]; - if (!hasLocationDescription) - { - [NSException raise:@"Missing Location Services usage description" format: - @"In iOS 8 and above, this app must have a value for NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription in its Info.plist."]; - } - // request location permissions, if both keys exist ask for less permissive - if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) - { - [self.locationManager requestWhenInUseAuthorization]; - } - else if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]) - { - [self.locationManager requestAlwaysAuthorization]; - } - } -#endif - - self.locationManager.headingFilter = 5.0; - self.locationManager.delegate = self; - [self.locationManager startUpdatingLocation]; + [self enableLocationServices]; } else { - [self.locationManager stopUpdatingLocation]; - [self.locationManager stopUpdatingHeading]; - self.locationManager.delegate = nil; - self.locationManager = nil; + [self disableLocationServices]; if ([self.delegate respondsToSelector:@selector(mapViewDidStopLocatingUser:)]) { From 3912a6726dc796a0a9be05987a4db82be0876ab5 Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Wed, 20 Jan 2016 20:16:22 -0500 Subject: [PATCH 2/3] [ios] Only ask for location permissions if not already granted/denied --- platform/ios/src/MGLMapView.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 65d39aabefb..0214aa55294 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -3015,7 +3015,7 @@ - (void)enableLocationServices self.locationManager = [[CLLocationManager alloc] init]; #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 - if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)]) + if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)] && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) { BOOL hasLocationDescription = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"] || [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]; if (!hasLocationDescription) From f6f91e07f074e42757844d03ba21b8af275ee69c Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Wed, 17 Feb 2016 23:25:13 -0500 Subject: [PATCH 3/3] Refactor into one 'validation' method --- platform/ios/src/MGLMapView.mm | 79 ++++++++++++++++------------------ 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 0214aa55294..470a314a7c7 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -179,7 +179,6 @@ @interface MGLMapView () pause(); [self.glView deleteDrawable]; - - if (self.locationManager) - { - [self disableLocationServices]; - self.shouldReenableLocationServicesOnWake = YES; - } } } @@ -1008,11 +1003,7 @@ - (void)wakeGL:(__unused NSNotification *)notification _displayLink.paused = NO; - if (self.shouldReenableLocationServicesOnWake) - { - [self enableLocationServices]; - self.shouldReenableLocationServicesOnWake = NO; - } + [self validateLocationServices]; } } @@ -3010,42 +3001,46 @@ - (void)annotationImageNeedsRedisplay:(MGLAnnotationImage *)annotationImage #pragma mark - User Location - -- (void)enableLocationServices +- (void)validateLocationServices { - self.locationManager = [[CLLocationManager alloc] init]; + BOOL shouldEnableLocationServices = !self.locationManager && self.showsUserLocation; -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 - if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)] && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) + if (shouldEnableLocationServices) { - BOOL hasLocationDescription = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"] || [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]; - if (!hasLocationDescription) - { - [NSException raise:@"Missing Location Services usage description" format: - @"In iOS 8 and above, this app must have a value for NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription in its Info.plist."]; - } + self.locationManager = [[CLLocationManager alloc] init]; - if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]) - { - [self.locationManager requestAlwaysAuthorization]; - } - else if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)] && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) { - [self.locationManager requestWhenInUseAuthorization]; + BOOL hasLocationDescription = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"] || [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]; + if (!hasLocationDescription) + { + [NSException raise:@"Missing Location Services usage description" format: + @"In iOS 8 and above, this app must have a value for NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription in its Info.plist."]; + } + + if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]) + { + [self.locationManager requestAlwaysAuthorization]; + } + else if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) + { + [self.locationManager requestWhenInUseAuthorization]; + } } - } #endif - self.locationManager.headingFilter = 5.0; - self.locationManager.delegate = self; - [self.locationManager startUpdatingLocation]; -} - -- (void)disableLocationServices -{ - [self.locationManager stopUpdatingLocation]; - [self.locationManager stopUpdatingHeading]; - self.locationManager.delegate = nil; - self.locationManager = nil; + self.locationManager.headingFilter = 5.0; + self.locationManager.delegate = self; + [self.locationManager startUpdatingLocation]; + } + else + { + [self.locationManager stopUpdatingLocation]; + [self.locationManager stopUpdatingHeading]; + self.locationManager.delegate = nil; + self.locationManager = nil; + } } - (void)setShowsUserLocation:(BOOL)showsUserLocation @@ -3065,11 +3060,11 @@ - (void)setShowsUserLocation:(BOOL)showsUserLocation self.userLocationAnnotationView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); - [self enableLocationServices]; + [self validateLocationServices]; } else { - [self disableLocationServices]; + [self validateLocationServices]; if ([self.delegate respondsToSelector:@selector(mapViewDidStopLocatingUser:)]) {