summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--include/mbgl/ios/MGLAccountManager.h7
-rw-r--r--include/mbgl/ios/MGLMapView.h12
-rw-r--r--ios/app/Settings.bundle/Root.plist2
-rw-r--r--ios/app/Settings.bundle/en.lproj/Root.strings2
-rw-r--r--ios/framework/Settings.bundle/Root.plist2
-rw-r--r--ios/framework/Settings.bundle/en.lproj/Root.stringsbin544 -> 552 bytes
-rw-r--r--platform/ios/src/MGLAccountManager.m14
-rw-r--r--platform/ios/src/MGLMapView.mm62
-rw-r--r--platform/ios/src/MGLMapboxEvents.h5
-rw-r--r--platform/ios/src/MGLMapboxEvents.m66
11 files changed, 112 insertions, 61 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 45d1c59fd4..840b9ce989 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -50,6 +50,7 @@ Known issues:
- The map view’s background can now be transparent or translucent, as long as the style’s background layer is transparent or translucent and `MGLMapView.opaque` is set to `NO`. ([#3096](https://github.com/mapbox/mapbox-gl-native/pull/3096))
- Documentation is now generated by [jazzy](https://github.com/realm/jazzy) instead of appledoc. ♪♫ ([#3203](https://github.com/mapbox/mapbox-gl-native/pull/3203))
- New API to provide a custom callout view to the map for annotations. ([#3456](https://github.com/mapbox/mapbox-gl-native/pull/3456))
+- Make telemetry on/off setting available in-app. ([#3445](https://github.com/mapbox/mapbox-gl-native/pull/3445))
## iOS 3.0.1
diff --git a/include/mbgl/ios/MGLAccountManager.h b/include/mbgl/ios/MGLAccountManager.h
index 2b3b1784f6..c52ef08607 100644
--- a/include/mbgl/ios/MGLAccountManager.h
+++ b/include/mbgl/ios/MGLAccountManager.h
@@ -26,12 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
*/
+ (nullable NSString *)accessToken;
-#pragma mark Providing User Metrics Opt-Out
-
-/**
- Whether in-app user metrics opt-out is configured. If set to the default value of `NO`, a user opt-out preference is expected in a `Settings.bundle` that shows in the application's section within the system Settings app.
- */
-+ (BOOL)mapboxMetricsEnabledSettingShownInApp;
++ (BOOL)mapboxMetricsEnabledSettingShownInApp __attribute__((deprecated("Telemetry settings are now always shown in the ℹ️ menu.")));
@end
diff --git a/include/mbgl/ios/MGLMapView.h b/include/mbgl/ios/MGLMapView.h
index feb5c6d630..ba7895b81f 100644
--- a/include/mbgl/ios/MGLMapView.h
+++ b/include/mbgl/ios/MGLMapView.h
@@ -129,8 +129,8 @@ IB_DESIGNABLE
@property (nonatomic, readonly) UIImageView *logoView;
/**
- A view showing legally required copyright notices, positioned at the
- bottom-right of the map view.
+ A view showing legally required copyright notices and telemetry settings,
+ positioned at the bottom-right of the map view.
@note The Mapbox terms of service, which governs the use of Mapbox-hosted
vector tiles and styles,
@@ -139,6 +139,14 @@ IB_DESIGNABLE
OpenStreetMap data, or other Mapbox data such as satellite or terrain
data. If that applies to this map view, do not hide this view or remove
any notices from it.
+
+ @note You are additionally
+ [required](https://www.mapbox.com/help/metrics-opt-out-for-users/) to
+ provide users with the option to disable anonymous usage and location
+ sharing (telemetry). If this view is hidden, you must implement this
+ setting elsewhere in your app or via `Settings.bundle`. See our
+ [website](https://www.mapbox.com/ios-sdk/#telemetry_opt_out) for
+ implementation help.
*/
@property (nonatomic, readonly) UIButton *attributionButton;
diff --git a/ios/app/Settings.bundle/Root.plist b/ios/app/Settings.bundle/Root.plist
index 076f402e1e..889610e152 100644
--- a/ios/app/Settings.bundle/Root.plist
+++ b/ios/app/Settings.bundle/Root.plist
@@ -18,7 +18,7 @@
<key>Key</key>
<string>MGLMapboxMetricsEnabled</string>
<key>Title</key>
- <string>Mapbox Metrics</string>
+ <string>Mapbox Telemetry</string>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>TrueValue</key>
diff --git a/ios/app/Settings.bundle/en.lproj/Root.strings b/ios/app/Settings.bundle/en.lproj/Root.strings
index c4fe784dd6..5343a34ae5 100644
--- a/ios/app/Settings.bundle/en.lproj/Root.strings
+++ b/ios/app/Settings.bundle/en.lproj/Root.strings
@@ -1,3 +1,3 @@
"Privacy Settings" = "Privacy Settings";
-"Mapbox Metrics" = "Mapbox Metrics";
+"Mapbox Telemetry" = "Mapbox Telemetry";
"This setting allows the application to share anonymized location and usage data with Mapbox." = "This setting allows the application to share anonymized location and usage data with Mapbox.";
diff --git a/ios/framework/Settings.bundle/Root.plist b/ios/framework/Settings.bundle/Root.plist
index 076f402e1e..889610e152 100644
--- a/ios/framework/Settings.bundle/Root.plist
+++ b/ios/framework/Settings.bundle/Root.plist
@@ -18,7 +18,7 @@
<key>Key</key>
<string>MGLMapboxMetricsEnabled</string>
<key>Title</key>
- <string>Mapbox Metrics</string>
+ <string>Mapbox Telemetry</string>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>TrueValue</key>
diff --git a/ios/framework/Settings.bundle/en.lproj/Root.strings b/ios/framework/Settings.bundle/en.lproj/Root.strings
index 51959f60af..e7658d692d 100644
--- a/ios/framework/Settings.bundle/en.lproj/Root.strings
+++ b/ios/framework/Settings.bundle/en.lproj/Root.strings
Binary files differ
diff --git a/platform/ios/src/MGLAccountManager.m b/platform/ios/src/MGLAccountManager.m
index 8bfe1d68b3..c5aeae7077 100644
--- a/platform/ios/src/MGLAccountManager.m
+++ b/platform/ios/src/MGLAccountManager.m
@@ -8,7 +8,6 @@
@interface MGLAccountManager() <FABKit>
-@property (atomic) BOOL mapboxMetricsEnabledSettingShownInApp;
@property (atomic) NSString *accessToken;
@end
@@ -21,15 +20,8 @@
// Load all referenced categories due to absence of -ObjC linker flag
[MGLCategoryLoader loadCategories];
- // Read the initial configuration from Info.plist. The shown-in-app setting
- // preempts the Settings bundle check in -[MGLMapboxEvents init] triggered
- // by setting the access token.
- NSBundle *bundle = [NSBundle mainBundle];
- NSNumber *shownInAppNumber = [bundle objectForInfoDictionaryKey:@"MGLMapboxMetricsEnabledSettingShownInApp"];
- if (shownInAppNumber) {
- [MGLAccountManager sharedManager].mapboxMetricsEnabledSettingShownInApp = [shownInAppNumber boolValue];
- }
- NSString *accessToken = [bundle objectForInfoDictionaryKey:@"MGLMapboxAccessToken"];
+ // Read the initial configuration from Info.plist.
+ NSString *accessToken = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"MGLMapboxAccessToken"];
if (accessToken.length) {
self.accessToken = accessToken;
}
@@ -60,7 +52,7 @@
}
+ (BOOL) mapboxMetricsEnabledSettingShownInApp {
- return [MGLAccountManager sharedManager].mapboxMetricsEnabledSettingShownInApp;
+ NSLog(@"mapboxMetricsEnabledSettingShownInApp is no longer necessary; the Mapbox iOS SDK has changed to always provide a telemetry setting in-app.");
}
+ (void) setAccessToken:(NSString *) accessToken {
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index 4ee12942b4..0fdf2ea66a 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -117,6 +117,7 @@ public:
CLLocationManagerDelegate,
UIActionSheetDelegate,
MGLCalloutViewDelegate,
+ UIAlertViewDelegate,
MGLMultiPointDelegate,
MGLAnnotationImageDelegate>
@@ -333,6 +334,7 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
_attributionButton.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_attributionButton];
_attributionButtonConstraints = [NSMutableArray array];
+ [_attributionButton addObserver:self forKeyPath:@"hidden" options:NSKeyValueObservingOptionNew context:NULL];
// setup compass
//
@@ -480,6 +482,7 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[MGLAccountManager sharedManager] removeObserver:self forKeyPath:@"accessToken"];
+ [_attributionButton removeObserver:self forKeyPath:@"hidden"];
[self validateDisplayLink];
@@ -1422,13 +1425,9 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
@"© Mapbox",
@"© OpenStreetMap",
@"Improve This Map",
+ @"Mapbox Telemetry",
nil];
- // iOS 8+: add action that opens app's Settings.app panel, if applicable
- if (&UIApplicationOpenSettingsURLString != NULL && ! [MGLAccountManager mapboxMetricsEnabledSettingShownInApp])
- {
- [self.attributionSheet addButtonWithTitle:@"Adjust Privacy Settings"];
- }
}
[self.attributionSheet showFromRect:self.attributionButton.frame inView:self animated:YES];
@@ -1453,10 +1452,48 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
[[UIApplication sharedApplication] openURL:
[NSURL URLWithString:feedbackURL]];
}
- // skips to 4 because button is conditionally added after cancel (index 3)
- else if (buttonIndex == actionSheet.firstOtherButtonIndex + 4)
+ else if (buttonIndex == actionSheet.firstOtherButtonIndex + 3)
{
- [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
+ NSString *message;
+ NSString *participate;
+ NSString *optOut;
+
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"MGLMapboxMetricsEnabled"])
+ {
+ message = @"You are helping to make OpenStreetMap and Mapbox maps better by contributing anonymous usage data.";
+ participate = @"Keep Participating";
+ optOut = @"Stop Participating";
+ }
+ else
+ {
+ message = @"You can help make OpenStreetMap and Mapbox maps better by contributing anonymous usage data.";
+ participate = @"Participate";
+ optOut = @"Don’t Participate";
+ }
+
+ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Make Mapbox Maps Better"
+ message:message
+ delegate:self
+ cancelButtonTitle:participate
+ otherButtonTitles:@"Tell Me More", optOut, nil];
+ [alert show];
+ }
+}
+
+- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
+{
+ if (buttonIndex == alertView.cancelButtonIndex)
+ {
+ [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"MGLMapboxMetricsEnabled"];
+ }
+ else if (buttonIndex == alertView.firstOtherButtonIndex)
+ {
+ [[UIApplication sharedApplication] openURL:
+ [NSURL URLWithString:@"https://mapbox.com/telemetry/"]];
+ }
+ else if (buttonIndex == alertView.firstOtherButtonIndex + 1)
+ {
+ [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"MGLMapboxMetricsEnabled"];
}
}
@@ -1472,6 +1509,15 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
_mbglFileSource->setAccessToken((std::string)[accessToken UTF8String]);
}
}
+ else if ([keyPath isEqualToString:@"hidden"] && object == _attributionButton)
+ {
+ NSNumber *hiddenNumber = change[NSKeyValueChangeNewKey];
+ BOOL attributionButtonWasHidden = [hiddenNumber boolValue];
+ if (attributionButtonWasHidden)
+ {
+ [MGLMapboxEvents ensureMetricsOptoutExists];
+ }
+ }
}
+ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingZoomEnabled
diff --git a/platform/ios/src/MGLMapboxEvents.h b/platform/ios/src/MGLMapboxEvents.h
index 920a2227fd..dba24885bf 100644
--- a/platform/ios/src/MGLMapboxEvents.h
+++ b/platform/ios/src/MGLMapboxEvents.h
@@ -66,7 +66,10 @@ typedef NS_MUTABLE_DICTIONARY_OF(NSString *, id) MGLMutableMapboxEventAttributes
+ (void) flush;
// Main thread only
-+ (void)validate;
++ (void) validate;
+
+// Main thread only
++ (void) ensureMetricsOptoutExists;
@end
diff --git a/platform/ios/src/MGLMapboxEvents.m b/platform/ios/src/MGLMapboxEvents.m
index 259cfb3def..5fc062a2a2 100644
--- a/platform/ios/src/MGLMapboxEvents.m
+++ b/platform/ios/src/MGLMapboxEvents.m
@@ -180,36 +180,6 @@ const NSTimeInterval MGLFlushInterval = 60;
self = [super init];
if (self) {
- if (! [MGLAccountManager mapboxMetricsEnabledSettingShownInApp] &&
- [[NSUserDefaults standardUserDefaults] integerForKey:@"MGLMapboxAccountType"] == 0) {
- // Opt Out is not configured in UI, so check for Settings.bundle
- // Put Settings bundle into memory
- id defaultEnabledValue;
- NSString *appSettingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];
-
- if (appSettingsBundle) {
- // Dynamic Settings.bundle loading based on:
- // http://stackoverflow.com/questions/510216/can-you-make-the-settings-in-settings-bundle-default-even-if-you-dont-open-the
- NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[appSettingsBundle stringByAppendingPathComponent:@"Root.plist"]];
- NSArray *preferences = settings[@"PreferenceSpecifiers"];
- for (NSDictionary *prefSpecification in preferences) {
- if ([prefSpecification[@"Key"] isEqualToString:@"MGLMapboxMetricsEnabled"]) {
- defaultEnabledValue = prefSpecification[@"DefaultValue"];
- }
- }
- }
-
- if (!defaultEnabledValue)
- {
- [NSException raise:@"MGLMapboxMetricsEnabled setting missing" format:
- @"End users must be able to opt out of Metrics in your app, either inside Settings (via Settings.bundle) or inside this app. "
- @"If you implement the opt-out control inside this app, disable this assertion by setting MGLMapboxMetricsEnabledSettingShownInApp to YES in Info.plist."];
- }
- [[NSUserDefaults standardUserDefaults] registerDefaults:@{
- @"MGLMapboxMetricsEnabled": defaultEnabledValue,
- }];
- }
-
_appBundleId = [[NSBundle mainBundle] bundleIdentifier];
_appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
_appVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
@@ -770,6 +740,42 @@ const NSTimeInterval MGLFlushInterval = 60;
return result;
}
+// Main thread only
+//
++ (void) ensureMetricsOptoutExists {
+ MGLAssertIsMainThread();
+
+ NSNumber *shownInAppNumber = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"MGLMapboxMetricsEnabledSettingShownInApp"];
+ BOOL metricsEnabledSettingShownInAppFlag = [shownInAppNumber boolValue];
+
+ if ( ! metricsEnabledSettingShownInAppFlag &&
+ [[NSUserDefaults standardUserDefaults] integerForKey:@"MGLMapboxAccountType"] == 0) {
+ // Opt-out is not configured in UI, so check for Settings.bundle
+ id defaultEnabledValue;
+ NSString *appSettingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];
+
+ if (appSettingsBundle) {
+ // Dynamic Settings.bundle loading based on http://stackoverflow.com/a/510329/2094275
+ NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[appSettingsBundle stringByAppendingPathComponent:@"Root.plist"]];
+ NSArray *preferences = settings[@"PreferenceSpecifiers"];
+ for (NSDictionary *prefSpecification in preferences) {
+ if ([prefSpecification[@"Key"] isEqualToString:@"MGLMapboxMetricsEnabled"]) {
+ defaultEnabledValue = prefSpecification[@"DefaultValue"];
+ }
+ }
+ }
+
+ if ( ! defaultEnabledValue) {
+ [NSException raise:@"Telemetry opt-out missing" format:
+ @"End users must be able to opt out of Mapbox Telemetry in your app, either inside Settings (via Settings.bundle) or inside this app. "
+ @"By default, this opt-out control is included as a menu item in the attribution action sheet. "
+ @"If you reimplement the opt-out control inside this app, disable this assertion by setting MGLMapboxMetricsEnabledSettingShownInApp to YES in Info.plist."
+ @"\n\nSee https://www.mapbox.com/ios-sdk/#telemetry_opt_out for more information."
+ @"\n\nAdditionally, by hiding this attribution control you agree to display the required attribution elsewhere in this app."];
+ }
+ }
+}
+
#pragma mark CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
// Iterate through locations to pass all data