From b5f7e1c8d46989c70c6649fb991a021d0da80d1c Mon Sep 17 00:00:00 2001 From: Christian Wellenbrock Date: Tue, 4 Feb 2014 10:36:51 +0100 Subject: [PATCH 01/11] Add -[UIDevice aiCreateUuid] --- AdjustIo/AIAdditions/UIDevice+AIAdditions.h | 1 + AdjustIo/AIAdditions/UIDevice+AIAdditions.m | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/AdjustIo/AIAdditions/UIDevice+AIAdditions.h b/AdjustIo/AIAdditions/UIDevice+AIAdditions.h index f928cb894..62707848a 100644 --- a/AdjustIo/AIAdditions/UIDevice+AIAdditions.h +++ b/AdjustIo/AIAdditions/UIDevice+AIAdditions.h @@ -16,5 +16,6 @@ - (NSString *)aiMacAddress; - (NSString *)aiDeviceType; - (NSString *)aiDeviceName; +- (NSString *)aiCreateUuid; @end diff --git a/AdjustIo/AIAdditions/UIDevice+AIAdditions.m b/AdjustIo/AIAdditions/UIDevice+AIAdditions.m index f1770f371..d1af99587 100644 --- a/AdjustIo/AIAdditions/UIDevice+AIAdditions.m +++ b/AdjustIo/AIAdditions/UIDevice+AIAdditions.m @@ -101,4 +101,13 @@ - (NSString *)aiDeviceName { return machine; } +- (NSString *)aiCreateUuid { + CFUUIDRef newUniqueId = CFUUIDCreate(kCFAllocatorDefault); + CFStringRef stringRef = CFUUIDCreateString(kCFAllocatorDefault, newUniqueId); + NSString *uuidString = (__bridge_transfer NSString*)stringRef; + NSString *lowerUuid = [uuidString lowercaseString]; + CFRelease(newUniqueId); + return lowerUuid; +} + @end From d55f0a70cbad32e4c4ac5b2caca9dc9e2cc7a146 Mon Sep 17 00:00:00 2001 From: Christian Wellenbrock Date: Tue, 4 Feb 2014 11:12:51 +0100 Subject: [PATCH 02/11] Use dot notation for file names --- AdjustIo/AIActivityHandler.m | 4 ++-- AdjustIo/AIPackageHandler.m | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/AdjustIo/AIActivityHandler.m b/AdjustIo/AIActivityHandler.m index 0701a2726..03a2417f6 100644 --- a/AdjustIo/AIActivityHandler.m +++ b/AdjustIo/AIActivityHandler.m @@ -283,7 +283,7 @@ - (BOOL)updateActivityState { - (void)readActivityState { @try { - NSString *filename = [self activityStateFilename]; + NSString *filename = self.activityStateFilename; id object = [NSKeyedUnarchiver unarchiveObjectWithFile:filename]; if ([object isKindOfClass:[AIActivityState class]]) { self.activityState = object; @@ -303,7 +303,7 @@ - (void)readActivityState { } - (void)writeActivityState { - NSString *filename = [self activityStateFilename]; + NSString *filename = self.activityStateFilename; BOOL result = [NSKeyedArchiver archiveRootObject:self.activityState toFile:filename]; if (result == YES) { [AIUtil excludeFromBackup:filename]; diff --git a/AdjustIo/AIPackageHandler.m b/AdjustIo/AIPackageHandler.m index eddb05c88..23539898a 100644 --- a/AdjustIo/AIPackageHandler.m +++ b/AdjustIo/AIPackageHandler.m @@ -123,7 +123,7 @@ - (void)sendNextInternal { #pragma mark - private - (void)readPackageQueue { @try { - NSString *filename = [self packageQueueFilename]; + NSString *filename = self.packageQueueFilename; id object = [NSKeyedUnarchiver unarchiveObjectWithFile:filename]; if ([object isKindOfClass:[NSArray class]]) { self.packageQueue = object; @@ -143,7 +143,7 @@ - (void)readPackageQueue { } - (void)writePackageQueue { - NSString *filename = [self packageQueueFilename]; + NSString *filename = self.packageQueueFilename; BOOL result = [NSKeyedArchiver archiveRootObject:self.packageQueue toFile:filename]; if (result == YES) { [AIUtil excludeFromBackup:filename]; From eaaf14728a69dd3fbbe41f8ce715e0c45fe359a3 Mon Sep 17 00:00:00 2001 From: Christian Wellenbrock Date: Tue, 4 Feb 2014 11:13:41 +0100 Subject: [PATCH 03/11] Add ActivityState.uuid, create when needed --- AdjustIo/AIActivityState.h | 6 +++++- AdjustIo/AIActivityState.m | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/AdjustIo/AIActivityState.h b/AdjustIo/AIActivityState.h index a878e52e6..717a471e3 100644 --- a/AdjustIo/AIActivityState.h +++ b/AdjustIo/AIActivityState.h @@ -10,6 +10,9 @@ @interface AIActivityState : NSObject +// persistent data +@property (nonatomic, copy) NSString *uuid; + // global counters @property (nonatomic, assign) int eventCount; @property (nonatomic, assign) int sessionCount; @@ -19,8 +22,9 @@ @property (nonatomic, assign) double sessionLength; // all durations in seconds @property (nonatomic, assign) double timeSpent; @property (nonatomic, assign) double lastActivity; // all times in seconds since 1970 - @property (nonatomic, assign) double createdAt; + +// not persisted, only injected @property (nonatomic, assign) double lastInterval; - (void)resetSessionAttributes:(double)now; diff --git a/AdjustIo/AIActivityState.m b/AdjustIo/AIActivityState.m index 528f7a149..efb691e45 100644 --- a/AdjustIo/AIActivityState.m +++ b/AdjustIo/AIActivityState.m @@ -8,6 +8,7 @@ #import "AIActivityState.h" #import "AIPackageBuilder.h" +#import "UIDevice+AIAdditions.h" #pragma mark public implementation @@ -17,6 +18,9 @@ - (id)init { self = [super init]; if (self == nil) return nil; + // create UUID for new devices + self.uuid = [UIDevice.currentDevice aiCreateUuid]; + self.eventCount = 0; self.sessionCount = 0; self.subsessionCount = -1; // -1 means unknown @@ -67,6 +71,12 @@ - (id)initWithCoder:(NSCoder *)decoder { self.timeSpent = [decoder decodeDoubleForKey:@"timeSpent"]; self.createdAt = [decoder decodeDoubleForKey:@"createdAt"]; self.lastActivity = [decoder decodeDoubleForKey:@"lastActivity"]; + self.uuid = [decoder decodeObjectForKey:@"uuid"]; + + // create UUID for migrating devices + if (self.uuid == nil) { + self.uuid = [UIDevice.currentDevice aiCreateUuid]; + } self.lastInterval = -1; @@ -81,6 +91,7 @@ - (void)encodeWithCoder:(NSCoder *)encoder { [encoder encodeDouble:self.timeSpent forKey:@"timeSpent"]; [encoder encodeDouble:self.createdAt forKey:@"createdAt"]; [encoder encodeDouble:self.lastActivity forKey:@"lastActivity"]; + [encoder encodeObject:self.uuid forKey:@"uuid"]; } From e0adf0603da074ebc6efa903ea235586185f6250 Mon Sep 17 00:00:00 2001 From: Christian Wellenbrock Date: Tue, 4 Feb 2014 11:18:39 +0100 Subject: [PATCH 04/11] Add PackageBuilder.uuid, inject from ActivityState --- AdjustIo/AIActivityState.m | 1 + AdjustIo/AIPackageBuilder.h | 1 + 2 files changed, 2 insertions(+) diff --git a/AdjustIo/AIActivityState.m b/AdjustIo/AIActivityState.m index efb691e45..29006dd92 100644 --- a/AdjustIo/AIActivityState.m +++ b/AdjustIo/AIActivityState.m @@ -103,6 +103,7 @@ - (void)injectGeneralAttributes:(AIPackageBuilder *)builder { builder.sessionLength = self.sessionLength; builder.timeSpent = self.timeSpent; builder.createdAt = self.createdAt; + builder.uuid = self.uuid; } @end diff --git a/AdjustIo/AIPackageBuilder.h b/AdjustIo/AIPackageBuilder.h index 2aaeead3c..5af618f57 100644 --- a/AdjustIo/AIPackageBuilder.h +++ b/AdjustIo/AIPackageBuilder.h @@ -19,6 +19,7 @@ @property (nonatomic, copy) NSString *environment; @property (nonatomic, copy) NSString *userAgent; @property (nonatomic, copy) NSString *clientSdk; +@property (nonatomic, copy) NSString *uuid; @property (nonatomic, assign) BOOL trackingEnabled; // sessions From ef5ae3a569855337a277d861c588c78f8584a782 Mon Sep 17 00:00:00 2001 From: Christian Wellenbrock Date: Tue, 4 Feb 2014 11:19:07 +0100 Subject: [PATCH 05/11] Write PackageBuilder.uuid into package for key ios_uuid --- AdjustIo/AIPackageBuilder.m | 1 + 1 file changed, 1 insertion(+) diff --git a/AdjustIo/AIPackageBuilder.m b/AdjustIo/AIPackageBuilder.m index a8c5d44b6..e2ec18943 100644 --- a/AdjustIo/AIPackageBuilder.m +++ b/AdjustIo/AIPackageBuilder.m @@ -72,6 +72,7 @@ - (NSMutableDictionary *)defaultParameters { [self parameters:parameters setString:self.appToken forKey:@"app_token"]; [self parameters:parameters setString:self.macSha1 forKey:@"mac_sha1"]; [self parameters:parameters setString:self.macShortMd5 forKey:@"mac_md5"]; + [self parameters:parameters setString:self.uuid forKey:@"ios_uuid"]; [self parameters:parameters setString:self.idForAdvertisers forKey:@"idfa"]; [self parameters:parameters setString:self.fbAttributionId forKey:@"fb_id"]; [self parameters:parameters setString:self.environment forKey:@"environment"]; From a494a6e4121e97a13bb3eb3722f60f4d7226f64c Mon Sep 17 00:00:00 2001 From: Christian Wellenbrock Date: Tue, 4 Feb 2014 11:26:11 +0100 Subject: [PATCH 06/11] Log activityState.uuid after reading activityState --- AdjustIo/AIActivityHandler.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AdjustIo/AIActivityHandler.m b/AdjustIo/AIActivityHandler.m index 03a2417f6..f36a4451e 100644 --- a/AdjustIo/AIActivityHandler.m +++ b/AdjustIo/AIActivityHandler.m @@ -287,7 +287,7 @@ - (void)readActivityState { id object = [NSKeyedUnarchiver unarchiveObjectWithFile:filename]; if ([object isKindOfClass:[AIActivityState class]]) { self.activityState = object; - [AILogger debug:@"Read activity state: %@", self.activityState]; + [AILogger debug:@"Read activity state: %@ uuid:%@", self.activityState, self.activityState.uuid]; return; } else if (object == nil) { [AILogger verbose:@"Activity state file not found"]; From 822855f6ed88c92f5369986639789c8f13a3488f Mon Sep 17 00:00:00 2001 From: Christian Wellenbrock Date: Tue, 4 Feb 2014 15:52:13 +0100 Subject: [PATCH 07/11] Add compiler flag ADJUST_NO_IDFA to suppress usage of AdSupport --- AdjustIo/AIAdditions/UIDevice+AIAdditions.m | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/AdjustIo/AIAdditions/UIDevice+AIAdditions.m b/AdjustIo/AIAdditions/UIDevice+AIAdditions.m index d1af99587..27b8bd8ca 100644 --- a/AdjustIo/AIAdditions/UIDevice+AIAdditions.m +++ b/AdjustIo/AIAdditions/UIDevice+AIAdditions.m @@ -9,26 +9,35 @@ #import "UIDevice+AIAdditions.h" #import "NSString+AIAdditions.h" -#import #import #import #import #import +#if !ADJUST_NO_IDFA +#import +#endif + @implementation UIDevice(AIAdditions) - (BOOL)aiTrackingEnabled { +#if !ADJUST_NO_IDFA if (NSClassFromString(@"ASIdentifierManager")) { return ASIdentifierManager.sharedManager.advertisingTrackingEnabled; - } else { + } else +#endif + { return NO; } } - (NSString *)aiIdForAdvertisers { +#if !ADJUST_NO_IDFA if (NSClassFromString(@"ASIdentifierManager")) { return ASIdentifierManager.sharedManager.advertisingIdentifier.UUIDString; - } else { + } else +#endif + { return @""; } } From 3a088ec9de022f958841a1b579ec38a86f33c68d Mon Sep 17 00:00:00 2001 From: Christian Wellenbrock Date: Tue, 4 Feb 2014 16:41:49 +0100 Subject: [PATCH 08/11] Add doc/idfa.md --- doc/idfa.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 doc/idfa.md diff --git a/doc/idfa.md b/doc/idfa.md new file mode 100644 index 000000000..612639465 --- /dev/null +++ b/doc/idfa.md @@ -0,0 +1,44 @@ +## Remove IDFA support + +If your app got rejected by Apple because your app is using the advertising +identifier, this document is for you. + +1. Contact us at [support@adjust.io](mailto:support@adjust.io). We would like + to make sure that you are aware of the consequences of removing IDFA + support. + +2. After you talked with us, or when you just can't wait any longer, proceed + with the following steps to remove the IDFA support. + +### Remove the AdSupport framework + +- In the Project Navigator select your project. Make sure your target is + selected in the top left corner of the right hand window. + +- Select the `Build Phases` tab and expand the group `Link Binary with + Libraries`. + +- Select the `AdSupport.framework` and press the `-` button to remove it. + +- In the Project Navigator, expand the group `Frameworks`. + +- If the `AdSupport.framework` is in there, right click it, select `Delete` and + confirm `Remove Reference`. + +### Add the compiler flag `ADJUST_NO_IDFA` + +- In the Project Navigator select your project. Make sure your target is + selected in the top left corner of the right hand window. + +- Select the `Build Settings` tab and search for `Other C Flags` in the search + field below. + +- Double click on the right side of the `Other C Flags` line to change its + value + +- Press on the `+` button at the bottom of the overlay and paste the following + text into the selected line: + + ``` + -DADJUST_NO_IDFA + ``` From 0a6130881fb8c56ddbcb43123922d764392dd1c1 Mon Sep 17 00:00:00 2001 From: Christian Wellenbrock Date: Tue, 4 Feb 2014 18:00:49 +0100 Subject: [PATCH 09/11] Add +[NSString aiJoin:...] --- AdjustIo/AIAdditions/NSString+AIAdditions.h | 2 ++ AdjustIo/AIAdditions/NSString+AIAdditions.m | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/AdjustIo/AIAdditions/NSString+AIAdditions.h b/AdjustIo/AIAdditions/NSString+AIAdditions.h index af09d2c7a..846af17bd 100644 --- a/AdjustIo/AIAdditions/NSString+AIAdditions.h +++ b/AdjustIo/AIAdditions/NSString+AIAdditions.h @@ -16,4 +16,6 @@ - (NSString *)aiUrlEncode; - (NSString *)aiRemoveColons; ++ (NSString *)aiJoin:(NSString *)strings, ...; + @end diff --git a/AdjustIo/AIAdditions/NSString+AIAdditions.m b/AdjustIo/AIAdditions/NSString+AIAdditions.m index 9318ae9db..43442d044 100644 --- a/AdjustIo/AIAdditions/NSString+AIAdditions.m +++ b/AdjustIo/AIAdditions/NSString+AIAdditions.m @@ -54,4 +54,18 @@ - (NSString *)aiRemoveColons { return [self stringByReplacingOccurrencesOfString:@":" withString:@""]; } ++ (NSString *)aiJoin:(NSString *)first, ... { + NSString *iter, *result = first; + va_list strings; + va_start(strings, first); + + while ((iter = va_arg(strings, NSString*))) { + NSString *capitalized = iter.capitalizedString; + result = [result stringByAppendingString:capitalized]; + } + + va_end(strings); + return result; +} + @end From 17f83de62528c40ffda041bdd1ced3973e1f1c5d Mon Sep 17 00:00:00 2001 From: Christian Wellenbrock Date: Tue, 4 Feb 2014 18:02:09 +0100 Subject: [PATCH 10/11] Make UIDevice additions more dynamic --- AdjustIo/AIAdditions/UIDevice+AIAdditions.m | 47 +++++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/AdjustIo/AIAdditions/UIDevice+AIAdditions.m b/AdjustIo/AIAdditions/UIDevice+AIAdditions.m index 27b8bd8ca..82d7a384b 100644 --- a/AdjustIo/AIAdditions/UIDevice+AIAdditions.m +++ b/AdjustIo/AIAdditions/UIDevice+AIAdditions.m @@ -22,8 +22,26 @@ @implementation UIDevice(AIAdditions) - (BOOL)aiTrackingEnabled { #if !ADJUST_NO_IDFA - if (NSClassFromString(@"ASIdentifierManager")) { - return ASIdentifierManager.sharedManager.advertisingTrackingEnabled; + NSString *className = [NSString aiJoin:@"A", @"S", @"identifier", @"manager", nil]; + NSString *keyManager = [NSString aiJoin:@"shared", @"manager", nil]; + NSString *keyEnabled = [NSString aiJoin:@"is", @"advertising", @"tracking", @"enabled", nil]; + + Class class = NSClassFromString(className); + if (class) { + @try { + SEL selManager = NSSelectorFromString(keyManager); + SEL selEnabled = NSSelectorFromString(keyEnabled); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id manager = [class performSelector:selManager]; + BOOL enabled = (BOOL)[manager performSelector:selEnabled]; +#pragma clang diagnostic pop + + return enabled; + } @catch (NSException *e) { + return NO; + } } else #endif { @@ -33,8 +51,29 @@ - (BOOL)aiTrackingEnabled { - (NSString *)aiIdForAdvertisers { #if !ADJUST_NO_IDFA - if (NSClassFromString(@"ASIdentifierManager")) { - return ASIdentifierManager.sharedManager.advertisingIdentifier.UUIDString; + NSString *className = [NSString aiJoin:@"A", @"S", @"identifier", @"manager", nil]; + NSString *keyManager = [NSString aiJoin:@"shared", @"manager", nil]; + NSString *keyIdentifier = [NSString aiJoin:@"advertising", @"identifier", nil]; + NSString *keyString = [NSString aiJoin:@"UUID", @"string", nil]; + + Class class = NSClassFromString(className); + if (class) { + @try { + SEL selManager = NSSelectorFromString(keyManager); + SEL selIdentifier = NSSelectorFromString(keyIdentifier); + SEL selString = NSSelectorFromString(keyString); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id manager = [class performSelector:selManager]; + id identifier = [manager performSelector:selIdentifier]; + NSString *string = [identifier performSelector:selString]; +#pragma clang diagnostic pop + + return string; + } @catch (NSException *e) { + return @""; + } } else #endif { From 42f8a5d3c3b757ff81cc7fdfc59a06d0d9cc293a Mon Sep 17 00:00:00 2001 From: Christian Wellenbrock Date: Tue, 4 Feb 2014 19:01:56 +0100 Subject: [PATCH 11/11] Update version to 2.2.0 --- AdjustIO.podspec | 4 ++-- AdjustIo/AIUtil.m | 2 +- README.md | 2 +- VERSION | 2 +- doc/migration.md | 6 +++--- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/AdjustIO.podspec b/AdjustIO.podspec index 957351d91..92b755434 100644 --- a/AdjustIO.podspec +++ b/AdjustIO.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = "AdjustIO" - s.version = "2.1.4" + s.version = "2.2.0" s.summary = "This is the iOS SDK of AdjustIo. You can read more about it at http://adjust.io." s.homepage = "http://adjust.io" s.license = { :type => 'MIT', :file => 'MIT-LICENSE' } s.author = { "Christian Wellenbrock" => "welle@adeven.com" } - s.source = { :git => "https://github.com/adeven/adjust_ios_sdk.git", :tag => "v2.1.4" } + s.source = { :git => "https://github.com/adeven/adjust_ios_sdk.git", :tag => "v2.2.0" } s.platform = :ios, '4.3' s.framework = 'AdSupport', 'SystemConfiguration' s.source_files = 'AdjustIo/*.{h,m}', 'AdjustIo/AIAdditions/*.{h,m}' diff --git a/AdjustIo/AIUtil.m b/AdjustIo/AIUtil.m index 34e8451e9..95817d46e 100644 --- a/AdjustIo/AIUtil.m +++ b/AdjustIo/AIUtil.m @@ -13,7 +13,7 @@ #include static NSString * const kBaseUrl = @"https://app.adjust.io"; -static NSString * const kClientSdk = @"ios2.1.4"; +static NSString * const kClientSdk = @"ios2.2.0"; #pragma mark - diff --git a/README.md b/README.md index 7f2ded24c..c39fcc43b 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ If you're using [CocoaPods][cocoapods], you can add the following line to your `Podfile` and continue with [step 3](#step3): ```ruby -pod 'AdjustIO', :git => 'git://github.com/adeven/adjust_ios_sdk.git', :tag => 'v2.1.4' +pod 'AdjustIO', :git => 'git://github.com/adeven/adjust_ios_sdk.git', :tag => 'v2.2.0' ``` ### 1. Get the SDK diff --git a/VERSION b/VERSION index 7d2ed7c70..ccbccc3dc 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1.4 +2.2.0 diff --git a/doc/migration.md b/doc/migration.md index 8d908635f..3d0be2d39 100644 --- a/doc/migration.md +++ b/doc/migration.md @@ -1,7 +1,7 @@ -## Migrate your AdjustIo SDK for iOS from v1.x to v2.1.4 +## Migrate your AdjustIo SDK for iOS from v1.x to v2.2.0 1. Delete the old `AdjustIo` source folder from your Xcode project. Download - version v2.1.4 and drag the new folder into your Xcode project. + version v2.2.0 and drag the new folder into your Xcode project. ![][drag] @@ -55,7 +55,7 @@ 2. The `appDidLaunch` method now expects your App Token instead of your App ID. You can find your App Token in your [dashboard]. -2. The AdjustIo SDK for iOS 2.1.4 uses [ARC][arc]. If you haven't done already, +2. The AdjustIo SDK for iOS 2.2.0 uses [ARC][arc]. If you haven't done already, we recommend [transitioning your project to use ARC][transition] as well. If you don't want to use ARC, you have to enable ARC for all files of the AdjustIo SDK. Please consult the [README] for details.