Skip to content

Commit

Permalink
Merge pull request #31 from maplibre/ios14-location-permissions
Browse files Browse the repository at this point in the history
ios14 location permissions
  • Loading branch information
petr-pokorny-1 authored Feb 23, 2021
2 parents e4e63ab + 514416c commit cc2ea9f
Show file tree
Hide file tree
Showing 21 changed files with 647 additions and 103 deletions.
31 changes: 31 additions & 0 deletions platform/ios/platform/darwin/src/MGLLocationManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)setDesiredAccuracy:(CLLocationAccuracy)desiredAccuracy;

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
/**
Specifies the level of location accuracy the Maps SDK has permission to use.
@note If the value of this property is `CLAccuracyAuthorizationFullAccuracy`, you can set the
`MGLLocationManager.desiredAccuracy` property to any value. If the value is `CLAccuracyAuthorizationReducedAccuracy`,
setting `MGLLocationManager.desiredAccuracy` to a value other than` kCLLocationAccuracyReduced` has no effect on
the location information.
*/
- (CLAccuracyAuthorization)accuracyAuthorization API_AVAILABLE(ios(14));
#endif

/**
Specifies the type of user activity associated with the location updates.
Expand All @@ -78,6 +90,17 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)setActivityType:(CLActivityType)activityType;

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
/**
Requests the user's permission to temporarily use location update services
with full accuracy.
@note If the user turned off location accuracy you may use this method to
request full accuracy for a session.
*/
- (void)requestTemporaryFullAccuracyAuthorizationWithPurposeKey:(NSString *)purposeKey API_AVAILABLE(ios(14));
#endif

@required

/**
Expand Down Expand Up @@ -195,6 +218,14 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)locationManager:(id<MGLLocationManager>)manager
didFailWithError:(nonnull NSError *)error;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
/**
Notifies the delegate that the location authorization status has changed.
@param manager The location manager reporting the change.
*/
- (void)locationManagerDidChangeAuthorization:(id<MGLLocationManager>)manager;
#endif

@optional

Expand Down
30 changes: 30 additions & 0 deletions platform/ios/platform/darwin/src/MGLLocationManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,15 @@ - (CLLocationAccuracy)desiredAccuracy {
}

- (CLAuthorizationStatus)authorizationStatus {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
if (@available(iOS 14.0, *)) {
return self.locationManager.authorizationStatus;
} else {
return kCLAuthorizationStatusNotDetermined;
}
#else
return [CLLocationManager authorizationStatus];
#endif
}

- (void)setActivityType:(CLActivityType)activityType {
Expand All @@ -49,6 +57,23 @@ - (CLActivityType)activityType {
return self.locationManager.activityType;
}

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
- (CLAccuracyAuthorization)accuracyAuthorization {
if (@available(iOS 14.0, *)) {
return self.locationManager.accuracyAuthorization;
} else {
return CLAccuracyAuthorizationFullAccuracy;
}
}

- (void)requestTemporaryFullAccuracyAuthorizationWithPurposeKey:(NSString *)purposeKey {
if (@available(iOS 14.0, *)) {
[self.locationManager requestTemporaryFullAccuracyAuthorizationWithPurposeKey:purposeKey];
}
}
#endif


- (void)dismissHeadingCalibrationDisplay {
[self.locationManager dismissHeadingCalibrationDisplay];
}
Expand Down Expand Up @@ -113,4 +138,9 @@ - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *
}
}

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
- (void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager {
[self.delegate locationManagerDidChangeAuthorization:self];
}
#endif
@end
2 changes: 2 additions & 0 deletions platform/ios/platform/darwin/src/MGLStyleValue.mm
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ id MGLJSONObjectFromMBGLValue(const mbgl::Value &value) {
return @(value);
}, [](const int64_t value) {
return @(value);
}, [](const uint64_t value) {
return @(value);
}, [](const double value) {
return @(value);
}, [](const std::string &value) {
Expand Down
2 changes: 2 additions & 0 deletions platform/ios/platform/darwin/src/MGLStyleValue_Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ namespace mbgl {
}
}

id MGLJSONObjectFromMBGLValue(const mbgl::Value &value);

NS_INLINE MGLTransition MGLTransitionFromOptions(const mbgl::style::TransitionOptions& options) {
MGLTransition transition;
transition.duration = MGLTimeIntervalFromDuration(options.duration.value_or(mbgl::Duration::zero()));
Expand Down
12 changes: 12 additions & 0 deletions platform/ios/platform/ios/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT

### Features

* Added `MGLLocationManager.accuracyAuthorization` and `[MGLLocationManager requestTemporaryFullAccuracyAuthorizationWithPurposeKeyproperty:]` to support iOS 14 location accuracy privacy changes. (cherry pick from [#361](https://github.com/mapbox/mapbox-gl-native-ios/pull/361))
* Added `[MGLLocationManager requestTemporaryFullAccuracyAuthorizationWithPurposeKeyproperty:]` to allow developers request just-in-time full-accuracy permissions. (cherry pick from [#361](https://github.com/mapbox/mapbox-gl-native-ios/pull/361))
* Added `[MGLLocationManagerDelegate locationManagerDidChangeAuthorization:]` to let `MGLMapView` know about privacy changes. (cherry pick from [#376](https://github.com/mapbox/mapbox-gl-native-ios/pull/376))
* Added `[MGLMapViewDelegate mapView:didChangeLocationManagerAuthorization:]` to allow developers adjust their apps to privacy settings changes. (cherry pick from [#376](https://github.com/mapbox/mapbox-gl-native-ios/pull/376))
* Added an approximate user location halo when `MGLLocationManager.accuracyAuthorization` is set to `CLAccuracyAuthorizationReducedAccuracy`. (cherry pick from [#381](https://github.com/mapbox/mapbox-gl-native-ios/pull/381))
* The `MGLAccuracyAuthorizationDescription` as element of `NSLocationTemporaryUsageDescriptionDictionary` Info.plist key can now be set to describe why you request accuracy authorization. (cherry pick from [#392](https://github.com/mapbox/mapbox-gl-native-ios/pull/392))
* Added `[MGLMapViewDelegate mapViewStyleForDefaultUserLocationAnnotationView:]` and `MGLUserLocationAnnotationViewStyle` class to allow developers customize the default user location annotation view UI style. (cherry pick from [#403](https://github.com/mapbox/mapbox-gl-native-ios/pull/403))

### Bug Fixes

* Fixed an issue that caused a crash when custom location managers did not implement `MGLLocationManager.accuracyAuthorization`. (cherry pick from [#474](https://github.com/mapbox/mapbox-gl-native-ios/pull/474))

### Other

* mapbox-gl-js submodule has been replaced with maplibre-gl-js
Expand Down
35 changes: 20 additions & 15 deletions platform/ios/platform/ios/app/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.mapbox.MapboxGL</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
Expand All @@ -26,12 +26,28 @@
<true/>
<key>NSHumanReadableCopyright</key>
<string>© 2014–2019 Mapbox</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>The map will display your location. If you choose Always, the map may also use your location when it isn’t visible in order to improve OpenStreetMap.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>The map will display your location. The map may also use your location when it isn’t visible in order to improve OpenStreetMap and Mapbox products.</string>
<string>The map will display your location. The map may also use your location when it isn’t visible in order to improve OpenStreetMap.</string>
<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
<key>MGLAccuracyAuthorizationDescription</key>
<string>MapLibre requires your precise location to help you navigate the map.</string>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>The map will display your location.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>The map will display your location. If you choose Always, the map may also use your location when it isn’t visible in order to improve OpenStreetMap and Mapbox products.</string>
<key>UIApplicationShortcutItems</key>
<array>
<dict>
<key>UIApplicationShortcutItemIconFile</key>
<string>settings</string>
<key>UIApplicationShortcutItemTitle</key>
<string>Settings</string>
<key>UIApplicationShortcutItemType</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).settings</string>
</dict>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
Expand All @@ -53,16 +69,5 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIApplicationShortcutItems</key>
<array>
<dict>
<key>UIApplicationShortcutItemTitle</key>
<string>Settings</string>
<key>UIApplicationShortcutItemType</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).settings</string>
<key>UIApplicationShortcutItemIconFile</key>
<string>settings</string>
</dict>
</array>
</dict>
</plist>
3 changes: 1 addition & 2 deletions platform/ios/platform/ios/app/MBXOrnamentsViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#import "MBXOrnamentsViewController.h"

@interface MBXOrnamentsViewController ()<MGLMapViewDelegate>
@interface MBXOrnamentsViewController ()

@property (nonatomic) MGLMapView *mapView;
@property (nonatomic) NSTimer *timer;
Expand Down Expand Up @@ -64,7 +64,6 @@ - (void)viewDidLoad {
zoomLevel:16
direction:30
animated:NO];
mapView.delegate = self;
mapView.showsScale = YES;
[self.view addSubview:mapView];

Expand Down
36 changes: 34 additions & 2 deletions platform/ios/platform/ios/app/MBXViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

#import "MBXFrameTimeGraphView.h"
#import "../src/MGLMapView_Experimental.h"

#import <objc/runtime.h>

static const CLLocationCoordinate2D WorldTourDestinations[] = {
Expand Down Expand Up @@ -213,7 +212,7 @@ @interface MBXViewController () <UITableViewDelegate,
@property (nonatomic) BOOL zoomLevelOrnamentEnabled;
@property (nonatomic) NSMutableArray<UIWindow *> *helperWindows;
@property (nonatomic) NSMutableArray<UIView *> *contentInsetsOverlays;

@property (nonatomic, copy) void (^locationBlock)(void);
@end

@interface MGLMapView (MBXViewController)
Expand Down Expand Up @@ -1952,6 +1951,12 @@ - (IBAction)cycleStyles:(__unused id)sender
}

- (IBAction)locateUser:(id)sender
{
[self nextTrackingMode:sender];
}


- (void)nextTrackingMode:(id)sender
{
MGLUserTrackingMode nextMode;
NSString *nextAccessibilityValue;
Expand Down Expand Up @@ -2333,6 +2338,33 @@ - (void)mapViewDidFinishRenderingFrame:(MGLMapView *)mapView fullyRendered:(BOOL
}
}

- (void)mapView:(nonnull MGLMapView *)mapView didChangeLocationManagerAuthorization:(nonnull id<MGLLocationManager>)manager {
if (@available(iOS 14, *)) {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
if (manager.authorizationStatus == kCLAuthorizationStatusDenied || manager.accuracyAuthorization == CLAccuracyAuthorizationReducedAccuracy) {
[self alertAccuracyChanges];
}
#endif
}
}

- (void)alertAccuracyChanges {
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"MapLibre works best with your precise location."
message:@"You'll get turn-by-turn directions."
preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction *settingsAction = [UIAlertAction actionWithTitle:@"Turn On in Settings" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}];

UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"Keep Precise Location Off" style:UIAlertActionStyleDefault
handler:nil];

[alert addAction:settingsAction];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
}

- (void)saveCurrentMapState:(__unused NSNotification *)notification {

// The following properties can change after the view loads so we need to save their
Expand Down
6 changes: 3 additions & 3 deletions platform/ios/platform/ios/benchmark/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.mapbox.GL.benchmark</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
Expand All @@ -24,6 +24,8 @@
<string>15256</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>MGLMapboxMetricsEnabledSettingShownInApp</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>© 2015–2019 Mapbox</string>
<key>UIApplicationExitsOnSuspend</key>
Expand All @@ -47,7 +49,5 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>MGLMapboxMetricsEnabledSettingShownInApp</key>
<true/>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>

@interface MBXBenchViewController : UIViewController

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "MBXBenchViewController.h"
#import "MBXBenchAppDelegate.h"
#import "MGLMapView_Private.h"
#import "MGLMapViewDelegate.h"

#include "locations.hpp"

Expand Down
17 changes: 16 additions & 1 deletion platform/ios/platform/ios/docs/guides/Info.plist Keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,22 @@ Mapbox-hosted vector tiles and styles require an API access token, which you can

As an alternative, you can use `MGLAccountManager.accessToken` to set a token in code. See [our guide](https://www.mapbox.com/help/ios-private-access-token/) for some tips on keeping access tokens in open source code private.

## MGLAccuracyAuthorizationDescription

Set the Mapbox accuracy authorization description string as an element of `NSLocationTemporaryUsageDescriptionDictionary` to be used by the map to request authorization when the `MGLLocationManager.accuracyAuthorization` is set to `CLAccuracyAuthorizationReducedAccuracy`. Requesting accuracy authorization is available for devices running iOS 14.0 and above.

Example:

```xml
<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
<key>MGLAccuracyAuthorizationDescription</key>
<string>Mapbox requires your precise location to help you navigate the map.</string>
</dict>
```

Remove `MGLAccuracyAuthorizationDescription` if you want to control when to request for accuracy authorization.

## MGLMapboxAPIBaseURL

Use this key if you need to customize the API base URL used throughout the SDK. If unset, the default Mapbox API is used.
Expand Down Expand Up @@ -47,4 +63,3 @@ At runtime, you can obtain the value of this key using the `MGLOfflineStorage.da
Beginning in version 4.0, the SDK also performs collision detection between style layers based on different sources by default. For the default behavior, omit the `MGLCollisionBehaviorPre4_0` key or set it to NO (`false`).

This property may also be set using `[[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:@"MGLCollisionBehaviorPre4_0"]`; it will override any value specified in the `Info.plist`.

Loading

0 comments on commit cc2ea9f

Please sign in to comment.