From 52ccea7ae8a8f22029dffac6600f0b80bb9467ff Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 20 Mar 2015 10:14:30 -0500 Subject: [PATCH 01/28] #1033 - Initial port of MBLocationManager into iOS GL --- ios/app/MBLocationManager.h | 24 ++++++ ios/app/MBLocationManager.m | 142 ++++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 ios/app/MBLocationManager.h create mode 100644 ios/app/MBLocationManager.m diff --git a/ios/app/MBLocationManager.h b/ios/app/MBLocationManager.h new file mode 100644 index 000000000..84a847c9e --- /dev/null +++ b/ios/app/MBLocationManager.h @@ -0,0 +1,24 @@ +// +// MBLocationManager.h +// Hermes +// +// Created by Brad Leege on 3/8/15. +// Copyright (c) 2015 Mapbox. All rights reserved. +// + +#import +#import "CoreLocation/CoreLocation.h" + +@interface MBLocationManager : NSObject + ++ (id)sharedManager; + +- (BOOL) isAuthorizedStatusDetermined; +- (void) requestAlwaysAuthorization; + +- (void) startUpdatingLocation; +- (void) stopUpdatingLocation; + +- (void) setBackgroundStatus:(BOOL)isBackground; + +@end diff --git a/ios/app/MBLocationManager.m b/ios/app/MBLocationManager.m new file mode 100644 index 000000000..9aa235fc2 --- /dev/null +++ b/ios/app/MBLocationManager.m @@ -0,0 +1,142 @@ +// +// MBLocationManager.m +// Hermes +// +// 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 +// +// Created by Brad Leege on 3/8/15. +// Copyright (c) 2015 Mapbox. All rights reserved. +// + +#import "MBLocationManager.h" +#import "CoreLocation/CoreLocation.h" + +@interface MBLocationManager() + +@property (atomic) CLLocationManager *locationManager; +@property (atomic) BOOL isBackground; + +@end + +@implementation MBLocationManager + + +static MBLocationManager *sharedManager = nil; + +- (id) init { + if (self = [super init]) { + + NSString *settingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"]; + if(!settingsBundle) { + NSLog(@"Could not find Settings.bundle"); + } else { + NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent:@"Root.plist"]]; + NSArray *preferences = [settings objectForKey:@"PreferenceSpecifiers"]; + NSMutableDictionary *defaultsToRegister = [[NSMutableDictionary alloc] initWithCapacity:[preferences count]]; + for(NSDictionary *prefSpecification in preferences) { + NSString *key = [prefSpecification objectForKey:@"Key"]; + if(key && [[prefSpecification allKeys] containsObject:@"DefaultValue"]) { + [defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key]; + } + } + + [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister]; + } + + _locationManager = [[CLLocationManager alloc] init]; + _locationManager.distanceFilter = 2; + _locationManager.desiredAccuracy = kCLLocationAccuracyBest; + _locationManager.pausesLocationUpdatesAutomatically = YES; + [_locationManager setDelegate:self]; + } + return self; +} + ++ (id)sharedManager { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedManager = [[self alloc] init]; + }); + return sharedManager; +} + +- (BOOL) isAuthorizedStatusDetermined { + return ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusNotDetermined); +} + +- (void) requestAlwaysAuthorization { + if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { + [self.locationManager requestAlwaysAuthorization]; + } else { + // This is iOS 7 or below so Starting Location Updates will trigger authorization request + [self startUpdatingLocation]; + } +} + +- (void) setBackgroundStatus:(BOOL)isBackground { + self.isBackground = isBackground; +} + +- (void) startUpdatingLocation { + [self.locationManager startUpdatingLocation]; +} + +- (void) stopUpdatingLocation { + [self.locationManager stopUpdatingLocation]; +} + +#pragma mark CLLocationManagerDelegate +- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { + CLLocation *loc = (CLLocation *)[locations objectAtIndex:0]; + NSLog(@"didUpdateLocations() called with %lu location in array. First Location = %f, %f", (unsigned long)locations.count, loc.coordinate.latitude, loc.coordinate.longitude); + +/** + if (![[NSUserDefaults standardUserDefaults] boolForKey:@"mapbox_metrics_enabled_preference"]) { + NSLog(@"Mapbox Metrics are not enabled, so return without sending in data."); + return; + } + + // Iterate through locations to pass all data + for (CLLocation *loc in locations) { + NSMutableDictionary *evt = [[NSMutableDictionary alloc] init]; + [evt setValue:[[NSNumber alloc] initWithDouble:loc.coordinate.latitude] forKey:@"lat"]; + [evt setValue:[[NSNumber alloc] initWithDouble:loc.coordinate.longitude] forKey:@"lng"]; + [evt setValue:[[NSNumber alloc] initWithBool:_isBackground] forKey:@"isBackground"]; + [[MapboxEvents sharedManager] pushEvent:@"location" withAttributes:evt]; + } +*/ +} + +- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { + NSString *newStatus = nil; + switch (status) { + case kCLAuthorizationStatusNotDetermined: + newStatus = @"User Hasn't Determined Yet"; + break; + case kCLAuthorizationStatusRestricted: + newStatus = @"Restricted and Can't Be Changed By User"; + break; + case kCLAuthorizationStatusDenied: + newStatus = @"User Explcitly Denied"; + [[MBLocationManager sharedManager] stopUpdatingLocation]; + break; + case kCLAuthorizationStatusAuthorized: + newStatus = @"User Has Authorized / Authorized Always"; + [[MBLocationManager sharedManager] startUpdatingLocation]; + break; + // case kCLAuthorizationStatusAuthorizedAlways: + // newStatus = @"Not Determined"; + // break; + case kCLAuthorizationStatusAuthorizedWhenInUse: + newStatus = @"User Has Authorized When In Use Only"; + [[MBLocationManager sharedManager] startUpdatingLocation]; + break; + default: + newStatus = @"Unknown"; + break; + } + NSLog(@"MBLocationManager didChangeAuthorizationStatus() called. New Status = %@", newStatus); +} + +@end From e083c13f654836469963f64445f51b0e5e16aec7 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 20 Mar 2015 10:36:22 -0500 Subject: [PATCH 02/28] #1033 - Instantiating MBLocationManager in MBXViewController --- ios/app/MBXViewController.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ios/app/MBXViewController.mm b/ios/app/MBXViewController.mm index 98b337f92..822549070 100644 --- a/ios/app/MBXViewController.mm +++ b/ios/app/MBXViewController.mm @@ -5,6 +5,7 @@ #import #import +#import "MBLocationManager.h" static UIColor *const kTintColor = [UIColor colorWithRed:0.120 green:0.550 blue:0.670 alpha:1.000]; @@ -39,6 +40,7 @@ mbgl::Settings_NSUserDefaults *settings = nullptr; { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveState:) name:UIApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(restoreState:) name:UIApplicationWillEnterForegroundNotification object:nil]; + [MBLocationManager sharedManager]; } return self; From c42e83fcc6f888373c318ee9aa2e5f0c28e7d970 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 20 Mar 2015 11:11:06 -0500 Subject: [PATCH 03/28] #1033 - Moving MBLocationManager to Core GL from app specific instance. --- gyp/platform-ios.gypi | 2 ++ {ios/app => include/mbgl/ios}/MBLocationManager.h | 0 ios/app/MBXViewController.mm | 2 -- {ios/app => platform/ios}/MBLocationManager.m | 0 platform/ios/MGLMapView.mm | 5 +++++ styles | 2 +- 6 files changed, 8 insertions(+), 3 deletions(-) rename {ios/app => include/mbgl/ios}/MBLocationManager.h (100%) rename {ios/app => platform/ios}/MBLocationManager.m (100%) diff --git a/gyp/platform-ios.gypi b/gyp/platform-ios.gypi index a8a827af6..f3191659a 100644 --- a/gyp/platform-ios.gypi +++ b/gyp/platform-ios.gypi @@ -16,6 +16,8 @@ '../platform/darwin/asset_root.mm', '../platform/darwin/image.mm', '../platform/darwin/reachability.m', + '../include/mbgl/ios/MBLocationManager.h', + '../platform/ios/MBLocationManager.m', '../include/mbgl/ios/MGLMapView.h', '../platform/ios/MGLMapView.mm', '../include/mbgl/ios/MGLStyleFunctionValue.h', diff --git a/ios/app/MBLocationManager.h b/include/mbgl/ios/MBLocationManager.h similarity index 100% rename from ios/app/MBLocationManager.h rename to include/mbgl/ios/MBLocationManager.h diff --git a/ios/app/MBXViewController.mm b/ios/app/MBXViewController.mm index 822549070..98b337f92 100644 --- a/ios/app/MBXViewController.mm +++ b/ios/app/MBXViewController.mm @@ -5,7 +5,6 @@ #import #import -#import "MBLocationManager.h" static UIColor *const kTintColor = [UIColor colorWithRed:0.120 green:0.550 blue:0.670 alpha:1.000]; @@ -40,7 +39,6 @@ mbgl::Settings_NSUserDefaults *settings = nullptr; { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveState:) name:UIApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(restoreState:) name:UIApplicationWillEnterForegroundNotification object:nil]; - [MBLocationManager sharedManager]; } return self; diff --git a/ios/app/MBLocationManager.m b/platform/ios/MBLocationManager.m similarity index 100% rename from ios/app/MBLocationManager.m rename to platform/ios/MBLocationManager.m diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 281755a4c..0592683d6 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -21,6 +21,8 @@ #import "NSArray+MGLAdditions.h" #import "NSDictionary+MGLAdditions.h" +#import "MBLocationManager.h" + // Returns the path to the default cache database on this system. const std::string &defaultCacheDatabase() { @@ -338,6 +340,9 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; + // Setup MBLocationManager for metrics + [MBLocationManager sharedManager]; + // set initial position // mbglMap->setLatLngZoom(mbgl::LatLng(0, 0), mbglMap->getMinZoom()); diff --git a/styles b/styles index c13039337..25b1b7dff 160000 --- a/styles +++ b/styles @@ -1 +1 @@ -Subproject commit c1303933798e1bb48649d8a64b71038b4d3ed0a4 +Subproject commit 25b1b7dff37a18151e3286144bc8013b432a8860 From 253643f57d055a7e90ddea17374d706ef2c18ed4 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 20 Mar 2015 11:37:50 -0500 Subject: [PATCH 04/28] #1033 - Renaming MBLocationManager to MGLMetricsLocationManager to better comply with naming scheme. --- gyp/platform-ios.gypi | 4 ++-- ...tionManager.h => MGLMetricsLocationManager.h} | 2 +- platform/ios/MGLMapView.mm | 4 ++-- ...tionManager.m => MGLMetricsLocationManager.m} | 16 ++++++++-------- 4 files changed, 13 insertions(+), 13 deletions(-) rename include/mbgl/ios/{MBLocationManager.h => MGLMetricsLocationManager.h} (84%) rename platform/ios/{MBLocationManager.m => MGLMetricsLocationManager.m} (90%) diff --git a/gyp/platform-ios.gypi b/gyp/platform-ios.gypi index f3191659a..43c51d61b 100644 --- a/gyp/platform-ios.gypi +++ b/gyp/platform-ios.gypi @@ -16,8 +16,8 @@ '../platform/darwin/asset_root.mm', '../platform/darwin/image.mm', '../platform/darwin/reachability.m', - '../include/mbgl/ios/MBLocationManager.h', - '../platform/ios/MBLocationManager.m', + '../include/mbgl/ios/MGLMetricsLocationManager.h', + '../platform/ios/MGLMetricsLocationManager.m', '../include/mbgl/ios/MGLMapView.h', '../platform/ios/MGLMapView.mm', '../include/mbgl/ios/MGLStyleFunctionValue.h', diff --git a/include/mbgl/ios/MBLocationManager.h b/include/mbgl/ios/MGLMetricsLocationManager.h similarity index 84% rename from include/mbgl/ios/MBLocationManager.h rename to include/mbgl/ios/MGLMetricsLocationManager.h index 84a847c9e..1630b848a 100644 --- a/include/mbgl/ios/MBLocationManager.h +++ b/include/mbgl/ios/MGLMetricsLocationManager.h @@ -9,7 +9,7 @@ #import #import "CoreLocation/CoreLocation.h" -@interface MBLocationManager : NSObject +@interface MGLMetricsLocationManager : NSObject + (id)sharedManager; diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 0592683d6..6136eeb3c 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -21,7 +21,7 @@ #import "NSArray+MGLAdditions.h" #import "NSDictionary+MGLAdditions.h" -#import "MBLocationManager.h" +#import "MGLMetricsLocationManager.h" // Returns the path to the default cache database on this system. @@ -341,7 +341,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; // Setup MBLocationManager for metrics - [MBLocationManager sharedManager]; + [MGLMetricsLocationManager sharedManager]; // set initial position // diff --git a/platform/ios/MBLocationManager.m b/platform/ios/MGLMetricsLocationManager.m similarity index 90% rename from platform/ios/MBLocationManager.m rename to platform/ios/MGLMetricsLocationManager.m index 9aa235fc2..0732c04e3 100644 --- a/platform/ios/MBLocationManager.m +++ b/platform/ios/MGLMetricsLocationManager.m @@ -9,20 +9,20 @@ // Copyright (c) 2015 Mapbox. All rights reserved. // -#import "MBLocationManager.h" +#import "MGLMetricsLocationManager.h" #import "CoreLocation/CoreLocation.h" -@interface MBLocationManager() +@interface MGLMetricsLocationManager() @property (atomic) CLLocationManager *locationManager; @property (atomic) BOOL isBackground; @end -@implementation MBLocationManager +@implementation MGLMetricsLocationManager -static MBLocationManager *sharedManager = nil; +static MGLMetricsLocationManager *sharedManager = nil; - (id) init { if (self = [super init]) { @@ -119,24 +119,24 @@ static MBLocationManager *sharedManager = nil; break; case kCLAuthorizationStatusDenied: newStatus = @"User Explcitly Denied"; - [[MBLocationManager sharedManager] stopUpdatingLocation]; + [[MGLMetricsLocationManager sharedManager] stopUpdatingLocation]; break; case kCLAuthorizationStatusAuthorized: newStatus = @"User Has Authorized / Authorized Always"; - [[MBLocationManager sharedManager] startUpdatingLocation]; + [[MGLMetricsLocationManager sharedManager] startUpdatingLocation]; break; // case kCLAuthorizationStatusAuthorizedAlways: // newStatus = @"Not Determined"; // break; case kCLAuthorizationStatusAuthorizedWhenInUse: newStatus = @"User Has Authorized When In Use Only"; - [[MBLocationManager sharedManager] startUpdatingLocation]; + [[MGLMetricsLocationManager sharedManager] startUpdatingLocation]; break; default: newStatus = @"Unknown"; break; } - NSLog(@"MBLocationManager didChangeAuthorizationStatus() called. New Status = %@", newStatus); + NSLog(@"MGLMetricsLocationManager didChangeAuthorizationStatus() called. New Status = %@", newStatus); } @end From ec304d37ac0fd03f3cf96ab9a5466b6a8f689674 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 20 Mar 2015 16:01:52 -0500 Subject: [PATCH 05/28] #1033 - Integrating MapboxEvents class. --- gyp/platform-ios.gypi | 6 +- include/mbgl/ios/MGLMapboxEvents.h | 24 +++ platform/ios/MGLMapboxEvents.m | 250 +++++++++++++++++++++++++++++ 3 files changed, 278 insertions(+), 2 deletions(-) create mode 100644 include/mbgl/ios/MGLMapboxEvents.h create mode 100644 platform/ios/MGLMapboxEvents.m diff --git a/gyp/platform-ios.gypi b/gyp/platform-ios.gypi index 43c51d61b..738a4afa5 100644 --- a/gyp/platform-ios.gypi +++ b/gyp/platform-ios.gypi @@ -16,10 +16,12 @@ '../platform/darwin/asset_root.mm', '../platform/darwin/image.mm', '../platform/darwin/reachability.m', - '../include/mbgl/ios/MGLMetricsLocationManager.h', - '../platform/ios/MGLMetricsLocationManager.m', + '../include/mbgl/ios/MGLMapboxEvents.h', + '../platform/ios/MGLMapboxEvents.m', '../include/mbgl/ios/MGLMapView.h', '../platform/ios/MGLMapView.mm', + '../include/mbgl/ios/MGLMetricsLocationManager.h', + '../platform/ios/MGLMetricsLocationManager.m', '../include/mbgl/ios/MGLStyleFunctionValue.h', '../platform/ios/MGLStyleFunctionValue.m', '../include/mbgl/ios/MGLTypes.h', diff --git a/include/mbgl/ios/MGLMapboxEvents.h b/include/mbgl/ios/MGLMapboxEvents.h new file mode 100644 index 000000000..c0cff7c2b --- /dev/null +++ b/include/mbgl/ios/MGLMapboxEvents.h @@ -0,0 +1,24 @@ +// +// MapboxEvents.h +// MapboxEvents +// +// Created by Brad Leege on 3/5/15. +// Copyright (c) 2015 Mapbox. All rights reserved. +// + +#import + +@interface MGLMapboxEvents : NSObject + +@property (atomic) NSInteger flushAt; +@property (atomic) NSInteger flushAfter; +@property (atomic) NSString *api; +@property (atomic) NSString *token; +@property (atomic) NSString *appName; +@property (atomic) NSString *appVersion; + ++ (id)sharedManager; + +- (void) pushEvent:(NSString *)event withAttributes:(NSDictionary *)attributeDictionary; + +@end \ No newline at end of file diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m new file mode 100644 index 000000000..cd6ecbd0a --- /dev/null +++ b/platform/ios/MGLMapboxEvents.m @@ -0,0 +1,250 @@ +// +// MapboxEvents.m +// MapboxEvents +// +// Dynamic detection of ASIdentifierManager from Mixpanel +// https://github.com/mixpanel/mixpanel-iphone/blob/master/LICENSE +// +// Created by Brad Leege on 3/5/15. +// Copyright (c) 2015 Mapbox. All rights reserved. +// + +#import "MGLMapboxEvents.h" +#import +#import +#import +#include + +@interface MGLMapboxEvents() + +@property (atomic) NSMutableArray *queue; +@property (atomic) NSString *instance; +@property (atomic) NSString *anonid; +@property (atomic) NSTimer *timer; +@property (atomic) NSString *userAgent; + +@end + +@implementation MGLMapboxEvents + +static MGLMapboxEvents *sharedManager = nil; + +NSString *anonId = nil; +NSDateFormatter *rfc3339DateFormatter = nil; +NSString *model; +NSString *iOSVersion; +NSString *carrier; +NSNumber *scale; + +- (id) init { + self = [super init]; + if (self) { + _queue = [[NSMutableArray alloc] init]; + _flushAt = 20; + _flushAfter = 10000; + _api = @"https://api.tiles.mapbox.com"; + _token = nil; + _instance = [[NSUUID UUID] UUIDString]; + Class ASIdentifierManagerClass = NSClassFromString(@"ASIdentifierManager"); + if (ASIdentifierManagerClass) { + SEL sharedManagerSelector = NSSelectorFromString(@"sharedManager"); + id sharedManager = ((id (*)(id, SEL))[ASIdentifierManagerClass methodForSelector:sharedManagerSelector])(ASIdentifierManagerClass, sharedManagerSelector); + // Add check here + SEL isAdvertisingTrackingEnabledSelector = NSSelectorFromString(@"isAdvertisingTrackingEnabled"); + BOOL trackingEnabled = ((BOOL (*)(id, SEL))[sharedManager methodForSelector:isAdvertisingTrackingEnabledSelector])(sharedManager, isAdvertisingTrackingEnabledSelector); + if (trackingEnabled) { + SEL advertisingIdentifierSelector = NSSelectorFromString(@"advertisingIdentifier"); + NSUUID *uuid = ((NSUUID* (*)(id, SEL))[sharedManager methodForSelector:advertisingIdentifierSelector])(sharedManager, advertisingIdentifierSelector); + _anonid = [uuid UUIDString]; + } else { + _anonid = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; + } + } else { + _anonid = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; + } + + + // Get Vendor ID + anonId = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; + model = [self getSysInfoByName:"hw.machine"]; + iOSVersion = [NSString stringWithFormat:@"%@ %@", [UIDevice currentDevice].systemName, [UIDevice currentDevice].systemVersion]; + if ([UIScreen instancesRespondToSelector:@selector(nativeScale)]) { + scale = [[NSNumber alloc] initWithFloat:[UIScreen mainScreen].nativeScale]; + } else { + scale = [[NSNumber alloc] initWithFloat:[UIScreen mainScreen].scale]; + } + CTCarrier *carrierVendor = [[[CTTelephonyNetworkInfo alloc] init] subscriberCellularProvider]; + carrier = [carrierVendor carrierName]; + + _userAgent = @"MapboxEventsiOS/1.0"; + + // Setup Date Format + rfc3339DateFormatter = [[NSDateFormatter alloc] init]; + NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; + + [rfc3339DateFormatter setLocale:enUSPOSIXLocale]; + [rfc3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"]; + [rfc3339DateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]]; + } + return self; +} + ++ (id)sharedManager { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedManager = [[self alloc] init]; + }); + return sharedManager; +} + +- (void) pushEvent:(NSString *)event withAttributes:(NSDictionary *)attributeDictionary { + + if (!event) { + return; + } + + NSMutableDictionary *evt = [[NSMutableDictionary alloc] init]; + // mapbox-events stock attributes + [evt setObject:event forKey:@"event"]; + [evt setObject:[NSNumber numberWithInt:1] forKey:@"version"]; + [evt setObject:[self formatDate:[NSDate date]] forKey:@"created"]; + [evt setObject:self.instance forKey:@"instance"]; + [evt setObject:self.anonid forKey:@"anonid"]; + + // mapbox-events-ios stock attributes + [evt setValue:[rfc3339DateFormatter stringFromDate:[NSDate date]] forKey:@"deviceTimestamp"]; + [evt setValue:model forKey:@"model"]; + [evt setValue:iOSVersion forKey:@"operatingSystem"]; + [evt setValue:[self getDeviceOrientation] forKey:@"orientation"]; + [evt setValue:[[NSNumber alloc] initWithFloat:(100 * [UIDevice currentDevice].batteryLevel)] forKey:@"batteryLevel"]; + [evt setValue:scale forKey:@"resolution"]; + [evt setValue:carrier forKey:@"carrier"]; + + for (NSString *key in [attributeDictionary allKeys]) { + [evt setObject:[attributeDictionary valueForKey:key] forKey:key]; + } + + // Make Immutable Version + NSDictionary *finalEvent = [NSDictionary dictionaryWithDictionary:evt]; + + // Put On The Queue + [self.queue addObject:finalEvent]; + + // Has Flush Limit Been Reached? + if ((int)_queue.count >= (int)_flushAt) { + [self flush]; + } + + // Reset Timer (Initial Starting of Timer after first event is pushed) + [self startTimer]; +} + +- (void) flush { + if (_token == nil) { + NSLog(@"token hasn't been set yet, so no events can be sent. return"); + return; + } + + if (_flushAt > [_queue count]) { + NSLog(@"flush() flushAt (%lu) is greater than current queue count (%lu) so just return", _flushAt, [_queue count]); + return; + } + + // Create Array of Events to push to the Server + NSRange theRange = NSMakeRange(0, (int)_flushAt); + NSArray *events = [_queue subarrayWithRange:theRange]; + + // Update Queue to remove events sent to server + [_queue removeObjectsInRange:theRange]; + + // Send Array of Events to Server + [self postEvents:events]; + +} + +- (void) postEvents:(NSArray *)events { + // Setup URL Request + NSString *url = [NSString stringWithFormat:@"%@/events/v1?access_token=%@", _api, _token]; + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]]; + [request setValue:[self getUserAgent] forHTTPHeaderField:@"User-Agent"]; + [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; + [request setHTTPMethod:@"POST"]; + + // Convert Array of Dictionaries to JSON + if ([NSJSONSerialization isValidJSONObject:events]) { + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:events options:NSJSONWritingPrettyPrinted error:nil]; + [request setHTTPBody:jsonData]; + + // Send non blocking HTTP Request to server + [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:nil]; + } +} + +- (void) startTimer { + // Stop Timer if it already exists + if (_timer) { + [_timer invalidate]; + _timer = nil; + } + + // Start New Timer + NSTimeInterval interval = (double)((NSInteger)_flushAfter); + _timer = [NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(flush) userInfo:nil repeats:YES]; +} + +- (NSString *) getUserAgent { + + if (_appName != nil && _appVersion != nil && ([_userAgent rangeOfString:_appName].location == NSNotFound)) { + _userAgent = [NSString stringWithFormat:@"%@/%@ %@", _appName, _appVersion, _userAgent]; + } + return _userAgent; +} + +- (NSString *) formatDate:(NSDate *)date { + return [rfc3339DateFormatter stringFromDate:date]; +} + +- (NSString *) getDeviceOrientation { + switch ([UIDevice currentDevice].orientation) { + case UIDeviceOrientationUnknown: + return @"Unknown"; + break; + case UIDeviceOrientationPortrait: + return @"Portrait"; + break; + case UIDeviceOrientationPortraitUpsideDown: + return @"PortraitUpsideDown"; + break; + case UIDeviceOrientationLandscapeLeft: + return @"LandscapeLeft"; + break; + case UIDeviceOrientationLandscapeRight: + return @"LandscapeRight"; + break; + case UIDeviceOrientationFaceUp: + return @"FaceUp"; + break; + case UIDeviceOrientationFaceDown: + return @"FaceDown"; + break; + default: + return @"Default - Unknown"; + break; + } +} + +- (NSString *)getSysInfoByName:(char *)typeSpecifier +{ + size_t size; + sysctlbyname(typeSpecifier, NULL, &size, NULL, 0); + + char *answer = malloc(size); + sysctlbyname(typeSpecifier, answer, &size, NULL, 0); + + NSString *results = [NSString stringWithCString:answer encoding: NSUTF8StringEncoding]; + + free(answer); + return results; +} + +@end \ No newline at end of file From c4097fff2de10a198270756e85618e188314963f Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 20 Mar 2015 16:30:07 -0500 Subject: [PATCH 06/28] #1033 - Adding MGLMapboxEvents to MGLMapView --- platform/ios/MGLMapView.mm | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 6136eeb3c..981007df2 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -21,9 +21,9 @@ #import "NSArray+MGLAdditions.h" #import "NSDictionary+MGLAdditions.h" +#import "MGLMapboxEvents.h" #import "MGLMetricsLocationManager.h" - // Returns the path to the default cache database on this system. const std::string &defaultCacheDatabase() { static const std::string path = []() -> std::string { @@ -170,6 +170,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; if (accessToken) { mbglMap->setAccessToken((std::string)[accessToken cStringUsingEncoding:[NSString defaultCStringEncoding]]); + [[MGLMapboxEvents sharedManager] setAccessToken:accessToken]; } } @@ -210,6 +211,17 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; // setup accessibility // self.accessibilityLabel = @"Map"; + + // setup Metrics + MGLMapboxEvents *events = [MGLMapboxEvents sharedManager]; + NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"]; + NSString *appVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; + if (appName != nil) { + events.appName = appName; + } + if (appVersion != nil) { + events.appVersion = appVersion; + } // create GL view // From 8a73f2186afb1f58fe7ea469fb426a6115ee209e Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 20 Mar 2015 16:37:49 -0500 Subject: [PATCH 07/28] #1033 - Adding CoreTelephony dependency and fixing access token setting method name. --- gyp/platform-ios.gypi | 1 + platform/ios/MGLMapView.mm | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/gyp/platform-ios.gypi b/gyp/platform-ios.gypi index 738a4afa5..317b37b9b 100644 --- a/gyp/platform-ios.gypi +++ b/gyp/platform-ios.gypi @@ -45,6 +45,7 @@ 'ldflags': [ '-framework CoreGraphics', '-framework CoreLocation', + '-framework CoreTelephony', '-framework ImageIO', '-framework GLKit', '-framework MobileCoreServices', diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 981007df2..d6e7a16a2 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -170,7 +170,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; if (accessToken) { mbglMap->setAccessToken((std::string)[accessToken cStringUsingEncoding:[NSString defaultCStringEncoding]]); - [[MGLMapboxEvents sharedManager] setAccessToken:accessToken]; + [[MGLMapboxEvents sharedManager] setToken:accessToken]; } } From 263ae1a4cdd2b3ab318d98df46f3b8c337dade5a Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 20 Mar 2015 16:50:43 -0500 Subject: [PATCH 08/28] #1033 - Initial integration of anonymous location metrics reporting --- platform/ios/MGLMetricsLocationManager.m | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/ios/MGLMetricsLocationManager.m b/platform/ios/MGLMetricsLocationManager.m index 0732c04e3..65f6f0666 100644 --- a/platform/ios/MGLMetricsLocationManager.m +++ b/platform/ios/MGLMetricsLocationManager.m @@ -11,6 +11,7 @@ #import "MGLMetricsLocationManager.h" #import "CoreLocation/CoreLocation.h" +#import "MGLMapboxEvents.h" @interface MGLMetricsLocationManager() @@ -90,12 +91,14 @@ static MGLMetricsLocationManager *sharedManager = nil; - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { CLLocation *loc = (CLLocation *)[locations objectAtIndex:0]; NSLog(@"didUpdateLocations() called with %lu location in array. First Location = %f, %f", (unsigned long)locations.count, loc.coordinate.latitude, loc.coordinate.longitude); - + + // TODO Add Opt Out Checking When Built /** if (![[NSUserDefaults standardUserDefaults] boolForKey:@"mapbox_metrics_enabled_preference"]) { NSLog(@"Mapbox Metrics are not enabled, so return without sending in data."); return; } +*/ // Iterate through locations to pass all data for (CLLocation *loc in locations) { @@ -103,9 +106,8 @@ static MGLMetricsLocationManager *sharedManager = nil; [evt setValue:[[NSNumber alloc] initWithDouble:loc.coordinate.latitude] forKey:@"lat"]; [evt setValue:[[NSNumber alloc] initWithDouble:loc.coordinate.longitude] forKey:@"lng"]; [evt setValue:[[NSNumber alloc] initWithBool:_isBackground] forKey:@"isBackground"]; - [[MapboxEvents sharedManager] pushEvent:@"location" withAttributes:evt]; + [[MGLMapboxEvents sharedManager] pushEvent:@"location" withAttributes:evt]; } -*/ } - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { From 33f4dfffd2d9ef20d803e495c47b1248b51bd12c Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 20 Mar 2015 17:14:25 -0500 Subject: [PATCH 09/28] #1033 - Removing BackgroundStatus analytic --- include/mbgl/ios/MGLMetricsLocationManager.h | 2 -- platform/ios/MGLMetricsLocationManager.m | 7 ------- 2 files changed, 9 deletions(-) diff --git a/include/mbgl/ios/MGLMetricsLocationManager.h b/include/mbgl/ios/MGLMetricsLocationManager.h index 1630b848a..ce04ae9ef 100644 --- a/include/mbgl/ios/MGLMetricsLocationManager.h +++ b/include/mbgl/ios/MGLMetricsLocationManager.h @@ -19,6 +19,4 @@ - (void) startUpdatingLocation; - (void) stopUpdatingLocation; -- (void) setBackgroundStatus:(BOOL)isBackground; - @end diff --git a/platform/ios/MGLMetricsLocationManager.m b/platform/ios/MGLMetricsLocationManager.m index 65f6f0666..08a81b71b 100644 --- a/platform/ios/MGLMetricsLocationManager.m +++ b/platform/ios/MGLMetricsLocationManager.m @@ -16,13 +16,11 @@ @interface MGLMetricsLocationManager() @property (atomic) CLLocationManager *locationManager; -@property (atomic) BOOL isBackground; @end @implementation MGLMetricsLocationManager - static MGLMetricsLocationManager *sharedManager = nil; - (id) init { @@ -75,10 +73,6 @@ static MGLMetricsLocationManager *sharedManager = nil; } } -- (void) setBackgroundStatus:(BOOL)isBackground { - self.isBackground = isBackground; -} - - (void) startUpdatingLocation { [self.locationManager startUpdatingLocation]; } @@ -105,7 +99,6 @@ static MGLMetricsLocationManager *sharedManager = nil; NSMutableDictionary *evt = [[NSMutableDictionary alloc] init]; [evt setValue:[[NSNumber alloc] initWithDouble:loc.coordinate.latitude] forKey:@"lat"]; [evt setValue:[[NSNumber alloc] initWithDouble:loc.coordinate.longitude] forKey:@"lng"]; - [evt setValue:[[NSNumber alloc] initWithBool:_isBackground] forKey:@"isBackground"]; [[MGLMapboxEvents sharedManager] pushEvent:@"location" withAttributes:evt]; } } From de0aaff1f03a72d7eb1cb0ae56bb30d148a973af Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 23 Mar 2015 11:29:34 -0500 Subject: [PATCH 10/28] #1033 - Adding TODO to location where Opt Out and Metrics Disabled Checking will be implemented. --- platform/ios/MGLMapboxEvents.m | 10 ++++++++++ platform/ios/MGLMetricsLocationManager.m | 8 -------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index cd6ecbd0a..c8b742204 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -99,6 +99,16 @@ NSNumber *scale; - (void) pushEvent:(NSString *)event withAttributes:(NSDictionary *)attributeDictionary { + // TODO Add Opt Out Checking When Built + /** + if (![[NSUserDefaults standardUserDefaults] boolForKey:@"mapbox_metrics_enabled_preference"]) { + NSLog(@"Mapbox Metrics are not enabled, so return without sending in data."); + return; + } + */ + + // TODO - Add Metrics Disabled App Wide Check + if (!event) { return; } diff --git a/platform/ios/MGLMetricsLocationManager.m b/platform/ios/MGLMetricsLocationManager.m index 08a81b71b..5eac0370d 100644 --- a/platform/ios/MGLMetricsLocationManager.m +++ b/platform/ios/MGLMetricsLocationManager.m @@ -85,14 +85,6 @@ static MGLMetricsLocationManager *sharedManager = nil; - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { CLLocation *loc = (CLLocation *)[locations objectAtIndex:0]; NSLog(@"didUpdateLocations() called with %lu location in array. First Location = %f, %f", (unsigned long)locations.count, loc.coordinate.latitude, loc.coordinate.longitude); - - // TODO Add Opt Out Checking When Built -/** - if (![[NSUserDefaults standardUserDefaults] boolForKey:@"mapbox_metrics_enabled_preference"]) { - NSLog(@"Mapbox Metrics are not enabled, so return without sending in data."); - return; - } -*/ // Iterate through locations to pass all data for (CLLocation *loc in locations) { From 11eebc498fd751e704a4738708a1ca72a1c943ba Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 23 Mar 2015 11:48:53 -0500 Subject: [PATCH 11/28] #1033 - Initial location of map.load event --- platform/ios/MGLMapView.mm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index f20c43cae..fe835f7fe 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -387,6 +387,14 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; _regionChangeDelegateQueue = [NSOperationQueue new]; _regionChangeDelegateQueue.maxConcurrentOperationCount = 1; + + // Fire map.load + NSMutableDictionary *evt = [[NSMutableDictionary alloc] init]; + [evt setValue:[[NSNumber alloc] initWithDouble:mbglMap->getLatLng().latitude] forKey:@"lat"]; + [evt setValue:[[NSNumber alloc] initWithDouble:mbglMap->getLatLng().longitude] forKey:@"lng"]; + [evt setValue:[[NSNumber alloc] initWithDouble:mbglMap->getZoom()] forKey:@"zoom"]; + [[MGLMapboxEvents sharedManager] pushEvent:@"map.load" withAttributes:evt]; + return YES; } From 14c4ce75e194aae49077ea4d9e94fdd9cc45cdfa Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 23 Mar 2015 13:22:06 -0500 Subject: [PATCH 12/28] #1033 - First Map Zoom (aka `map.click` event) --- platform/ios/MGLMapView.mm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index fe835f7fe..7e2343b74 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -865,6 +865,16 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; [weakSelf unrotateIfNeededAnimated:YES]; [weakSelf notifyMapChange:@(mbgl::MapChangeRegionDidChangeAnimated)]; + + // Send Map Zoom Event + CGPoint ptInView = CGPointMake([doubleTap locationInView:doubleTap.view].x, [doubleTap locationInView:doubleTap.view].y); + CLLocationCoordinate2D coord = [self convertPoint:ptInView toCoordinateFromView:doubleTap.view]; + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + [dict setValue:[[NSNumber alloc] initWithDouble:coord.latitude] forKey:@"lat"]; + [dict setValue:[[NSNumber alloc] initWithDouble:coord.longitude] forKey:@"lng"]; + [dict setValue:[[NSNumber alloc] initWithDouble:[weakSelf zoomLevel]] forKey:@"zoom"]; + + [[MGLMapboxEvents sharedManager] pushEvent:@"map.click" withAttributes:dict]; }]; } } From 8b2d18814e049678808de3aa82dac9919a20ddaa Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 23 Mar 2015 13:25:39 -0500 Subject: [PATCH 13/28] #1033 - Map Zoom out event --- platform/ios/MGLMapView.mm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 7e2343b74..6ba95e61b 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -902,6 +902,16 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; [weakSelf unrotateIfNeededAnimated:YES]; [weakSelf notifyMapChange:@(mbgl::MapChangeRegionDidChangeAnimated)]; + + // Send Map Zoom Event + CGPoint ptInView = CGPointMake([twoFingerTap locationInView:twoFingerTap.view].x, [twoFingerTap locationInView:twoFingerTap.view].y); + CLLocationCoordinate2D coord = [self convertPoint:ptInView toCoordinateFromView:twoFingerTap.view]; + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + [dict setValue:[[NSNumber alloc] initWithDouble:coord.latitude] forKey:@"lat"]; + [dict setValue:[[NSNumber alloc] initWithDouble:coord.longitude] forKey:@"lng"]; + [dict setValue:[[NSNumber alloc] initWithDouble:[weakSelf zoomLevel]] forKey:@"zoom"]; + + [[MGLMapboxEvents sharedManager] pushEvent:@"map.click" withAttributes:dict]; }]; } } From 4b5158d0fecdfd7cbf97d02cffd7bf3929bbfe2e Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 23 Mar 2015 13:30:49 -0500 Subject: [PATCH 14/28] #1033 - Add Quick Zoom Event --- platform/ios/MGLMapView.mm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 6ba95e61b..bd6312c12 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -943,6 +943,16 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; [self unrotateIfNeededAnimated:YES]; [self notifyMapChange:@(mbgl::MapChangeRegionDidChangeAnimated)]; + + // Send Map Zoom Event + CGPoint ptInView = CGPointMake([quickZoom locationInView:quickZoom.view].x, [quickZoom locationInView:quickZoom.view].y); + CLLocationCoordinate2D coord = [self convertPoint:ptInView toCoordinateFromView:quickZoom.view]; + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + [dict setValue:[[NSNumber alloc] initWithDouble:coord.latitude] forKey:@"lat"]; + [dict setValue:[[NSNumber alloc] initWithDouble:coord.longitude] forKey:@"lng"]; + [dict setValue:[[NSNumber alloc] initWithDouble:[self zoomLevel]] forKey:@"zoom"]; + + [[MGLMapboxEvents sharedManager] pushEvent:@"map.click" withAttributes:dict]; } } From a4332736f700512aa463086c137e5e2ebf2a4856 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 23 Mar 2015 16:42:01 -0500 Subject: [PATCH 15/28] #1033 - Adding Gesture tracking for all 7 supported gestures. DRYing out code. --- platform/ios/MGLMapView.mm | 60 ++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index bd6312c12..3aa0ef2e0 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -606,6 +606,8 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; - (void)handlePanGesture:(UIPanGestureRecognizer *)pan { + [self trackGestureEvent:@"Pan" forRecognizer:pan]; + if ( ! self.isScrollEnabled) return; mbglMap->cancelTransitions(); @@ -662,6 +664,8 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch { + [self trackGestureEvent:@"Pinch" forRecognizer:pinch]; + if ( ! self.isZoomEnabled) return; if (mbglMap->getZoom() <= mbglMap->getMinZoom() && pinch.scale < 1) return; @@ -696,6 +700,8 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; - (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate { + [self trackGestureEvent:@"Rotation" forRecognizer:rotate]; + if ( ! self.isRotateEnabled) return; mbglMap->cancelTransitions(); @@ -734,8 +740,10 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; - (void)handleSingleTapGesture:(UITapGestureRecognizer *)singleTap { + [self trackGestureEvent:@"SingleTap" forRecognizer:singleTap]; + CGPoint tapPoint = [singleTap locationInView:self]; - + // tolerances based on touch size & typical marker aspect ratio CGFloat toleranceWidth = 50; CGFloat toleranceHeight = 75; @@ -846,6 +854,8 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; - (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap { + [self trackGestureEvent:@"DoubleTap" forRecognizer:doubleTap]; + if ( ! self.isZoomEnabled) return; mbglMap->cancelTransitions(); @@ -865,22 +875,14 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; [weakSelf unrotateIfNeededAnimated:YES]; [weakSelf notifyMapChange:@(mbgl::MapChangeRegionDidChangeAnimated)]; - - // Send Map Zoom Event - CGPoint ptInView = CGPointMake([doubleTap locationInView:doubleTap.view].x, [doubleTap locationInView:doubleTap.view].y); - CLLocationCoordinate2D coord = [self convertPoint:ptInView toCoordinateFromView:doubleTap.view]; - NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; - [dict setValue:[[NSNumber alloc] initWithDouble:coord.latitude] forKey:@"lat"]; - [dict setValue:[[NSNumber alloc] initWithDouble:coord.longitude] forKey:@"lng"]; - [dict setValue:[[NSNumber alloc] initWithDouble:[weakSelf zoomLevel]] forKey:@"zoom"]; - - [[MGLMapboxEvents sharedManager] pushEvent:@"map.click" withAttributes:dict]; }]; } } - (void)handleTwoFingerTapGesture:(UITapGestureRecognizer *)twoFingerTap { + [self trackGestureEvent:@"TwoFingerTap" forRecognizer:twoFingerTap]; + if ( ! self.isZoomEnabled) return; if (mbglMap->getZoom() == mbglMap->getMinZoom()) return; @@ -902,22 +904,14 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; [weakSelf unrotateIfNeededAnimated:YES]; [weakSelf notifyMapChange:@(mbgl::MapChangeRegionDidChangeAnimated)]; - - // Send Map Zoom Event - CGPoint ptInView = CGPointMake([twoFingerTap locationInView:twoFingerTap.view].x, [twoFingerTap locationInView:twoFingerTap.view].y); - CLLocationCoordinate2D coord = [self convertPoint:ptInView toCoordinateFromView:twoFingerTap.view]; - NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; - [dict setValue:[[NSNumber alloc] initWithDouble:coord.latitude] forKey:@"lat"]; - [dict setValue:[[NSNumber alloc] initWithDouble:coord.longitude] forKey:@"lng"]; - [dict setValue:[[NSNumber alloc] initWithDouble:[weakSelf zoomLevel]] forKey:@"zoom"]; - - [[MGLMapboxEvents sharedManager] pushEvent:@"map.click" withAttributes:dict]; }]; } } - (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom { + [self trackGestureEvent:@"LongPress" forRecognizer:quickZoom]; + if ( ! self.isZoomEnabled) return; mbglMap->cancelTransitions(); @@ -943,16 +937,6 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; [self unrotateIfNeededAnimated:YES]; [self notifyMapChange:@(mbgl::MapChangeRegionDidChangeAnimated)]; - - // Send Map Zoom Event - CGPoint ptInView = CGPointMake([quickZoom locationInView:quickZoom.view].x, [quickZoom locationInView:quickZoom.view].y); - CLLocationCoordinate2D coord = [self convertPoint:ptInView toCoordinateFromView:quickZoom.view]; - NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; - [dict setValue:[[NSNumber alloc] initWithDouble:coord.latitude] forKey:@"lat"]; - [dict setValue:[[NSNumber alloc] initWithDouble:coord.longitude] forKey:@"lng"]; - [dict setValue:[[NSNumber alloc] initWithDouble:[self zoomLevel]] forKey:@"zoom"]; - - [[MGLMapboxEvents sharedManager] pushEvent:@"map.click" withAttributes:dict]; } } @@ -963,6 +947,20 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; return ([validSimultaneousGestures containsObject:gestureRecognizer] && [validSimultaneousGestures containsObject:otherGestureRecognizer]); } +- (void) trackGestureEvent:(NSString *) gesture forRecognizer:(UIGestureRecognizer *) recognizer +{ + // Send Map Zoom Event + CGPoint ptInView = CGPointMake([recognizer locationInView:recognizer.view].x, [recognizer locationInView:recognizer.view].y); + CLLocationCoordinate2D coord = [self convertPoint:ptInView toCoordinateFromView:recognizer.view]; + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + [dict setValue:[[NSNumber alloc] initWithDouble:coord.latitude] forKey:@"lat"]; + [dict setValue:[[NSNumber alloc] initWithDouble:coord.longitude] forKey:@"lng"]; + [dict setValue:[[NSNumber alloc] initWithDouble:[self zoomLevel]] forKey:@"zoom"]; + [dict setValue:gesture forKey:@"gesture"]; + + [[MGLMapboxEvents sharedManager] pushEvent:@"map.click" withAttributes:dict]; +} + #pragma mark - Properties - #pragma clang diagnostic push From 9b6ea527225a5a99f8c8f8ad61e984b7bafb8b10 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 23 Mar 2015 17:13:47 -0500 Subject: [PATCH 16/28] #1033 - Adding map.dragend event --- platform/ios/MGLMapView.mm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 3aa0ef2e0..cd25dda0b 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -659,6 +659,16 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; [weakSelf notifyMapChange:@(mbgl::MapChangeRegionDidChangeAnimated)]; }]; } + + // Send Map Drag End Event + CGPoint ptInView = CGPointMake([pan locationInView:pan.view].x, [pan locationInView:pan.view].y); + CLLocationCoordinate2D coord = [self convertPoint:ptInView toCoordinateFromView:pan.view]; + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + [dict setValue:[[NSNumber alloc] initWithDouble:coord.latitude] forKey:@"lat"]; + [dict setValue:[[NSNumber alloc] initWithDouble:coord.longitude] forKey:@"lng"]; + [dict setValue:[[NSNumber alloc] initWithDouble:[self zoomLevel]] forKey:@"zoom"]; + + [[MGLMapboxEvents sharedManager] pushEvent:@"map.dragend" withAttributes:dict]; } } From 26a3ef3c7139a71d13ed6a6f50bc70725b5350f7 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 23 Mar 2015 17:31:30 -0500 Subject: [PATCH 17/28] #1033 - Adding Push Enabled attribute --- platform/ios/MGLMapView.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index cd25dda0b..6fa2a1e8b 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -668,6 +668,8 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; [dict setValue:[[NSNumber alloc] initWithDouble:coord.longitude] forKey:@"lng"]; [dict setValue:[[NSNumber alloc] initWithDouble:[self zoomLevel]] forKey:@"zoom"]; + [dict setValue:[[NSNumber alloc] initWithBool:[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]] forKey:@"enabled.push"]; + [[MGLMapboxEvents sharedManager] pushEvent:@"map.dragend" withAttributes:dict]; } } From 91cae4f44dc432568db6336de25e9140d884aaac Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 23 Mar 2015 17:36:36 -0500 Subject: [PATCH 18/28] #1033 - Renaming LongPress to QuickZoom for gesture event --- platform/ios/MGLMapView.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 6fa2a1e8b..6f30b7b81 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -922,7 +922,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; - (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom { - [self trackGestureEvent:@"LongPress" forRecognizer:quickZoom]; + [self trackGestureEvent:@"QuickZoom" forRecognizer:quickZoom]; if ( ! self.isZoomEnabled) return; From 11aef0d9d097feb98f4f1b9d6060926b0bd4fca6 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 23 Mar 2015 18:29:13 -0500 Subject: [PATCH 19/28] #1033 - Adding accessibilityFontScale attribute --- platform/ios/MGLMapboxEvents.m | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index c8b742204..5c5442444 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -129,6 +129,7 @@ NSNumber *scale; [evt setValue:[[NSNumber alloc] initWithFloat:(100 * [UIDevice currentDevice].batteryLevel)] forKey:@"batteryLevel"]; [evt setValue:scale forKey:@"resolution"]; [evt setValue:carrier forKey:@"carrier"]; + [evt setValue:[NSNumber numberWithInt:[self getContentSizeScale]] forKey:@"accessibilityFontScale"]; for (NSString *key in [attributeDictionary allKeys]) { [evt setObject:[attributeDictionary valueForKey:key] forKey:key]; @@ -243,6 +244,38 @@ NSNumber *scale; } } +- (int) getContentSizeScale { + NSString *sc = [UIApplication sharedApplication].preferredContentSizeCategory; + + if ([sc isEqualToString:UIContentSizeCategoryExtraSmall]) { + return -3; + } else if ([sc isEqualToString:UIContentSizeCategorySmall]) { + return -2; + } else if ([sc isEqualToString:UIContentSizeCategoryMedium]) { + return -1; + } else if ([sc isEqualToString:UIContentSizeCategoryLarge]) { + return 0; + } else if ([sc isEqualToString:UIContentSizeCategoryExtraLarge]) { + return 1; + } else if ([sc isEqualToString:UIContentSizeCategoryExtraExtraLarge]) { + return 2; + } else if ([sc isEqualToString:UIContentSizeCategoryExtraExtraExtraLarge]) { + return 3; + } else if ([sc isEqualToString:UIContentSizeCategoryAccessibilityMedium]) { + return -11; + } else if ([sc isEqualToString:UIContentSizeCategoryAccessibilityLarge]) { + return 10; + } else if ([sc isEqualToString:UIContentSizeCategoryAccessibilityExtraLarge]) { + return 11; + } else if ([sc isEqualToString:UIContentSizeCategoryAccessibilityExtraExtraLarge]) { + return 12; + } else if ([sc isEqualToString:UIContentSizeCategoryAccessibilityExtraExtraExtraLarge]) { + return 13; + } + return -9999; +} + + - (NSString *)getSysInfoByName:(char *)typeSpecifier { size_t size; From 99049dc6b5872e93db52e1a48fae6ed90e45ecd5 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 23 Mar 2015 19:32:34 -0500 Subject: [PATCH 20/28] #1033 - Moving map.load to background thread. Moving enabled.push to map.load event. Adding enabled.email check. --- platform/ios/MGLMapView.mm | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 6f30b7b81..000e63956 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -388,12 +388,30 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; _regionChangeDelegateQueue.maxConcurrentOperationCount = 1; - // Fire map.load - NSMutableDictionary *evt = [[NSMutableDictionary alloc] init]; - [evt setValue:[[NSNumber alloc] initWithDouble:mbglMap->getLatLng().latitude] forKey:@"lat"]; - [evt setValue:[[NSNumber alloc] initWithDouble:mbglMap->getLatLng().longitude] forKey:@"lng"]; - [evt setValue:[[NSNumber alloc] initWithDouble:mbglMap->getZoom()] forKey:@"zoom"]; - [[MGLMapboxEvents sharedManager] pushEvent:@"map.load" withAttributes:evt]; + // Fire map.load on a background thread + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + NSMutableDictionary *evt = [[NSMutableDictionary alloc] init]; + [evt setValue:[[NSNumber alloc] initWithDouble:mbglMap->getLatLng().latitude] forKey:@"lat"]; + [evt setValue:[[NSNumber alloc] initWithDouble:mbglMap->getLatLng().longitude] forKey:@"lng"]; + [evt setValue:[[NSNumber alloc] initWithDouble:mbglMap->getZoom()] forKey:@"zoom"]; + [[MGLMapboxEvents sharedManager] pushEvent:@"map.load" withAttributes:evt]; + + [evt setValue:[[NSNumber alloc] initWithBool:[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]] forKey:@"enabled.push"]; + + NSString *email = @"Unknown"; + Class MFMailComposeViewController = NSClassFromString(@"MFMailComposeViewController"); + if (MFMailComposeViewController) { + SEL canSendMail = NSSelectorFromString(@"canSendMail"); + BOOL sendMail = ((BOOL (*)(id, SEL))[MFMailComposeViewController methodForSelector:canSendMail])(MFMailComposeViewController, canSendMail); + email = [NSString stringWithFormat:@"%i", sendMail]; + } + [evt setValue:email forKey:@"enabled.email"]; + + + + + }); return YES; } @@ -668,8 +686,6 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; [dict setValue:[[NSNumber alloc] initWithDouble:coord.longitude] forKey:@"lng"]; [dict setValue:[[NSNumber alloc] initWithDouble:[self zoomLevel]] forKey:@"zoom"]; - [dict setValue:[[NSNumber alloc] initWithBool:[[UIApplication sharedApplication] isRegisteredForRemoteNotifications]] forKey:@"enabled.push"]; - [[MGLMapboxEvents sharedManager] pushEvent:@"map.dragend" withAttributes:dict]; } } From 3e062d0e202c018f45979cd6669c26a2c5c195b0 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Tue, 24 Mar 2015 10:02:13 -0500 Subject: [PATCH 21/28] #1033 - Flush all events to server when app enters background --- include/mbgl/ios/MGLMapboxEvents.h | 2 ++ platform/ios/MGLMapView.mm | 7 +++---- platform/ios/MGLMapboxEvents.m | 10 +++++++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/include/mbgl/ios/MGLMapboxEvents.h b/include/mbgl/ios/MGLMapboxEvents.h index c0cff7c2b..bb28ec26c 100644 --- a/include/mbgl/ios/MGLMapboxEvents.h +++ b/include/mbgl/ios/MGLMapboxEvents.h @@ -21,4 +21,6 @@ - (void) pushEvent:(NSString *)event withAttributes:(NSDictionary *)attributeDictionary; +- (void) flush; + @end \ No newline at end of file diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 000e63956..82114672d 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -407,10 +407,6 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; email = [NSString stringWithFormat:@"%i", sendMail]; } [evt setValue:email forKey:@"enabled.email"]; - - - - }); return YES; @@ -590,6 +586,9 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; - (void)appDidBackground:(NSNotification *)notification { + // Flush Any Events Still In Queue + [[MGLMapboxEvents sharedManager] flush]; + mbglMap->stop(); [self.glView deleteDrawable]; diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index 5c5442444..a91a0ed94 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -156,13 +156,17 @@ NSNumber *scale; return; } + + int upper = (int)_flushAt; if (_flushAt > [_queue count]) { - NSLog(@"flush() flushAt (%lu) is greater than current queue count (%lu) so just return", _flushAt, [_queue count]); - return; + if ([_queue count] == 0) { + return; + } + upper = (int)[_queue count]; } // Create Array of Events to push to the Server - NSRange theRange = NSMakeRange(0, (int)_flushAt); + NSRange theRange = NSMakeRange(0, upper); NSArray *events = [_queue subarrayWithRange:theRange]; // Update Queue to remove events sent to server From d1a95e21a7cc5e50a1610ff860170d572470a052 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Tue, 24 Mar 2015 10:16:16 -0500 Subject: [PATCH 22/28] #1033 - Adding wifi network name attribute --- platform/ios/MGLMapboxEvents.m | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index a91a0ed94..563aa3cdb 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -14,6 +14,7 @@ #import #import #include +#import @interface MGLMapboxEvents() @@ -129,6 +130,7 @@ NSNumber *scale; [evt setValue:[[NSNumber alloc] initWithFloat:(100 * [UIDevice currentDevice].batteryLevel)] forKey:@"batteryLevel"]; [evt setValue:scale forKey:@"resolution"]; [evt setValue:carrier forKey:@"carrier"]; + [evt setValue:[self getWifiNetworkName] forKey:@"wifi"]; [evt setValue:[NSNumber numberWithInt:[self getContentSizeScale]] forKey:@"accessibilityFontScale"]; for (NSString *key in [attributeDictionary allKeys]) { @@ -294,4 +296,23 @@ NSNumber *scale; return results; } +- (NSString *) getWifiNetworkName { + + NSString *ssid = @""; + CFArrayRef interfaces = CNCopySupportedInterfaces(); + if (interfaces) { + NSDictionary *info = (__bridge NSDictionary *)CNCopyCurrentNetworkInfo(CFArrayGetValueAtIndex(interfaces, 0)); + if (info) { + ssid = info[@"SSID"]; + } else { + ssid = @"<>"; + } + } else { + ssid = @"<>"; + } + + return ssid; +} + + @end \ No newline at end of file From 2da729dca09133442142be77c948281857da4b50 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Tue, 24 Mar 2015 10:33:35 -0500 Subject: [PATCH 23/28] #1033 - Fix automatic overwriting of anonId value --- platform/ios/MGLMapboxEvents.m | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index 563aa3cdb..cbb245859 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -40,6 +40,8 @@ NSNumber *scale; - (id) init { self = [super init]; if (self) { + + // Configure Events Infrastructure _queue = [[NSMutableArray alloc] init]; _flushAt = 20; _flushAfter = 10000; @@ -64,9 +66,6 @@ NSNumber *scale; _anonid = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; } - - // Get Vendor ID - anonId = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; model = [self getSysInfoByName:"hw.machine"]; iOSVersion = [NSString stringWithFormat:@"%@ %@", [UIDevice currentDevice].systemName, [UIDevice currentDevice].systemVersion]; if ([UIScreen instancesRespondToSelector:@selector(nativeScale)]) { From 81f6c5cab28e62900b1e291dd3ae0094cc70c105 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Tue, 24 Mar 2015 10:35:49 -0500 Subject: [PATCH 24/28] #1033 - Removing extraneous instance variable of anonId --- platform/ios/MGLMapboxEvents.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index cbb245859..52a6f464c 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -30,7 +30,6 @@ static MGLMapboxEvents *sharedManager = nil; -NSString *anonId = nil; NSDateFormatter *rfc3339DateFormatter = nil; NSString *model; NSString *iOSVersion; @@ -40,7 +39,7 @@ NSNumber *scale; - (id) init { self = [super init]; if (self) { - + // Configure Events Infrastructure _queue = [[NSMutableArray alloc] init]; _flushAt = 20; From 5acf518ea6c7fe1c52e63922619ede5ba3f2404f Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Tue, 24 Mar 2015 10:37:59 -0500 Subject: [PATCH 25/28] #1033 - Adding blank Settings.bundle infrastructure and ensuring it's loaded into memory --- ios/app/Settings.bundle/Root.plist | 61 ++++++++++++++++++ ios/app/Settings.bundle/en.lproj/Root.strings | Bin 0 -> 546 bytes platform/ios/MGLMapboxEvents.m | 18 ++++++ 3 files changed, 79 insertions(+) create mode 100644 ios/app/Settings.bundle/Root.plist create mode 100644 ios/app/Settings.bundle/en.lproj/Root.strings diff --git a/ios/app/Settings.bundle/Root.plist b/ios/app/Settings.bundle/Root.plist new file mode 100644 index 000000000..fa9830605 --- /dev/null +++ b/ios/app/Settings.bundle/Root.plist @@ -0,0 +1,61 @@ + + + + + PreferenceSpecifiers + + + Title + Group + Type + PSGroupSpecifier + + + AutocapitalizationType + None + AutocorrectionType + No + DefaultValue + + IsSecure + + Key + name_preference + KeyboardType + Alphabet + Title + Name + Type + PSTextFieldSpecifier + + + DefaultValue + + Key + enabled_preference + Title + Enabled + Type + PSToggleSwitchSpecifier + + + DefaultValue + 0.5 + Key + slider_preference + MaximumValue + 1 + MaximumValueImage + + MinimumValue + 0 + MinimumValueImage + + Type + PSSliderSpecifier + + + StringsTable + Root + + diff --git a/ios/app/Settings.bundle/en.lproj/Root.strings b/ios/app/Settings.bundle/en.lproj/Root.strings new file mode 100644 index 0000000000000000000000000000000000000000..8cd87b9d6b20c1fbf87bd4db3db267fca5ad4df9 GIT binary patch literal 546 zcmaixOHRW;5JYRuDMndFh#Ua1V1d}N;sVAV2TO?uC3a9aJn*VxFrY}tnon0(S66#J z-d9>G>6W!ur(SDqlp`9nn~*(m%iWnv?yq`Qfp6XbK1?+om~~#r)ZnhkYQU_VbfjuT zHNn`CX<0sd*m1A}>&5sU$akD=GTXJ1e literal 0 HcmV?d00001 diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index 52a6f464c..3178a460d 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -40,6 +40,24 @@ NSNumber *scale; self = [super init]; if (self) { + // Put Settings bundle into memory + NSString *settingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"]; + if(!settingsBundle) { + NSLog(@"Could not find Settings.bundle"); + } else { + NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent:@"Root.plist"]]; + NSArray *preferences = [settings objectForKey:@"PreferenceSpecifiers"]; + NSMutableDictionary *defaultsToRegister = [[NSMutableDictionary alloc] initWithCapacity:[preferences count]]; + for(NSDictionary *prefSpecification in preferences) { + NSString *key = [prefSpecification objectForKey:@"Key"]; + if(key && [[prefSpecification allKeys] containsObject:@"DefaultValue"]) { + [defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key]; + } + } + + [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister]; + } + // Configure Events Infrastructure _queue = [[NSMutableArray alloc] init]; _flushAt = 20; From 25381187be68f9a170082aa732bb3df61af34baf Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Tue, 24 Mar 2015 10:50:26 -0500 Subject: [PATCH 26/28] #1033 - Setting up Opt Out UI in Settings.app. Checking for Opt Out status at event push time. --- ios/app/Settings.bundle/Root.plist | 84 ++++++++++-------------------- platform/ios/MGLMapboxEvents.m | 13 +++-- 2 files changed, 33 insertions(+), 64 deletions(-) diff --git a/ios/app/Settings.bundle/Root.plist b/ios/app/Settings.bundle/Root.plist index fa9830605..513836e92 100644 --- a/ios/app/Settings.bundle/Root.plist +++ b/ios/app/Settings.bundle/Root.plist @@ -1,61 +1,31 @@ - - PreferenceSpecifiers - - - Title - Group - Type - PSGroupSpecifier - - - AutocapitalizationType - None - AutocorrectionType - No - DefaultValue - - IsSecure - - Key - name_preference - KeyboardType - Alphabet - Title - Name - Type - PSTextFieldSpecifier - - - DefaultValue - - Key - enabled_preference - Title - Enabled - Type - PSToggleSwitchSpecifier - - - DefaultValue - 0.5 - Key - slider_preference - MaximumValue - 1 - MaximumValueImage - - MinimumValue - 0 - MinimumValueImage - - Type - PSSliderSpecifier - - - StringsTable - Root - + + PreferenceSpecifiers + + + Title + Privacy Settings + Type + PSGroupSpecifier + + + DefaultValue + + Key + mapbox_metrics_enabled_preference + Title + Mapbox Metrics + Type + PSToggleSwitchSpecifier + TrueValue + + FalseValue + + + + StringsTable + Root + diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index 3178a460d..11303bc0e 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -116,13 +116,12 @@ NSNumber *scale; - (void) pushEvent:(NSString *)event withAttributes:(NSDictionary *)attributeDictionary { - // TODO Add Opt Out Checking When Built - /** - if (![[NSUserDefaults standardUserDefaults] boolForKey:@"mapbox_metrics_enabled_preference"]) { - NSLog(@"Mapbox Metrics are not enabled, so return without sending in data."); - return; - } - */ + // Opt Out Checking When Built + if (![[NSUserDefaults standardUserDefaults] boolForKey:@"mapbox_metrics_enabled_preference"]) { + NSLog(@"Mapbox Metrics are not enabled, so clear any currently stored events, and return without sending in data."); + [_queue removeAllObjects]; + return; + } // TODO - Add Metrics Disabled App Wide Check From 308d382bd28b0a03eb5bf427f9ff83316fea3c85 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Tue, 24 Mar 2015 11:33:08 -0500 Subject: [PATCH 27/28] #1033 - Building Mapbox Metrics Disabled UI in Settings.app and functionality in Events tracking infrastructure --- ios/app/Settings.bundle/Root.plist | 70 ++++++++++++++++++------------ platform/ios/MGLMapboxEvents.m | 8 +++- 2 files changed, 49 insertions(+), 29 deletions(-) diff --git a/ios/app/Settings.bundle/Root.plist b/ios/app/Settings.bundle/Root.plist index 513836e92..e09c22591 100644 --- a/ios/app/Settings.bundle/Root.plist +++ b/ios/app/Settings.bundle/Root.plist @@ -1,31 +1,47 @@ - - PreferenceSpecifiers - - - Title - Privacy Settings - Type - PSGroupSpecifier - - - DefaultValue - - Key - mapbox_metrics_enabled_preference - Title - Mapbox Metrics - Type - PSToggleSwitchSpecifier - TrueValue - - FalseValue - - - - StringsTable - Root - + + PreferenceSpecifiers + + + Title + Privacy Settings + Type + PSGroupSpecifier + + + DefaultValue + + Key + mapbox_metrics_disabled + Title + Mapbox Metrics Are Disabled + Type + PSTitleValueSpecifier + TrueValue + + FalseValue + + + + + StringsTable + Root + diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index 11303bc0e..a231b5115 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -123,7 +123,12 @@ NSNumber *scale; return; } - // TODO - Add Metrics Disabled App Wide Check + // Add Metrics Disabled App Wide Check + if ([[NSUserDefaults standardUserDefaults] objectForKey:@"mapbox_metrics_disabled"] != nil) { + NSLog(@"Mapbox Metrics have been disabled for this app."); + [_queue removeAllObjects]; + return; + } if (!event) { return; @@ -173,7 +178,6 @@ NSNumber *scale; return; } - int upper = (int)_flushAt; if (_flushAt > [_queue count]) { if ([_queue count] == 0) { From 708ae14468222ae89aae6798063cf21b04635503 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Tue, 24 Mar 2015 11:41:47 -0500 Subject: [PATCH 28/28] #1033 - Reverting to Metrics Enabled Preference in System.app --- ios/app/Settings.bundle/Root.plist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/app/Settings.bundle/Root.plist b/ios/app/Settings.bundle/Root.plist index e09c22591..4e50f0ef3 100644 --- a/ios/app/Settings.bundle/Root.plist +++ b/ios/app/Settings.bundle/Root.plist @@ -10,6 +10,7 @@ Type PSGroupSpecifier + DefaultValue @@ -39,7 +40,6 @@ FalseValue - --> StringsTable Root