From 611130f1713071a65c917f28c64e85f797ce16d2 Mon Sep 17 00:00:00 2001 From: genadyb Date: Thu, 14 Nov 2024 14:17:04 +0100 Subject: [PATCH 01/15] refac: changed handling of foreground / background events --- Adjust/Internal/ADJActivityHandler.m | 106 +++++++++++++-------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/Adjust/Internal/ADJActivityHandler.m b/Adjust/Internal/ADJActivityHandler.m index e1b85e90f..c9f3b6322 100644 --- a/Adjust/Internal/ADJActivityHandler.m +++ b/Adjust/Internal/ADJActivityHandler.m @@ -249,41 +249,19 @@ - (id)initWithConfig:(ADJConfig *_Nullable)adjustConfig } - (void)applicationDidBecomeActive { - self.internalState.background = NO; - [ADJUtil launchInQueue:self.internalQueue selfInject:self block:^(ADJActivityHandler * selfI) { - - [selfI activateWaitingForAttStatusI:selfI]; - - [selfI stopBackgroundTimerI:selfI]; - - [selfI startForegroundTimerI:selfI]; - - [selfI.logger verbose:@"Subsession start"]; - - [selfI startI:selfI]; - }]; + [selfI handleAppForegroundI:selfI]; + }]; } - (void)applicationWillResignActive { - self.internalState.background = YES; - [ADJUtil launchInQueue:self.internalQueue selfInject:self block:^(ADJActivityHandler * selfI) { - - [selfI pauseWaitingForAttStatusI:selfI]; - - [selfI stopForegroundTimerI:selfI]; - - [selfI startBackgroundTimerI:selfI]; - - [selfI.logger verbose:@"Subsession end"]; - - [selfI endI:selfI]; - }]; + [selfI handleAppBackgroundI:selfI]; + }]; } - (void)trackEvent:(ADJEvent *)event { @@ -710,22 +688,6 @@ - (void)trackAttStatusUpdate { [selfI trackAttStatusUpdateI:selfI]; }]; } -- (void)trackAttStatusUpdateI:(ADJActivityHandler *)selfI { - double now = [NSDate.date timeIntervalSince1970]; - - ADJPackageBuilder *infoBuilder = [[ADJPackageBuilder alloc] - initWithPackageParams:selfI.packageParams - activityState:selfI.activityState - config:selfI.adjustConfig - globalParameters:selfI.globalParameters - trackingStatusManager:self.trackingStatusManager - createdAt:now]; - infoBuilder.internalState = selfI.internalState; - - ADJActivityPackage *infoPackage = [infoBuilder buildInfoPackage:@"att"]; - [selfI.packageHandler addPackage:infoPackage]; - [selfI.packageHandler sendFirstPackage]; -} - (NSString *)getBasePath { return _basePath; @@ -933,8 +895,7 @@ - (void)initI:(ADJActivityHandler *)selfI [ADJUtil launchInQueue:self.internalQueue selfInject:self block:^(ADJActivityHandler * selfI) { if (!isInactive) { [selfI.logger debug:@"Start sdk, since the app is already in the foreground"]; - selfI.internalState.background = NO; - [selfI startI:selfI]; + [selfI handleAppForegroundI:selfI]; } else { [selfI.logger debug:@"Wait for the app to go to the foreground to start the sdk"]; } @@ -942,6 +903,28 @@ - (void)initI:(ADJActivityHandler *)selfI }]; } +- (void)handleAppForegroundI:(ADJActivityHandler *)selfI { + if (selfI.internalState.background == NO) + return; + + selfI.internalState.background = NO; + [selfI activateWaitingForAttStatusI:selfI]; + [selfI stopBackgroundTimerI:selfI]; + [selfI startForegroundTimerI:selfI]; + [selfI.logger verbose:@"Subsession start"]; + [selfI startI:selfI]; +} + +- (void)handleAppBackgroundI:(ADJActivityHandler *)selfI { + + selfI.internalState.background = YES; + [selfI pauseWaitingForAttStatusI:selfI]; + [selfI stopForegroundTimerI:selfI]; + [selfI startBackgroundTimerI:selfI]; + [selfI.logger verbose:@"Subsession end"]; + [selfI endI:selfI]; +} + - (void)startI:(ADJActivityHandler *)selfI { // it shouldn't start if it was disabled after a first session if (selfI.activityState != nil @@ -1131,6 +1114,23 @@ - (void)checkAttributionStateI:(ADJActivityHandler *)selfI { [selfI.attributionHandler getAttribution]; } +- (void)trackAttStatusUpdateI:(ADJActivityHandler *)selfI { + double now = [NSDate.date timeIntervalSince1970]; + + ADJPackageBuilder *infoBuilder = [[ADJPackageBuilder alloc] + initWithPackageParams:selfI.packageParams + activityState:selfI.activityState + config:selfI.adjustConfig + globalParameters:selfI.globalParameters + trackingStatusManager:self.trackingStatusManager + createdAt:now]; + infoBuilder.internalState = selfI.internalState; + + ADJActivityPackage *infoPackage = [infoBuilder buildInfoPackage:@"att"]; + [selfI.packageHandler addPackage:infoPackage]; + [selfI.packageHandler sendFirstPackage]; +} + - (void)processCachedDeeplinkI:(ADJActivityHandler *)selfI { if (![selfI checkActivityStateI:selfI]) return; @@ -1278,15 +1278,15 @@ - (BOOL)trackMeasurementConsentI:(ADJActivityHandler *)selfI double now = [NSDate.date timeIntervalSince1970]; // build package - ADJPackageBuilder *tpsBuilder = [[ADJPackageBuilder alloc] - initWithPackageParams:selfI.packageParams - activityState:selfI.activityState - config:selfI.adjustConfig - globalParameters:selfI.globalParameters - trackingStatusManager:self.trackingStatusManager - createdAt:now]; - tpsBuilder.internalState = selfI.internalState; - ADJActivityPackage *mcPackage = [tpsBuilder buildMeasurementConsentPackage:enabled]; + ADJPackageBuilder *mcBuilder = [[ADJPackageBuilder alloc] + initWithPackageParams:selfI.packageParams + activityState:selfI.activityState + config:selfI.adjustConfig + globalParameters:selfI.globalParameters + trackingStatusManager:self.trackingStatusManager + createdAt:now]; + mcBuilder.internalState = selfI.internalState; + ADJActivityPackage *mcPackage = [mcBuilder buildMeasurementConsentPackage:enabled]; [selfI.packageHandler addPackage:mcPackage]; [selfI.packageHandler sendFirstPackage]; From c08534a390cf5a81383eceebc723a9c53af2e813 Mon Sep 17 00:00:00 2001 From: genadyb Date: Thu, 14 Nov 2024 14:17:39 +0100 Subject: [PATCH 02/15] chore: adding logs for clarity --- Adjust/Internal/ADJPurchaseVerificationHandler.m | 1 + Adjust/Internal/ADJSdkClickHandler.m | 1 + 2 files changed, 2 insertions(+) diff --git a/Adjust/Internal/ADJPurchaseVerificationHandler.m b/Adjust/Internal/ADJPurchaseVerificationHandler.m index 461c73ce2..c60870ab2 100644 --- a/Adjust/Internal/ADJPurchaseVerificationHandler.m +++ b/Adjust/Internal/ADJPurchaseVerificationHandler.m @@ -131,6 +131,7 @@ - (void)sendPurchaseVerificationPackageI:(ADJPurchaseVerificationHandler *)selfI - (void)sendNextPurchaseVerificationPackageI:(ADJPurchaseVerificationHandler *)selfI { if (selfI.paused) { + [selfI.logger debug:@"Purchase verification handler is paused"]; return; } NSUInteger queueSize = selfI.packageQueue.count; diff --git a/Adjust/Internal/ADJSdkClickHandler.m b/Adjust/Internal/ADJSdkClickHandler.m index 5fcf6bd7d..c2f7387b8 100644 --- a/Adjust/Internal/ADJSdkClickHandler.m +++ b/Adjust/Internal/ADJSdkClickHandler.m @@ -134,6 +134,7 @@ - (void)sendSdkClickI:(ADJSdkClickHandler *)selfI - (void)sendNextSdkClickI:(ADJSdkClickHandler *)selfI { if (selfI.paused) { + [selfI.logger debug:@"Click handler is paused"]; return; } NSUInteger queueSize = selfI.packageQueue.count; From dfc23bbfd039b479f33cc76d975e611918132b79 Mon Sep 17 00:00:00 2001 From: genadyb Date: Thu, 14 Nov 2024 23:50:22 +0100 Subject: [PATCH 03/15] chore: improves log messages for pre-launch logic --- Adjust/Adjust.m | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/Adjust/Adjust.m b/Adjust/Adjust.m index 84345972f..ab209d535 100644 --- a/Adjust/Adjust.m +++ b/Adjust/Adjust.m @@ -367,9 +367,7 @@ - (void)trackSubsessionEnd { - (void)enable { self.savedPreLaunch.enabled = @YES; - if ([self checkActivityHandler:YES - trueMessage:@"enabled mode" - falseMessage:@"disabled mode"]) { + if ([self checkActivityHandler:@"enable SDK"]) { [self.activityHandler setEnabled:YES]; } } @@ -377,9 +375,7 @@ - (void)enable { - (void)disable { self.savedPreLaunch.enabled = @NO; - if ([self checkActivityHandler:NO - trueMessage:@"enabled mode" - falseMessage:@"disabled mode"]) { + if ([self checkActivityHandler:@"disable SDK"]) { [self.activityHandler setEnabled:NO]; } } @@ -400,7 +396,7 @@ - (void)isEnabledWithCompletionHandler:(nonnull ADJIsEnabledGetterBlock)completi - (void)processDeeplink:(ADJDeeplink *)deeplink { [ADJUserDefaults cacheDeeplinkUrl:deeplink.deeplink]; NSDate *clickTime = [NSDate date]; - if (![self checkActivityHandler]) { + if (![self checkActivityHandler:@"process deep link"]) { [ADJUserDefaults saveDeeplinkUrl:deeplink.deeplink clickTime:clickTime]; return; @@ -418,7 +414,7 @@ - (void)processAndResolveDeeplink:(nonnull ADJDeeplink *)deeplink // if deep link processing is triggered prior to SDK being initialized [ADJUserDefaults cacheDeeplinkUrl:deeplink.deeplink]; NSDate *clickTime = [NSDate date]; - if (![self checkActivityHandler]) { + if (![self checkActivityHandler:@"process and resolve deep link"]) { [ADJUserDefaults saveDeeplinkUrl:deeplink.deeplink clickTime:clickTime]; self.cachedResolvedDeeplinkBlock = completion; @@ -447,9 +443,7 @@ - (void)setPushTokenAsString:(NSString *)pushToken { } - (void)switchToOfflineMode { - if (![self checkActivityHandler:YES - trueMessage:@"offline mode" - falseMessage:@"online mode"]) { + if (![self checkActivityHandler:@"switch to offline mode"]) { self.savedPreLaunch.offline = YES; } else { [self.activityHandler setOfflineMode:YES]; @@ -457,9 +451,7 @@ - (void)switchToOfflineMode { } - (void)switchBackToOnlineMode { - if (![self checkActivityHandler:NO - trueMessage:@"offline mode" - falseMessage:@"online mode"]) { + if (![self checkActivityHandler:@"switch back to online mode"]) { self.savedPreLaunch.offline = NO; } else { [self.activityHandler setOfflineMode:NO]; @@ -587,7 +579,7 @@ - (void)gdprForgetMe { } - (void)trackThirdPartySharing:(nonnull ADJThirdPartySharing *)thirdPartySharing { - if (![self checkActivityHandler]) { + if (![self checkActivityHandler:@"track third party sharing"]) { if (self.savedPreLaunch.preLaunchAdjustThirdPartySharingArray == nil) { self.savedPreLaunch.preLaunchAdjustThirdPartySharingArray = [[NSMutableArray alloc] init]; @@ -599,7 +591,7 @@ - (void)trackThirdPartySharing:(nonnull ADJThirdPartySharing *)thirdPartySharing } - (void)trackMeasurementConsent:(BOOL)enabled { - if (![self checkActivityHandler]) { + if (![self checkActivityHandler:@"track measurement consent"]) { self.savedPreLaunch.lastMeasurementConsentTracked = [NSNumber numberWithBool:enabled]; return; } @@ -652,7 +644,7 @@ - (void)attributionWithCompletionHandler:(nonnull ADJAttributionGetterBlock)comp return; } - if (![self checkActivityHandler]) { + if (![self checkActivityHandler:@"read attribution request"]) { if (self.savedPreLaunch.cachedAttributionReadCallbacksArray == nil) { self.savedPreLaunch.cachedAttributionReadCallbacksArray = [NSMutableArray array]; } @@ -669,7 +661,7 @@ - (void)adidWithCompletionHandler:(nonnull ADJAdidGetterBlock)completion { return; } - if (![self checkActivityHandler]) { + if (![self checkActivityHandler:@"read adid request"]) { if (self.savedPreLaunch.cachedAdidReadCallbacksArray == nil) { self.savedPreLaunch.cachedAdidReadCallbacksArray = [NSMutableArray array]; } @@ -789,16 +781,6 @@ - (BOOL)checkActivityHandler { return [self checkActivityHandler:nil]; } -- (BOOL)checkActivityHandler:(BOOL)status - trueMessage:(NSString *)trueMessage - falseMessage:(NSString *)falseMessage { - if (status) { - return [self checkActivityHandler:trueMessage]; - } else { - return [self checkActivityHandler:falseMessage]; - } -} - - (BOOL)checkActivityHandler:(NSString *)savedForLaunchWarningSuffixMessage { if (self.activityHandler == nil) { if (savedForLaunchWarningSuffixMessage != nil) { From 534be867c8ef232c5f4eb3418df135fce04d34da Mon Sep 17 00:00:00 2001 From: genadyb Date: Wed, 11 Dec 2024 14:25:10 +0100 Subject: [PATCH 04/15] refac: improves implementation of SKAdNetwork and callbacks invocation --- Adjust/Internal/ADJActivityHandler.m | 9 +- Adjust/Internal/ADJSKAdNetwork.m | 292 ++++++++++++++++----------- 2 files changed, 182 insertions(+), 119 deletions(-) diff --git a/Adjust/Internal/ADJActivityHandler.m b/Adjust/Internal/ADJActivityHandler.m index c9f3b6322..61474d6d1 100644 --- a/Adjust/Internal/ADJActivityHandler.m +++ b/Adjust/Internal/ADJActivityHandler.m @@ -182,8 +182,14 @@ - (id)initWithConfig:(ADJConfig *_Nullable)adjustConfig [self readAttribution]; [self readActivityState]; + + NSDate *skanRegisterDate = [ADJUserDefaults getSkadRegisterCallTimestamp]; + if (skanRegisterDate != nil) { + [self.logger debug:@"Call to register app with SKAdNetwork already made for this install"]; + } + // register SKAdNetwork attribution if we haven't already - if (self.adjustConfig.isSkanAttributionEnabled) { + if (self.adjustConfig.isSkanAttributionEnabled && !skanRegisterDate) { NSNumber *numConversionValue = [NSNumber numberWithInteger:kSkanRegisterConversionValue]; NSNumber *numLockWindow = [NSNumber numberWithBool:kSkanRegisterLockWindow]; @@ -191,6 +197,7 @@ - (id)initWithConfig:(ADJConfig *_Nullable)adjustConfig coarseValue:kSkanRegisterCoarseValue lockWindow:numLockWindow withCompletionHandler:^(NSError * _Nonnull error) { + [self notifySkanCallbackWithConversionValue:numConversionValue coarseValue:kSkanRegisterCoarseValue lockWindow:numLockWindow diff --git a/Adjust/Internal/ADJSKAdNetwork.m b/Adjust/Internal/ADJSKAdNetwork.m index d1be1093c..67727a878 100644 --- a/Adjust/Internal/ADJSKAdNetwork.m +++ b/Adjust/Internal/ADJSKAdNetwork.m @@ -13,12 +13,20 @@ #import "ADJAdjustFactory.h" #import "ADJLogger.h" -@interface ADJSKAdNetwork() +static const char * const kInternalQueueName = "io.adjust.SKAdNetworkQueue"; +@interface ADJSKAdNetwork() @property (nonatomic, weak) id logger; - +@property (nonatomic, strong) dispatch_queue_t internalQueue; @end +static NSString * const ADJSKAdNetworkDomain = @"com.adjust.sdk.skadnetwork"; +typedef NS_ENUM(NSInteger, ADJSKAdNetworkError) { + ADJSKAdNetworkErrorOsNotSupported = -100, + ADJSKAdNetworkErrorFrameworkNotFound = -101, + ADJSKAdNetworkErrorApiNotAvailable = -102 +}; + @implementation ADJSKAdNetwork #pragma mark - Lifecycle @@ -39,108 +47,117 @@ - (instancetype)init { } self.logger = [ADJAdjustFactory logger]; + self.internalQueue = dispatch_queue_create(kInternalQueueName, DISPATCH_QUEUE_SERIAL); return self; } #pragma mark - SKAdNetwork API -- (void)registerAppForAdNetworkAttribution { +- (void)registerAppForAdNetworkAttributionWithCompletionHandler:(void (^)(NSError *error))completion { + + NSError *error = [self checkSKAdNetworkMethodAvailability:@"registerAppForAdNetworkAttribution"]; + if (error != nil) { + [self asyncSendResultError:error toCompletionHandler:completion]; + return; + } + Class class = NSClassFromString(@"SKAdNetwork"); SEL selector = NSSelectorFromString(@"registerAppForAdNetworkAttribution"); - if (@available(iOS 14.0, *)) { - if ([self isApiAvailableForClass:class andSelector:selector]) { - NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; - [invocation setSelector:selector]; - [invocation setTarget:class]; - [invocation invoke]; - [self.logger verbose:@"Call to SKAdNetwork's registerAppForAdNetworkAttribution method made"]; - } - } else { - [self.logger warn:@"SKAdNetwork's registerAppForAdNetworkAttribution method not available for this operating system version"]; - } + NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + [invocation setSelector:selector]; + [invocation setTarget:class]; + [invocation invoke]; + [self.logger verbose:@"Call to SKAdNetwork's registerAppForAdNetworkAttribution method made"]; + [self asyncSendResultError:error toCompletionHandler:completion]; } -- (void)updateConversionValue:(NSInteger)conversionValue { +- (void)updateConversionValue:(NSInteger)conversionValue + withCompletionHandler:(void (^)(NSError *error))completion { + + NSError *error = [self checkSKAdNetworkMethodAvailability:@"updateConversionValue:"]; + if (error != nil) { + [self asyncSendResultError:error toCompletionHandler:completion]; + return; + } + Class class = NSClassFromString(@"SKAdNetwork"); SEL selector = NSSelectorFromString(@"updateConversionValue:"); - if (@available(iOS 14.0, *)) { - if ([self isApiAvailableForClass:class andSelector:selector]) { - NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; - [invocation setSelector:selector]; - [invocation setTarget:class]; - [invocation setArgument:&conversionValue atIndex:2]; - [invocation invoke]; - [self.logger verbose:@"Call to SKAdNetwork's updateConversionValue: method made with value %d", conversionValue]; - } - } else { - [self.logger warn:@"SKAdNetwork's updateConversionValue: method not available for this operating system version"]; - } + NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + [invocation setSelector:selector]; + [invocation setTarget:class]; + [invocation setArgument:&conversionValue atIndex:2]; + [invocation invoke]; + [self.logger verbose:@"Call to SKAdNetwork's updateConversionValue: method made with value %d", conversionValue]; + [self asyncSendResultError:error toCompletionHandler:completion]; } - (void)updatePostbackConversionValue:(NSInteger)conversionValue withCompletionHandler:(void (^)(NSError *error))completion { + + NSError *error = [self checkSKAdNetworkMethodAvailability:@"updatePostbackConversionValue:completionHandler:"]; + if (error != nil) { + [self asyncSendResultError:error toCompletionHandler:completion]; + return; + } + Class class = NSClassFromString(@"SKAdNetwork"); SEL selector = NSSelectorFromString(@"updatePostbackConversionValue:completionHandler:"); - if (@available(iOS 15.4, *)) { - if ([self isApiAvailableForClass:class andSelector:selector]) { - NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; - [invocation setSelector:selector]; - [invocation setTarget:class]; - [invocation setArgument:&conversionValue atIndex:2]; - [invocation setArgument:&completion atIndex:3]; - [invocation invoke]; - } - } else { - [self.logger warn:@"SKAdNetwork's updatePostbackConversionValue:completionHandler: method not available for this operating system version"]; - } + NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + [invocation setSelector:selector]; + [invocation setTarget:class]; + [invocation setArgument:&conversionValue atIndex:2]; + [invocation setArgument:&completion atIndex:3]; + [invocation invoke]; } - (void)updatePostbackConversionValue:(NSInteger)fineValue coarseValue:(NSString *)coarseValue withCompletionHandler:(void (^)(NSError *error))completion { + + NSError *error = [self checkSKAdNetworkMethodAvailability:@"updatePostbackConversionValue:coarseValue:completionHandler:"]; + if (error != nil) { + [self asyncSendResultError:error toCompletionHandler:completion]; + return; + } + Class class = NSClassFromString(@"SKAdNetwork"); SEL selector = NSSelectorFromString(@"updatePostbackConversionValue:coarseValue:completionHandler:"); - if (@available(iOS 16.1, *)) { - if ([self isApiAvailableForClass:class andSelector:selector]) { - NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; - [invocation setSelector:selector]; - [invocation setTarget:class]; - [invocation setArgument:&fineValue atIndex:2]; - [invocation setArgument:&coarseValue atIndex:3]; - [invocation setArgument:&completion atIndex:4]; - [invocation invoke]; - } - } else { - [self.logger warn:@"SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method not available for this operating system version"]; - } + NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + [invocation setSelector:selector]; + [invocation setTarget:class]; + [invocation setArgument:&fineValue atIndex:2]; + [invocation setArgument:&coarseValue atIndex:3]; + [invocation setArgument:&completion atIndex:4]; + [invocation invoke]; } - (void)updatePostbackConversionValue:(NSInteger)fineValue coarseValue:(NSString *)coarseValue lockWindow:(BOOL)lockWindow withCompletionHandler:(void (^)(NSError *error))completion { + + NSError *error = [self checkSKAdNetworkMethodAvailability:@"updatePostbackConversionValue:coarseValue:lockWindow:completionHandler:"]; + if (error != nil) { + [self asyncSendResultError:error toCompletionHandler:completion]; + return; + } + Class class = NSClassFromString(@"SKAdNetwork"); SEL selector = NSSelectorFromString(@"updatePostbackConversionValue:coarseValue:lockWindow:completionHandler:"); - if (@available(iOS 16.1, *)) { - if ([self isApiAvailableForClass:class andSelector:selector]) { - NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; - [invocation setSelector:selector]; - [invocation setTarget:class]; - [invocation setArgument:&fineValue atIndex:2]; - [invocation setArgument:&coarseValue atIndex:3]; - [invocation setArgument:&lockWindow atIndex:4]; - [invocation setArgument:&completion atIndex:5]; - [invocation invoke]; - } - } else { - [self.logger warn:@"SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method not available for this operating system version"]; - } + NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + [invocation setSelector:selector]; + [invocation setTarget:class]; + [invocation setArgument:&fineValue atIndex:2]; + [invocation setArgument:&coarseValue atIndex:3]; + [invocation setArgument:&lockWindow atIndex:4]; + [invocation setArgument:&completion atIndex:5]; + [invocation invoke]; } #pragma mark - Adjust helper methods @@ -149,13 +166,12 @@ - (void)registerWithConversionValue:(NSInteger)conversionValue coarseValue:(nonnull NSString *)coarseValue lockWindow:(nonnull NSNumber *)lockWindow withCompletionHandler:(void (^_Nonnull)(NSError *_Nullable error))completion { - if (NSClassFromString(@"SKAdNetwork") == nil) { - [self.logger debug:@"StoreKit.framework not found in the app (SKAdNetwork class not found)"]; - return; - } - if ([ADJUserDefaults getSkadRegisterCallTimestamp] != nil) { - [self.logger debug:@"Call to register app with SKAdNetwork already made for this install"]; - completion(nil); + + NSError *error = nil; + // Check iOS 14.0+ / NON-tvOS / SKAdNetwork framework available + if (![self checkSKAdNetworkFrameworkAvailability:&error]) { + [self.logger debug:error.localizedDescription]; + [self asyncSendResultError:error toCompletionHandler:completion]; return; } @@ -164,31 +180,45 @@ - (void)registerWithConversionValue:(NSInteger)conversionValue coarseValue:[self getSkAdNetworkCoarseConversionValue:coarseValue] lockWindow:lockWindow withCompletionHandler:^(NSError * _Nullable error) { - completion(error); + if (error == nil) { + [self writeSkAdNetworkRegisterCallTimestamp]; + } + if (completion != nil) { + completion(error); + } }]; } else if (@available(iOS 15.4, *)) { [self updatePostbackConversionValue:conversionValue withCompletionHandler:^(NSError * _Nullable error) { - completion(error); + if (error == nil) { + [self writeSkAdNetworkRegisterCallTimestamp]; + } + if (completion != nil) { + completion(error); + } + }]; + } else { // if (@available(iOS 14.0, *)) { already checked in 'checkSKAdNetworkFrameworkAvailability' + [self registerAppForAdNetworkAttributionWithCompletionHandler:^(NSError *error) { + if (error == nil) { + [self writeSkAdNetworkRegisterCallTimestamp]; + } + if (completion != nil) { + completion(error); + } }]; - } else if (@available(iOS 14.0, *)) { - [self registerAppForAdNetworkAttribution]; - completion(nil); - } else { - [self.logger error:@"SKAdNetwork API not available on this iOS version"]; - completion(nil); - return; } - - [self writeSkAdNetworkRegisterCallTimestamp]; } - (void)updateConversionValue:(NSInteger)conversionValue coarseValue:(nullable NSString *)coarseValue lockWindow:(nullable NSNumber *)lockWindow withCompletionHandler:(void (^_Nullable)(NSError *_Nullable error))completion { - if (NSClassFromString(@"SKAdNetwork") == nil) { - [self.logger debug:@"StoreKit.framework not found in the app (SKAdNetwork class not found)"]; + + NSError *error = nil; + // Check iOS 14.0+ / NON-tvOS / SKAdNetwork available + if (![self checkSKAdNetworkFrameworkAvailability:&error]) { + [self.logger debug:error.localizedDescription]; + [self asyncSendResultError:error toCompletionHandler:completion]; return; } @@ -252,49 +282,78 @@ - (void)updateConversionValue:(NSInteger)conversionValue completion(error); } }]; - } else if (@available(iOS 14.0, *)) { - [self updateConversionValue:conversionValue]; - if (completion != nil) { - completion(nil); - } - } else { - [self.logger error:@"SKAdNetwork API not available on this iOS version"]; - if (completion != nil) { - completion(nil); - } + } else { //if (@available(iOS 14.0, *)) { already checked in 'checkSKAdNetworkFrameworkAvailability' + [self updateConversionValue:conversionValue withCompletionHandler:^(NSError *error) { + if (error) { + [self.logger error:@"Call to SKAdNetwork's updateConversionValue: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription]; + } else { + [self.logger debug:@"Called SKAdNetwork's updateConversionValue: method with conversion value: %d", conversionValue]; + } + if (completion != nil) { + completion(error); + } + }]; } } #pragma mark - Private -- (BOOL)isApiAvailableForClass:(Class)class andSelector:(SEL)selector { +- (BOOL)checkSKAdNetworkFrameworkAvailability:(NSError **)error { #if !(TARGET_OS_TV) - if (class == nil) { - [self.logger warn:@"StoreKit.framework not found in the app (SKAdNetwork class not found)"]; - return NO; - } - if (!selector) { - [self.logger warn:@"Selector for given method was not found"]; - return NO; - } - if ([class respondsToSelector:selector] == NO) { - [self.logger warn:@"%@ method implementation not found", NSStringFromSelector(selector)]; + if (@available(iOS 14.0, *)) { + if (NSClassFromString(@"SKAdNetwork") == nil) { + NSString *strError = @"SKAdNetwork class not found. Check StoreKit.framework availability."; + *error = [NSError errorWithDomain:ADJSKAdNetworkDomain + code:ADJSKAdNetworkErrorFrameworkNotFound + userInfo:@{ NSLocalizedDescriptionKey: strError }]; + return NO; + } + return YES; + } else { + NSString *strError = @"SKAdNetwork API not available on this iOS version"; + *error = [NSError errorWithDomain:ADJSKAdNetworkDomain + code:ADJSKAdNetworkErrorOsNotSupported + userInfo:@{ NSLocalizedDescriptionKey: strError }]; return NO; } - return YES; #else - [self.logger debug:@"%@ method implementation not available for tvOS platform", NSStringFromSelector(selector)]; + NSString *strError = @"SKAdNetwork is not supported on tvOS"; + *error = [NSError errorWithDomain:ADJSKAdNetworkDomain + code:ADJSKAdNetworkErrorOsNotSupported + userInfo:@{ NSLocalizedDescriptionKey: strError }]; return NO; #endif } +- (NSError *)checkSKAdNetworkMethodAvailability:(NSString *)methodName { + Class class = NSClassFromString(@"SKAdNetwork"); + SEL selector = NSSelectorFromString(methodName); + + if ([class respondsToSelector:selector] == NO) { + NSString *strError = [NSString stringWithFormat:@"Implementation of %@ not found in SKAdNetwork", methodName]; + NSError *error = [NSError errorWithDomain:ADJSKAdNetworkDomain + code:ADJSKAdNetworkErrorApiNotAvailable + userInfo:@{ NSLocalizedDescriptionKey: strError }]; + return error; + } + return nil; +} + +- (void)asyncSendResultError:(NSError *_Nullable)error + toCompletionHandler:(void (^_Nullable)(NSError *_Nullable error))completion { + dispatch_async(self.internalQueue, ^{ + if (completion != nil) { + completion(error); + } + }); +} + - (void)writeSkAdNetworkRegisterCallTimestamp { NSDate *callTime = [NSDate date]; [ADJUserDefaults saveSkadRegisterCallTimestamp:callTime]; } - (NSString *)getSkAdNetworkCoarseConversionValue:(NSString *)adjustCoarseValue { -#if !(TARGET_OS_TV) if (@available(iOS 16.1, *)) { if ([adjustCoarseValue isEqualToString:@"low"]) { NSString * __autoreleasing *lowValue = (NSString * __autoreleasing *)dlsym(RTLD_DEFAULT, "SKAdNetworkCoarseConversionValueLow"); @@ -311,9 +370,6 @@ - (NSString *)getSkAdNetworkCoarseConversionValue:(NSString *)adjustCoarseValue } else { return nil; } -#else - return nil; -#endif } @end From a120b26b309c43f001dad9ffe8955df60de1caa1 Mon Sep 17 00:00:00 2001 From: genadyb Date: Fri, 13 Dec 2024 12:41:03 +0100 Subject: [PATCH 05/15] chore: improves logging for SKAN calls --- Adjust/Internal/ADJSKAdNetwork.m | 36 +++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/Adjust/Internal/ADJSKAdNetwork.m b/Adjust/Internal/ADJSKAdNetwork.m index 67727a878..2cf09327e 100644 --- a/Adjust/Internal/ADJSKAdNetwork.m +++ b/Adjust/Internal/ADJSKAdNetwork.m @@ -180,6 +180,12 @@ - (void)registerWithConversionValue:(NSInteger)conversionValue coarseValue:[self getSkAdNetworkCoarseConversionValue:coarseValue] lockWindow:lockWindow withCompletionHandler:^(NSError * _Nullable error) { + if (error) { + [self.logger error:@"Registration: call to SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d failed\nDescription: %@", conversionValue, coarseValue, [lockWindow boolValue], error.localizedDescription]; + } else { + [self.logger debug:@"Registration: called SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d", conversionValue, coarseValue, [lockWindow boolValue]]; + } + if (error == nil) { [self writeSkAdNetworkRegisterCallTimestamp]; } @@ -190,6 +196,11 @@ - (void)registerWithConversionValue:(NSInteger)conversionValue } else if (@available(iOS 15.4, *)) { [self updatePostbackConversionValue:conversionValue withCompletionHandler:^(NSError * _Nullable error) { + if (error) { + [self.logger error:@"Registration: call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription]; + } else { + [self.logger debug:@"Registration: called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d", conversionValue]; + } if (error == nil) { [self writeSkAdNetworkRegisterCallTimestamp]; } @@ -199,6 +210,11 @@ - (void)registerWithConversionValue:(NSInteger)conversionValue }]; } else { // if (@available(iOS 14.0, *)) { already checked in 'checkSKAdNetworkFrameworkAvailability' [self registerAppForAdNetworkAttributionWithCompletionHandler:^(NSError *error) { + if (error) { + [self.logger error:@"Registration: call to SKAdNetwork's registerAppForAdNetworkAttribution method failed\nDescription: %@", error.localizedDescription]; + } else { + [self.logger debug:@"Registration: called SKAdNetwork's registerAppForAdNetworkAttribution method"]; + } if (error == nil) { [self writeSkAdNetworkRegisterCallTimestamp]; } @@ -232,9 +248,9 @@ - (void)updateConversionValue:(NSInteger)conversionValue lockWindow:[lockWindow boolValue] withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Call to SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d failed\nDescription: %@", conversionValue, coarseValue, [lockWindow boolValue], error.localizedDescription]; + [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d failed\nDescription: %@", conversionValue, coarseValue, [lockWindow boolValue], error.localizedDescription]; } else { - [self.logger debug:@"Called SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d", conversionValue, coarseValue, [lockWindow boolValue]]; + [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d", conversionValue, coarseValue, [lockWindow boolValue]]; } if (completion != nil) { completion(error); @@ -246,9 +262,9 @@ - (void)updateConversionValue:(NSInteger)conversionValue coarseValue:[self getSkAdNetworkCoarseConversionValue:coarseValue] withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Call to SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method with conversion value: %d, coarse value: %@ failed\nDescription: %@", conversionValue, coarseValue, error.localizedDescription]; + [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method with conversion value: %d, coarse value: %@ failed\nDescription: %@", conversionValue, coarseValue, error.localizedDescription]; } else { - [self.logger debug:@"Called SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method with conversion value: %d, coarse value: %@", conversionValue, coarseValue]; + [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method with conversion value: %d, coarse value: %@", conversionValue, coarseValue]; } if (completion != nil) { completion(error); @@ -261,9 +277,9 @@ - (void)updateConversionValue:(NSInteger)conversionValue [self updatePostbackConversionValue:conversionValue withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription]; + [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription]; } else { - [self.logger debug:@"Called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d", conversionValue]; + [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d", conversionValue]; } if (completion != nil) { completion(error); @@ -274,9 +290,9 @@ - (void)updateConversionValue:(NSInteger)conversionValue [self updatePostbackConversionValue:conversionValue withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription]; + [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription]; } else { - [self.logger debug:@"Called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d", conversionValue]; + [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d", conversionValue]; } if (completion != nil) { completion(error); @@ -285,9 +301,9 @@ - (void)updateConversionValue:(NSInteger)conversionValue } else { //if (@available(iOS 14.0, *)) { already checked in 'checkSKAdNetworkFrameworkAvailability' [self updateConversionValue:conversionValue withCompletionHandler:^(NSError *error) { if (error) { - [self.logger error:@"Call to SKAdNetwork's updateConversionValue: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription]; + [self.logger error:@"Update CV: call to SKAdNetwork's updateConversionValue: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription]; } else { - [self.logger debug:@"Called SKAdNetwork's updateConversionValue: method with conversion value: %d", conversionValue]; + [self.logger debug:@"Update CV: called SKAdNetwork's updateConversionValue: method with conversion value: %d", conversionValue]; } if (completion != nil) { completion(error); From 418200563ebfa5e7d07fda287677d9226aab1537 Mon Sep 17 00:00:00 2001 From: genadyb Date: Fri, 13 Dec 2024 17:40:23 +0100 Subject: [PATCH 06/15] feat: implements sending last SKAN update data to the backend --- Adjust/Adjust.m | 1 + Adjust/Internal/ADJActivityHandler.m | 9 +-- Adjust/Internal/ADJPackageBuilder.m | 19 +++++ Adjust/Internal/ADJSKAdNetwork.h | 6 ++ Adjust/Internal/ADJSKAdNetwork.m | 111 +++++++++++++++++++++++---- Adjust/Internal/ADJUserDefaults.h | 6 ++ Adjust/Internal/ADJUserDefaults.m | 10 +++ 7 files changed, 141 insertions(+), 21 deletions(-) diff --git a/Adjust/Adjust.m b/Adjust/Adjust.m index ab209d535..212c45102 100644 --- a/Adjust/Adjust.m +++ b/Adjust/Adjust.m @@ -628,6 +628,7 @@ - (void)updateSkanConversionValue:(NSInteger)conversionValue [[ADJSKAdNetwork getInstance] updateConversionValue:conversionValue coarseValue:coarseValue lockWindow:lockWindow + source:ADJSKAdNetworkCallSourceClient withCompletionHandler:completion]; } diff --git a/Adjust/Internal/ADJActivityHandler.m b/Adjust/Internal/ADJActivityHandler.m index 61474d6d1..b863a011b 100644 --- a/Adjust/Internal/ADJActivityHandler.m +++ b/Adjust/Internal/ADJActivityHandler.m @@ -182,14 +182,8 @@ - (id)initWithConfig:(ADJConfig *_Nullable)adjustConfig [self readAttribution]; [self readActivityState]; - - NSDate *skanRegisterDate = [ADJUserDefaults getSkadRegisterCallTimestamp]; - if (skanRegisterDate != nil) { - [self.logger debug:@"Call to register app with SKAdNetwork already made for this install"]; - } - // register SKAdNetwork attribution if we haven't already - if (self.adjustConfig.isSkanAttributionEnabled && !skanRegisterDate) { + if (self.adjustConfig.isSkanAttributionEnabled) { NSNumber *numConversionValue = [NSNumber numberWithInteger:kSkanRegisterConversionValue]; NSNumber *numLockWindow = [NSNumber numberWithBool:kSkanRegisterLockWindow]; @@ -2782,6 +2776,7 @@ - (void)checkConversionValue:(ADJResponseData *)responseData { [[ADJSKAdNetwork getInstance] updateConversionValue:[conversionValue intValue] coarseValue:coarseValue lockWindow:lockWindow + source:ADJSKAdNetworkCallSourceBackend withCompletionHandler:^(NSError *error) { [self notifySkanCallbackWithConversionValue:conversionValue coarseValue:coarseValue diff --git a/Adjust/Internal/ADJPackageBuilder.m b/Adjust/Internal/ADJPackageBuilder.m index 0e7fd178e..269a1893a 100644 --- a/Adjust/Internal/ADJPackageBuilder.m +++ b/Adjust/Internal/ADJPackageBuilder.m @@ -18,6 +18,7 @@ #import "ADJAdRevenue.h" #import "ADJAppStorePurchase.h" #import "ADJAppStoreSubscription.h" +#import "ADJSKAdNetwork.h" NSString * const ADJAttributionTokenParameter = @"attribution_token"; @@ -366,6 +367,7 @@ - (NSMutableDictionary *)getSessionParameters { [self addConsentToParameters:parameters forActivityKind:ADJActivityKindSession]; [self addIdfvIfPossibleToParameters:parameters]; [self injectFeatureFlagsWithParameters:parameters]; + [self injectLastSkanUpdateWithParameters:parameters]; return parameters; } @@ -433,6 +435,7 @@ - (NSMutableDictionary *)getEventParameters:(ADJEvent *)event { [self addConsentToParameters:parameters forActivityKind:ADJActivityKindEvent]; [self addIdfvIfPossibleToParameters:parameters]; [self injectFeatureFlagsWithParameters:parameters]; + [self injectLastSkanUpdateWithParameters:parameters]; return parameters; } @@ -500,6 +503,7 @@ - (NSMutableDictionary *)getInfoParameters:(NSString *)source { [self addConsentToParameters:parameters forActivityKind:ADJActivityKindInfo]; [self addIdfvIfPossibleToParameters:parameters]; [self injectFeatureFlagsWithParameters:parameters]; + [self injectLastSkanUpdateWithParameters:parameters]; return parameters; } @@ -568,6 +572,7 @@ - (NSMutableDictionary *)getAdRevenueParameters:(ADJAdRevenue *)adRevenue { [self addConsentToParameters:parameters forActivityKind:ADJActivityKindAdRevenue]; [self addIdfvIfPossibleToParameters:parameters]; [self injectFeatureFlagsWithParameters:parameters]; + [self injectLastSkanUpdateWithParameters:parameters]; return parameters; } @@ -635,6 +640,7 @@ - (NSMutableDictionary *)getClickParameters:(NSString *)source { [self addConsentToParameters:parameters forActivityKind:ADJActivityKindClick]; [self addIdfvIfPossibleToParameters:parameters]; [self injectFeatureFlagsWithParameters:parameters]; + [self injectLastSkanUpdateWithParameters:parameters]; return parameters; } @@ -684,6 +690,7 @@ - (NSMutableDictionary *)getAttributionParameters:(NSString *)initiatedBy { [self addConsentToParameters:parameters forActivityKind:ADJActivityKindAttribution]; [self addIdfvIfPossibleToParameters:parameters]; [self injectFeatureFlagsWithParameters:parameters]; + [self injectLastSkanUpdateWithParameters:parameters]; return parameters; } @@ -728,6 +735,7 @@ - (NSMutableDictionary *)getGdprParameters { [self addConsentToParameters:parameters forActivityKind:ADJActivityKindGdpr]; [self addIdfvIfPossibleToParameters:parameters]; [self injectFeatureFlagsWithParameters:parameters]; + [self injectLastSkanUpdateWithParameters:parameters]; return parameters; } @@ -799,6 +807,7 @@ - (NSMutableDictionary *)getThirdPartySharingParameters:(nonnull ADJThirdPartySh [self addConsentToParameters:parameters forActivityKind:ADJActivityKindThirdPartySharing]; [self addIdfvIfPossibleToParameters:parameters]; [self injectFeatureFlagsWithParameters:parameters]; + [self injectLastSkanUpdateWithParameters:parameters]; return parameters; } @@ -864,6 +873,7 @@ - (NSMutableDictionary *)getMeasurementConsentParameters:(BOOL)enabled { [self addConsentToParameters:parameters forActivityKind:ADJActivityKindMeasurementConsent]; [self addIdfvIfPossibleToParameters:parameters]; [self injectFeatureFlagsWithParameters:parameters]; + [self injectLastSkanUpdateWithParameters:parameters]; return parameters; } @@ -928,6 +938,7 @@ - (NSMutableDictionary *)getSubscriptionParameters:(ADJAppStoreSubscription *)su [self addConsentToParameters:parameters forActivityKind:ADJActivityKindSubscription]; [self addIdfvIfPossibleToParameters:parameters]; [self injectFeatureFlagsWithParameters:parameters]; + [self injectLastSkanUpdateWithParameters:parameters]; return parameters; } @@ -982,6 +993,7 @@ - (NSMutableDictionary *)getPurchaseVerificationParameters { [self addConsentToParameters:parameters forActivityKind:ADJActivityKindPurchaseVerification]; [self addIdfvIfPossibleToParameters:parameters]; [self injectFeatureFlagsWithParameters:parameters]; + [self injectLastSkanUpdateWithParameters:parameters]; return parameters; } @@ -1031,6 +1043,13 @@ - (void)injectFeatureFlagsWithParameters:(NSMutableDictionary *)parameters { } } +- (void)injectLastSkanUpdateWithParameters:(NSMutableDictionary *)parameters { + NSDictionary *lastSkanUpdateData = [[ADJSKAdNetwork getInstance] lastSKAdNetworkUpdateData]; + if (lastSkanUpdateData != nil) { + [ADJPackageBuilder parameters:parameters setDictionaryJson:lastSkanUpdateData forKey:@"last_skan_update"]; + } +} + - (ADJActivityPackage *)defaultActivityPackage { ADJActivityPackage *activityPackage = [[ADJActivityPackage alloc] init]; activityPackage.clientSdk = self.packageParams.clientSdk; diff --git a/Adjust/Internal/ADJSKAdNetwork.h b/Adjust/Internal/ADJSKAdNetwork.h index cdd7b57a0..ee2b0b674 100644 --- a/Adjust/Internal/ADJSKAdNetwork.h +++ b/Adjust/Internal/ADJSKAdNetwork.h @@ -10,6 +10,10 @@ @interface ADJSKAdNetwork : NSObject +extern NSString * _Nonnull const ADJSKAdNetworkCallSourceSdk; +extern NSString * _Nonnull const ADJSKAdNetworkCallSourceBackend; +extern NSString * _Nonnull const ADJSKAdNetworkCallSourceClient; + + (nullable instancetype)getInstance; - (void)registerWithConversionValue:(NSInteger)conversionValue @@ -20,6 +24,8 @@ - (void)updateConversionValue:(NSInteger)conversionValue coarseValue:(nullable NSString *)coarseValue lockWindow:(nullable NSNumber *)lockWindow + source:(nonnull NSString *)source withCompletionHandler:(void (^_Nullable)(NSError *_Nullable error))completion; +- (NSDictionary * _Nullable)lastSKAdNetworkUpdateData; @end diff --git a/Adjust/Internal/ADJSKAdNetwork.m b/Adjust/Internal/ADJSKAdNetwork.m index 2cf09327e..6f295c89f 100644 --- a/Adjust/Internal/ADJSKAdNetwork.m +++ b/Adjust/Internal/ADJSKAdNetwork.m @@ -12,14 +12,9 @@ #import "ADJUserDefaults.h" #import "ADJAdjustFactory.h" #import "ADJLogger.h" +#import "ADJUtil.h" static const char * const kInternalQueueName = "io.adjust.SKAdNetworkQueue"; - -@interface ADJSKAdNetwork() -@property (nonatomic, weak) id logger; -@property (nonatomic, strong) dispatch_queue_t internalQueue; -@end - static NSString * const ADJSKAdNetworkDomain = @"com.adjust.sdk.skadnetwork"; typedef NS_ENUM(NSInteger, ADJSKAdNetworkError) { ADJSKAdNetworkErrorOsNotSupported = -100, @@ -27,6 +22,16 @@ typedef NS_ENUM(NSInteger, ADJSKAdNetworkError) { ADJSKAdNetworkErrorApiNotAvailable = -102 }; +NSString * const ADJSKAdNetworkCallSourceSdk = @"sdk"; +NSString * const ADJSKAdNetworkCallSourceBackend = @"backend"; +NSString * const ADJSKAdNetworkCallSourceClient = @"client"; + +@interface ADJSKAdNetwork() +@property (nonatomic, weak) id logger; +@property (nonatomic, strong) dispatch_queue_t internalQueue; +@end + + @implementation ADJSKAdNetwork #pragma mark - Lifecycle @@ -167,6 +172,13 @@ - (void)registerWithConversionValue:(NSInteger)conversionValue lockWindow:(nonnull NSNumber *)lockWindow withCompletionHandler:(void (^_Nonnull)(NSError *_Nullable error))completion { + + NSDate *skanRegisterDate = [self skadNetworkRegisterCallTimestamp]; + if (skanRegisterDate != nil) { + [self.logger debug:@"Call to register app with SKAdNetwork already made for this install"]; + return; + } + NSError *error = nil; // Check iOS 14.0+ / NON-tvOS / SKAdNetwork framework available if (![self checkSKAdNetworkFrameworkAvailability:&error]) { @@ -177,7 +189,7 @@ - (void)registerWithConversionValue:(NSInteger)conversionValue if (@available(iOS 16.1, *)) { [self updatePostbackConversionValue:conversionValue - coarseValue:[self getSkAdNetworkCoarseConversionValue:coarseValue] + coarseValue:[self getSKAdNetworkCoarseConversionValue:coarseValue] lockWindow:lockWindow withCompletionHandler:^(NSError * _Nullable error) { if (error) { @@ -187,7 +199,12 @@ - (void)registerWithConversionValue:(NSInteger)conversionValue } if (error == nil) { - [self writeSkAdNetworkRegisterCallTimestamp]; + [self writeSKAdNetworkRegisterCallTimestamp]; + [self writeLastSKAdNetworkUpdateConversionValue:[NSNumber numberWithInteger:conversionValue] + coarseValue:[self getSKAdNetworkCoarseConversionValue:coarseValue] + lockWindow:lockWindow + timestamp:[NSDate date] + source:ADJSKAdNetworkCallSourceSdk]; } if (completion != nil) { completion(error); @@ -202,7 +219,12 @@ - (void)registerWithConversionValue:(NSInteger)conversionValue [self.logger debug:@"Registration: called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d", conversionValue]; } if (error == nil) { - [self writeSkAdNetworkRegisterCallTimestamp]; + [self writeSKAdNetworkRegisterCallTimestamp]; + [self writeLastSKAdNetworkUpdateConversionValue:[NSNumber numberWithInteger:conversionValue] + coarseValue:nil + lockWindow:nil + timestamp:[NSDate date] + source:ADJSKAdNetworkCallSourceSdk]; } if (completion != nil) { completion(error); @@ -216,7 +238,12 @@ - (void)registerWithConversionValue:(NSInteger)conversionValue [self.logger debug:@"Registration: called SKAdNetwork's registerAppForAdNetworkAttribution method"]; } if (error == nil) { - [self writeSkAdNetworkRegisterCallTimestamp]; + [self writeSKAdNetworkRegisterCallTimestamp]; + [self writeLastSKAdNetworkUpdateConversionValue:nil + coarseValue:nil + lockWindow:nil + timestamp:[NSDate date] + source:ADJSKAdNetworkCallSourceSdk]; } if (completion != nil) { completion(error); @@ -228,6 +255,7 @@ - (void)registerWithConversionValue:(NSInteger)conversionValue - (void)updateConversionValue:(NSInteger)conversionValue coarseValue:(nullable NSString *)coarseValue lockWindow:(nullable NSNumber *)lockWindow + source:(nonnull NSString *)source withCompletionHandler:(void (^_Nullable)(NSError *_Nullable error))completion { NSError *error = nil; @@ -244,13 +272,18 @@ - (void)updateConversionValue:(NSInteger)conversionValue if (lockWindow != nil) { // they do both [self updatePostbackConversionValue:conversionValue - coarseValue:[self getSkAdNetworkCoarseConversionValue:coarseValue] + coarseValue:[self getSKAdNetworkCoarseConversionValue:coarseValue] lockWindow:[lockWindow boolValue] withCompletionHandler:^(NSError * _Nullable error) { if (error) { [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d failed\nDescription: %@", conversionValue, coarseValue, [lockWindow boolValue], error.localizedDescription]; } else { [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d", conversionValue, coarseValue, [lockWindow boolValue]]; + [self writeLastSKAdNetworkUpdateConversionValue:[NSNumber numberWithInteger:conversionValue] + coarseValue:[self getSKAdNetworkCoarseConversionValue:coarseValue] + lockWindow:lockWindow + timestamp:[NSDate date] + source:source]; } if (completion != nil) { completion(error); @@ -259,12 +292,17 @@ - (void)updateConversionValue:(NSInteger)conversionValue } else { // Only coarse value is received [self updatePostbackConversionValue:conversionValue - coarseValue:[self getSkAdNetworkCoarseConversionValue:coarseValue] + coarseValue:[self getSKAdNetworkCoarseConversionValue:coarseValue] withCompletionHandler:^(NSError * _Nullable error) { if (error) { [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method with conversion value: %d, coarse value: %@ failed\nDescription: %@", conversionValue, coarseValue, error.localizedDescription]; } else { [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method with conversion value: %d, coarse value: %@", conversionValue, coarseValue]; + [self writeLastSKAdNetworkUpdateConversionValue:[NSNumber numberWithInteger:conversionValue] + coarseValue:[self getSKAdNetworkCoarseConversionValue:coarseValue] + lockWindow:nil + timestamp:[NSDate date] + source:source]; } if (completion != nil) { completion(error); @@ -280,6 +318,11 @@ - (void)updateConversionValue:(NSInteger)conversionValue [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription]; } else { [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d", conversionValue]; + [self writeLastSKAdNetworkUpdateConversionValue:[NSNumber numberWithInteger:conversionValue] + coarseValue:nil + lockWindow:nil + timestamp:[NSDate date] + source:source]; } if (completion != nil) { completion(error); @@ -293,6 +336,11 @@ - (void)updateConversionValue:(NSInteger)conversionValue [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription]; } else { [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d", conversionValue]; + [self writeLastSKAdNetworkUpdateConversionValue:[NSNumber numberWithInteger:conversionValue] + coarseValue:nil + lockWindow:nil + timestamp:[NSDate date] + source:source]; } if (completion != nil) { completion(error); @@ -304,6 +352,11 @@ - (void)updateConversionValue:(NSInteger)conversionValue [self.logger error:@"Update CV: call to SKAdNetwork's updateConversionValue: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription]; } else { [self.logger debug:@"Update CV: called SKAdNetwork's updateConversionValue: method with conversion value: %d", conversionValue]; + [self writeLastSKAdNetworkUpdateConversionValue:[NSNumber numberWithInteger:conversionValue] + coarseValue:nil + lockWindow:nil + timestamp:[NSDate date] + source:source]; } if (completion != nil) { completion(error); @@ -364,12 +417,42 @@ - (void)asyncSendResultError:(NSError *_Nullable)error }); } -- (void)writeSkAdNetworkRegisterCallTimestamp { +- (void)writeSKAdNetworkRegisterCallTimestamp { NSDate *callTime = [NSDate date]; [ADJUserDefaults saveSkadRegisterCallTimestamp:callTime]; } -- (NSString *)getSkAdNetworkCoarseConversionValue:(NSString *)adjustCoarseValue { +- (NSDate *)skadNetworkRegisterCallTimestamp { + return [ADJUserDefaults getSkadRegisterCallTimestamp]; +} + +- (void)writeLastSKAdNetworkUpdateConversionValue:(NSNumber * _Nullable)conversionValue + coarseValue:(NSString * _Nullable)coarseValue + lockWindow:(NSNumber * _Nullable)lockWindow + timestamp:(NSDate * _Nonnull)timestamp + source:(NSString * _Nonnull)source { + + NSMutableDictionary *skanUpdateData = [NSMutableDictionary dictionary]; + if (conversionValue != nil) { + [skanUpdateData setObject:conversionValue forKey:@"conv"]; + } + if (coarseValue != nil) { + [skanUpdateData setObject:coarseValue forKey:@"coav"]; + } + if (lockWindow != nil) { + [skanUpdateData setObject:lockWindow forKey:@"lw"]; + } + [skanUpdateData setObject:[ADJUtil formatDate:timestamp] forKey:@"ts"]; + [skanUpdateData setObject:source forKey:@"source"]; + + [ADJUserDefaults saveLastSkanUpdateData:skanUpdateData]; +} + +- (NSDictionary *)lastSKAdNetworkUpdateData { + return [ADJUserDefaults getLastSkanUpdateData]; +} + +- (NSString *)getSKAdNetworkCoarseConversionValue:(NSString *)adjustCoarseValue { if (@available(iOS 16.1, *)) { if ([adjustCoarseValue isEqualToString:@"low"]) { NSString * __autoreleasing *lowValue = (NSString * __autoreleasing *)dlsym(RTLD_DEFAULT, "SKAdNetworkCoarseConversionValueLow"); diff --git a/Adjust/Internal/ADJUserDefaults.h b/Adjust/Internal/ADJUserDefaults.h index 0e420d144..f01ec93d9 100644 --- a/Adjust/Internal/ADJUserDefaults.h +++ b/Adjust/Internal/ADJUserDefaults.h @@ -69,4 +69,10 @@ + (NSDictionary *)getControlParams; ++ (void)saveLastSkanUpdateData:(NSDictionary *)skanData; + ++ (NSDictionary *)getLastSkanUpdateData; + + + @end diff --git a/Adjust/Internal/ADJUserDefaults.m b/Adjust/Internal/ADJUserDefaults.m index 87b35becf..2db06b84c 100644 --- a/Adjust/Internal/ADJUserDefaults.m +++ b/Adjust/Internal/ADJUserDefaults.m @@ -20,6 +20,7 @@ static NSString * const PREFS_KEY_DEEPLINK_URL_CACHED = @"adj_deeplink_url_cached"; static NSString * const PREFS_KEY_ATT_WAITING_REMAINING_SECONDS = @"adj_att_waiting_remaining_seconds"; static NSString * const PREFS_KEY_CONTROL_PARAMS = @"adj_control_params"; +static NSString * const PREFS_KEY_LAST_SKAN_UPDATE_DATA = @"adj_last_skan_update"; @implementation ADJUserDefaults @@ -143,6 +144,14 @@ + (NSDictionary *)getControlParams { return [[NSUserDefaults standardUserDefaults] dictionaryForKey:PREFS_KEY_CONTROL_PARAMS]; } ++ (void)saveLastSkanUpdateData:(NSDictionary *)skanUpdateData { + [[NSUserDefaults standardUserDefaults] setObject:skanUpdateData forKey:PREFS_KEY_LAST_SKAN_UPDATE_DATA]; +} + ++ (NSDictionary *)getLastSkanUpdateData { + return [[NSUserDefaults standardUserDefaults] dictionaryForKey:PREFS_KEY_LAST_SKAN_UPDATE_DATA]; +} + + (void)clearAdjustStuff { [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_PUSH_TOKEN_DATA]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_PUSH_TOKEN_STRING]; @@ -156,6 +165,7 @@ + (void)clearAdjustStuff { [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_DEEPLINK_URL_CACHED]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_ATT_WAITING_REMAINING_SECONDS]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_CONTROL_PARAMS]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:PREFS_KEY_LAST_SKAN_UPDATE_DATA]; } @end From 95f54a7ce996f01806857ff153e02b90e1812ebc Mon Sep 17 00:00:00 2001 From: genadyb Date: Mon, 6 Jan 2025 14:11:16 +0100 Subject: [PATCH 07/15] refac: added call to client skan callback when invoked by the client --- Adjust/Adjust.m | 12 +- Adjust/Internal/ADJActivityHandler.h | 1 + Adjust/Internal/ADJActivityHandler.m | 46 +---- Adjust/Internal/ADJSKAdNetwork.h | 10 +- Adjust/Internal/ADJSKAdNetwork.m | 279 +++++++++++++++++++-------- 5 files changed, 222 insertions(+), 126 deletions(-) diff --git a/Adjust/Adjust.m b/Adjust/Adjust.m index 212c45102..c38134ca8 100644 --- a/Adjust/Adjust.m +++ b/Adjust/Adjust.m @@ -625,11 +625,19 @@ - (void)updateSkanConversionValue:(NSInteger)conversionValue coarseValue:(nullable NSString *)coarseValue lockWindow:(nullable NSNumber *)lockWindow withCompletionHandler:(void (^_Nullable)(NSError *_Nullable error))completion { - [[ADJSKAdNetwork getInstance] updateConversionValue:conversionValue + + [[ADJSKAdNetwork getInstance] updateConversionValue:[NSNumber numberWithInteger:conversionValue] coarseValue:coarseValue lockWindow:lockWindow source:ADJSKAdNetworkCallSourceClient - withCompletionHandler:completion]; + withCompletionHandler:^(NSDictionary * _Nonnull result) { + if ([self checkActivityHandler]) { + [self.activityHandler invokeClientSkanUpdateCallbackWithResult:result]; + } + if (completion != nil) { + completion([result objectForKey:ADJSKAdNetworkCallErrorKey]); + } + }]; } - (void)trackAdRevenue:(ADJAdRevenue *)adRevenue { diff --git a/Adjust/Internal/ADJActivityHandler.h b/Adjust/Internal/ADJActivityHandler.h index 1ec772a06..c9e7a1cee 100644 --- a/Adjust/Internal/ADJActivityHandler.h +++ b/Adjust/Internal/ADJActivityHandler.h @@ -111,6 +111,7 @@ - (void)adidWithCompletionHandler:(nonnull ADJAdidGetterBlock)completion; - (void)verifyAndTrackAppStorePurchase:(nonnull ADJEvent *)event withCompletionHandler:(nonnull ADJVerificationResultBlock)completion; +- (void)invokeClientSkanUpdateCallbackWithResult:(NSDictionary * _Nonnull)result; - (ADJPackageParams * _Nullable)packageParams; - (ADJActivityState * _Nullable)activityState; diff --git a/Adjust/Internal/ADJActivityHandler.m b/Adjust/Internal/ADJActivityHandler.m index b863a011b..2b386fd58 100644 --- a/Adjust/Internal/ADJActivityHandler.m +++ b/Adjust/Internal/ADJActivityHandler.m @@ -44,10 +44,6 @@ static NSString * const kSkanConversionValueResponseKey = @"skadn_conv_value"; static NSString * const kSkanCoarseValueResponseKey = @"skadn_coarse_value"; static NSString * const kSkanLockWindowResponseKey = @"skadn_lock_window"; -static NSString * const kSkanConversionValueCallbackKey = @"conversion_value"; -static NSString * const kSkanCoarseValueCallbackKey = @"coarse_value"; -static NSString * const kSkanLockWindowCallbackKey = @"lock_window"; -static NSString * const kSkanErrorCallbackKey = @"error"; static NSTimeInterval kForegroundTimerInterval; static NSTimeInterval kForegroundTimerStart; @@ -187,15 +183,11 @@ - (id)initWithConfig:(ADJConfig *_Nullable)adjustConfig NSNumber *numConversionValue = [NSNumber numberWithInteger:kSkanRegisterConversionValue]; NSNumber *numLockWindow = [NSNumber numberWithBool:kSkanRegisterLockWindow]; - [[ADJSKAdNetwork getInstance] registerWithConversionValue:kSkanRegisterConversionValue + [[ADJSKAdNetwork getInstance] registerWithConversionValue:numConversionValue coarseValue:kSkanRegisterCoarseValue lockWindow:numLockWindow - withCompletionHandler:^(NSError * _Nonnull error) { - - [self notifySkanCallbackWithConversionValue:numConversionValue - coarseValue:kSkanRegisterCoarseValue - lockWindow:numLockWindow - apiInvocationError:error]; + withCompletionHandler:^(NSDictionary * _Nonnull result) { + [self invokeClientSkanUpdateCallbackWithResult:result]; }]; } @@ -2773,15 +2765,12 @@ - (void)checkConversionValue:(ADJResponseData *)responseData { NSString *coarseValue = [responseData.jsonResponse objectForKey:kSkanCoarseValueResponseKey]; NSNumber *lockWindow = [responseData.jsonResponse objectForKey:kSkanLockWindowResponseKey]; - [[ADJSKAdNetwork getInstance] updateConversionValue:[conversionValue intValue] + [[ADJSKAdNetwork getInstance] updateConversionValue:conversionValue coarseValue:coarseValue lockWindow:lockWindow source:ADJSKAdNetworkCallSourceBackend - withCompletionHandler:^(NSError *error) { - [self notifySkanCallbackWithConversionValue:conversionValue - coarseValue:coarseValue - lockWindow:lockWindow - apiInvocationError:error]; + withCompletionHandler:^(NSDictionary * _Nonnull result) { + [self invokeClientSkanUpdateCallbackWithResult:result]; }]; } @@ -2789,7 +2778,6 @@ - (void)updateAttStatusFromUserCallback:(int)newAttStatusFromUser { [self.trackingStatusManager updateAttStatusFromUserCallback:newAttStatusFromUser]; } - - (void)processCoppaComplianceI:(ADJActivityHandler *)selfI { if (!selfI.adjustConfig.isCoppaComplianceEnabled) { [self resetThirdPartySharingCoppaActivityStateI:selfI]; @@ -2858,26 +2846,8 @@ - (BOOL)shouldDisableThirdPartySharingWhenCoppaEnabled:(ADJActivityHandler *)sel return !selfI.activityState.isThirdPartySharingDisabledForCoppa; } -#pragma mark Utils - -- (void)notifySkanCallbackWithConversionValue:(nonnull NSNumber *)conversionValue - coarseValue:(nullable NSString *)coarseValue - lockWindow:(nullable NSNumber *)lockWindow - apiInvocationError:(nullable NSError *)error { - // Create updated conversion data dictionary - NSMutableDictionary *conversionParams = [[NSMutableDictionary alloc] init]; - [conversionParams setObject:conversionValue.stringValue forKey:kSkanConversionValueCallbackKey]; - if (coarseValue != nil) { - [conversionParams setObject:coarseValue forKey:kSkanCoarseValueCallbackKey]; - } - if (lockWindow != nil) { - NSString *val = (lockWindow.boolValue) ? @"true" : @"false"; - [conversionParams setObject:val forKey:kSkanLockWindowCallbackKey]; - } - if (error != nil) { - [conversionParams setObject:error.localizedDescription forKey:kSkanErrorCallbackKey]; - } - +- (void)invokeClientSkanUpdateCallbackWithResult:(NSDictionary * _Nonnull)result { + NSDictionary *conversionParams = [result objectForKey:ADJSKAdNetworkCallActualConversionParamsKey]; // Ping the callback method if implemented if ([self.adjustDelegate respondsToSelector:@selector(adjustSkanUpdatedWithConversionData:)]) { [self.logger debug:@"Launching delegate's method adjustSkanUpdatedWithConversionData:"]; diff --git a/Adjust/Internal/ADJSKAdNetwork.h b/Adjust/Internal/ADJSKAdNetwork.h index ee2b0b674..fedd1b6af 100644 --- a/Adjust/Internal/ADJSKAdNetwork.h +++ b/Adjust/Internal/ADJSKAdNetwork.h @@ -13,19 +13,21 @@ extern NSString * _Nonnull const ADJSKAdNetworkCallSourceSdk; extern NSString * _Nonnull const ADJSKAdNetworkCallSourceBackend; extern NSString * _Nonnull const ADJSKAdNetworkCallSourceClient; +extern NSString * _Nonnull const ADJSKAdNetworkCallActualConversionParamsKey; +extern NSString * _Nonnull const ADJSKAdNetworkCallErrorKey; + (nullable instancetype)getInstance; -- (void)registerWithConversionValue:(NSInteger)conversionValue +- (void)registerWithConversionValue:(nonnull NSNumber *)conversionValue coarseValue:(nonnull NSString *)coarseValue lockWindow:(nonnull NSNumber *)lockWindow - withCompletionHandler:(void (^_Nonnull)(NSError *_Nullable error))completion; + withCompletionHandler:(void (^_Nonnull)(NSDictionary *_Nonnull result))completion; -- (void)updateConversionValue:(NSInteger)conversionValue +- (void)updateConversionValue:(nonnull NSNumber *)conversionValue coarseValue:(nullable NSString *)coarseValue lockWindow:(nullable NSNumber *)lockWindow source:(nonnull NSString *)source - withCompletionHandler:(void (^_Nullable)(NSError *_Nullable error))completion; + withCompletionHandler:(void (^_Nonnull)(NSDictionary *_Nonnull result))completion; - (NSDictionary * _Nullable)lastSKAdNetworkUpdateData; @end diff --git a/Adjust/Internal/ADJSKAdNetwork.m b/Adjust/Internal/ADJSKAdNetwork.m index 6f295c89f..f17b80756 100644 --- a/Adjust/Internal/ADJSKAdNetwork.m +++ b/Adjust/Internal/ADJSKAdNetwork.m @@ -19,19 +19,27 @@ typedef NS_ENUM(NSInteger, ADJSKAdNetworkError) { ADJSKAdNetworkErrorOsNotSupported = -100, ADJSKAdNetworkErrorFrameworkNotFound = -101, - ADJSKAdNetworkErrorApiNotAvailable = -102 + ADJSKAdNetworkErrorApiNotAvailable = -102, + ADJSKAdNetworkErrorInvalidCoarseValue = -103 }; +// Externally Available constants NSString * const ADJSKAdNetworkCallSourceSdk = @"sdk"; NSString * const ADJSKAdNetworkCallSourceBackend = @"backend"; NSString * const ADJSKAdNetworkCallSourceClient = @"client"; +NSString * const ADJSKAdNetworkCallActualConversionParamsKey = @"skan_call_actual_conversion_params"; +NSString * const ADJSKAdNetworkCallErrorKey = @"skan_call_error"; + +static NSString * const kSkanConversionValueCallbackKey = @"conversion_value"; +static NSString * const kSkanCoarseValueCallbackKey = @"coarse_value"; +static NSString * const kSkanLockWindowCallbackKey = @"lock_window"; +static NSString * const kSkanErrorCallbackKey = @"error"; @interface ADJSKAdNetwork() @property (nonatomic, weak) id logger; @property (nonatomic, strong) dispatch_queue_t internalQueue; @end - @implementation ADJSKAdNetwork #pragma mark - Lifecycle @@ -63,7 +71,7 @@ - (void)registerAppForAdNetworkAttributionWithCompletionHandler:(void (^)(NSErro NSError *error = [self checkSKAdNetworkMethodAvailability:@"registerAppForAdNetworkAttribution"]; if (error != nil) { - [self asyncSendResultError:error toCompletionHandler:completion]; + [self sendSkanCallError:error toCompletionHandler:completion]; return; } @@ -75,7 +83,7 @@ - (void)registerAppForAdNetworkAttributionWithCompletionHandler:(void (^)(NSErro [invocation setTarget:class]; [invocation invoke]; [self.logger verbose:@"Call to SKAdNetwork's registerAppForAdNetworkAttribution method made"]; - [self asyncSendResultError:error toCompletionHandler:completion]; + [self sendSkanCallError:error toCompletionHandler:completion]; } - (void)updateConversionValue:(NSInteger)conversionValue @@ -83,7 +91,7 @@ - (void)updateConversionValue:(NSInteger)conversionValue NSError *error = [self checkSKAdNetworkMethodAvailability:@"updateConversionValue:"]; if (error != nil) { - [self asyncSendResultError:error toCompletionHandler:completion]; + [self sendSkanCallError:error toCompletionHandler:completion]; return; } @@ -96,7 +104,7 @@ - (void)updateConversionValue:(NSInteger)conversionValue [invocation setArgument:&conversionValue atIndex:2]; [invocation invoke]; [self.logger verbose:@"Call to SKAdNetwork's updateConversionValue: method made with value %d", conversionValue]; - [self asyncSendResultError:error toCompletionHandler:completion]; + [self sendSkanCallError:error toCompletionHandler:completion]; } - (void)updatePostbackConversionValue:(NSInteger)conversionValue @@ -104,7 +112,7 @@ - (void)updatePostbackConversionValue:(NSInteger)conversionValue NSError *error = [self checkSKAdNetworkMethodAvailability:@"updatePostbackConversionValue:completionHandler:"]; if (error != nil) { - [self asyncSendResultError:error toCompletionHandler:completion]; + [self sendSkanCallError:error toCompletionHandler:completion]; return; } @@ -125,7 +133,7 @@ - (void)updatePostbackConversionValue:(NSInteger)fineValue NSError *error = [self checkSKAdNetworkMethodAvailability:@"updatePostbackConversionValue:coarseValue:completionHandler:"]; if (error != nil) { - [self asyncSendResultError:error toCompletionHandler:completion]; + [self sendSkanCallError:error toCompletionHandler:completion]; return; } @@ -148,7 +156,7 @@ - (void)updatePostbackConversionValue:(NSInteger)fineValue NSError *error = [self checkSKAdNetworkMethodAvailability:@"updatePostbackConversionValue:coarseValue:lockWindow:completionHandler:"]; if (error != nil) { - [self asyncSendResultError:error toCompletionHandler:completion]; + [self sendSkanCallError:error toCompletionHandler:completion]; return; } @@ -167,11 +175,10 @@ - (void)updatePostbackConversionValue:(NSInteger)fineValue #pragma mark - Adjust helper methods -- (void)registerWithConversionValue:(NSInteger)conversionValue +- (void)registerWithConversionValue:(nonnull NSNumber *)conversionValue coarseValue:(nonnull NSString *)coarseValue lockWindow:(nonnull NSNumber *)lockWindow - withCompletionHandler:(void (^_Nonnull)(NSError *_Nullable error))completion { - + withCompletionHandler:(void (^_Nonnull)(NSDictionary *_Nonnull result))completion { NSDate *skanRegisterDate = [self skadNetworkRegisterCallTimestamp]; if (skanRegisterDate != nil) { @@ -183,52 +190,77 @@ - (void)registerWithConversionValue:(NSInteger)conversionValue // Check iOS 14.0+ / NON-tvOS / SKAdNetwork framework available if (![self checkSKAdNetworkFrameworkAvailability:&error]) { [self.logger debug:error.localizedDescription]; - [self asyncSendResultError:error toCompletionHandler:completion]; + [self sendSkanCallResultWithConversionValue:conversionValue + coarseValue:coarseValue + lockWindow:lockWindow + apiInvocationError:error + toCompletionHandler:completion]; return; } if (@available(iOS 16.1, *)) { - [self updatePostbackConversionValue:conversionValue - coarseValue:[self getSKAdNetworkCoarseConversionValue:coarseValue] - lockWindow:lockWindow + NSError *error = nil; + NSString *skanCoarseValue = [self getSKAdNetworkCoarseConversionValue:coarseValue + withError:&error]; + if (skanCoarseValue == nil) { + [self.logger debug:error.localizedDescription]; + [self sendSkanCallResultWithConversionValue:conversionValue + coarseValue:coarseValue + lockWindow:lockWindow + apiInvocationError:error + toCompletionHandler:completion]; + return; + } + + [self updatePostbackConversionValue:conversionValue.integerValue + coarseValue:skanCoarseValue + lockWindow:lockWindow.boolValue withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Registration: call to SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d failed\nDescription: %@", conversionValue, coarseValue, [lockWindow boolValue], error.localizedDescription]; + [self.logger error:@"Registration: call to SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %ld, coarse value: %@, lock window: %d failed\nDescription: %@", + conversionValue.integerValue, skanCoarseValue, lockWindow.boolValue, error.localizedDescription]; } else { - [self.logger debug:@"Registration: called SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d", conversionValue, coarseValue, [lockWindow boolValue]]; + [self.logger debug:@"Registration: called SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %ld, coarse value: %@, lock window: %d", + conversionValue.integerValue, skanCoarseValue, lockWindow.boolValue]; } if (error == nil) { [self writeSKAdNetworkRegisterCallTimestamp]; - [self writeLastSKAdNetworkUpdateConversionValue:[NSNumber numberWithInteger:conversionValue] - coarseValue:[self getSKAdNetworkCoarseConversionValue:coarseValue] + [self writeLastSKAdNetworkUpdateConversionValue:conversionValue + coarseValue:skanCoarseValue lockWindow:lockWindow timestamp:[NSDate date] source:ADJSKAdNetworkCallSourceSdk]; } - if (completion != nil) { - completion(error); - } + [self sendSkanCallResultWithConversionValue:conversionValue + coarseValue:skanCoarseValue + lockWindow:lockWindow + apiInvocationError:error + toCompletionHandler:completion]; }]; } else if (@available(iOS 15.4, *)) { - [self updatePostbackConversionValue:conversionValue + [self updatePostbackConversionValue:conversionValue.integerValue withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Registration: call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription]; + [self.logger error:@"Registration: call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %ld failed\nDescription: %@", + conversionValue.integerValue, error.localizedDescription]; } else { - [self.logger debug:@"Registration: called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d", conversionValue]; + [self.logger debug:@"Registration: called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %ld", + conversionValue.integerValue]; } if (error == nil) { [self writeSKAdNetworkRegisterCallTimestamp]; - [self writeLastSKAdNetworkUpdateConversionValue:[NSNumber numberWithInteger:conversionValue] + [self writeLastSKAdNetworkUpdateConversionValue:conversionValue coarseValue:nil lockWindow:nil timestamp:[NSDate date] source:ADJSKAdNetworkCallSourceSdk]; } - if (completion != nil) { - completion(error); - } + [self sendSkanCallResultWithConversionValue:conversionValue + coarseValue:nil + lockWindow:nil + apiInvocationError:error + toCompletionHandler:completion]; }]; } else { // if (@available(iOS 14.0, *)) { already checked in 'checkSKAdNetworkFrameworkAvailability' [self registerAppForAdNetworkAttributionWithCompletionHandler:^(NSError *error) { @@ -239,128 +271,167 @@ - (void)registerWithConversionValue:(NSInteger)conversionValue } if (error == nil) { [self writeSKAdNetworkRegisterCallTimestamp]; - [self writeLastSKAdNetworkUpdateConversionValue:nil + [self writeLastSKAdNetworkUpdateConversionValue:conversionValue coarseValue:nil lockWindow:nil timestamp:[NSDate date] source:ADJSKAdNetworkCallSourceSdk]; } - if (completion != nil) { - completion(error); - } + [self sendSkanCallResultWithConversionValue:conversionValue + coarseValue:nil + lockWindow:nil + apiInvocationError:error + toCompletionHandler:completion]; }]; } } -- (void)updateConversionValue:(NSInteger)conversionValue +- (void)updateConversionValue:(nonnull NSNumber *)conversionValue coarseValue:(nullable NSString *)coarseValue lockWindow:(nullable NSNumber *)lockWindow source:(nonnull NSString *)source - withCompletionHandler:(void (^_Nullable)(NSError *_Nullable error))completion { + withCompletionHandler:(void (^_Nonnull)(NSDictionary *_Nonnull result))completion { NSError *error = nil; - // Check iOS 14.0+ / NON-tvOS / SKAdNetwork available + // Check iOS 14.0+ / NON-tvOS / SKAdNetwork framework available if (![self checkSKAdNetworkFrameworkAvailability:&error]) { [self.logger debug:error.localizedDescription]; - [self asyncSendResultError:error toCompletionHandler:completion]; + [self sendSkanCallResultWithConversionValue:conversionValue + coarseValue:coarseValue + lockWindow:lockWindow + apiInvocationError:error + toCompletionHandler:completion]; return; } + if (@available(iOS 16.1, *)) { // let's check if coarseValue and lockWindow make sense if (coarseValue != nil) { + NSError *error = nil; + NSString *skanCoarseValue = [self getSKAdNetworkCoarseConversionValue:coarseValue + withError:&error]; + if (skanCoarseValue == nil) { + [self.logger debug:error.localizedDescription]; + [self sendSkanCallResultWithConversionValue:conversionValue + coarseValue:coarseValue + lockWindow:lockWindow + apiInvocationError:error + toCompletionHandler:completion]; + return; + } + if (lockWindow != nil) { // they do both - [self updatePostbackConversionValue:conversionValue - coarseValue:[self getSKAdNetworkCoarseConversionValue:coarseValue] - lockWindow:[lockWindow boolValue] + [self updatePostbackConversionValue:conversionValue.integerValue + coarseValue:skanCoarseValue + lockWindow:lockWindow.boolValue withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d failed\nDescription: %@", conversionValue, coarseValue, [lockWindow boolValue], error.localizedDescription]; + [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %ld, coarse value: %@, lock window: %d failed\nDescription: %@", conversionValue.integerValue, skanCoarseValue, lockWindow.boolValue, error.localizedDescription]; } else { - [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d", conversionValue, coarseValue, [lockWindow boolValue]]; - [self writeLastSKAdNetworkUpdateConversionValue:[NSNumber numberWithInteger:conversionValue] - coarseValue:[self getSKAdNetworkCoarseConversionValue:coarseValue] + [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d", + conversionValue.integerValue, skanCoarseValue, lockWindow.boolValue]; + [self writeLastSKAdNetworkUpdateConversionValue:conversionValue + coarseValue:skanCoarseValue lockWindow:lockWindow timestamp:[NSDate date] source:source]; } - if (completion != nil) { - completion(error); - } + [self sendSkanCallResultWithConversionValue:conversionValue + coarseValue:skanCoarseValue + lockWindow:lockWindow + apiInvocationError:error + toCompletionHandler:completion]; }]; } else { // Only coarse value is received - [self updatePostbackConversionValue:conversionValue - coarseValue:[self getSKAdNetworkCoarseConversionValue:coarseValue] + [self updatePostbackConversionValue:conversionValue.integerValue + coarseValue:skanCoarseValue withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method with conversion value: %d, coarse value: %@ failed\nDescription: %@", conversionValue, coarseValue, error.localizedDescription]; + [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method with conversion value: %ld, coarse value: %@ failed\nDescription: %@", + conversionValue.integerValue, skanCoarseValue, error.localizedDescription]; } else { - [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method with conversion value: %d, coarse value: %@", conversionValue, coarseValue]; - [self writeLastSKAdNetworkUpdateConversionValue:[NSNumber numberWithInteger:conversionValue] - coarseValue:[self getSKAdNetworkCoarseConversionValue:coarseValue] + [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method with conversion value: %ld, coarse value: %@", + conversionValue.integerValue, skanCoarseValue]; + [self writeLastSKAdNetworkUpdateConversionValue:conversionValue + coarseValue:skanCoarseValue lockWindow:nil timestamp:[NSDate date] source:source]; } - if (completion != nil) { - completion(error); - } + [self sendSkanCallResultWithConversionValue:conversionValue + coarseValue:skanCoarseValue + lockWindow:nil + apiInvocationError:error + toCompletionHandler:completion]; }]; } } else { // they don't, let's make sure to update conversion value with a // call to updatePostbackConversionValue:completionHandler: method - [self updatePostbackConversionValue:conversionValue + [self updatePostbackConversionValue:conversionValue.integerValue withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription]; + [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %ld failed\nDescription: %@", + conversionValue.integerValue, error.localizedDescription]; } else { - [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d", conversionValue]; - [self writeLastSKAdNetworkUpdateConversionValue:[NSNumber numberWithInteger:conversionValue] + [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %ld", + conversionValue.integerValue]; + [self writeLastSKAdNetworkUpdateConversionValue:conversionValue coarseValue:nil lockWindow:nil timestamp:[NSDate date] source:source]; } - if (completion != nil) { - completion(error); - } + [self sendSkanCallResultWithConversionValue:conversionValue + coarseValue:nil + lockWindow:nil + apiInvocationError:error + toCompletionHandler:completion]; }]; } } else if (@available(iOS 15.4, *)) { - [self updatePostbackConversionValue:conversionValue + [self updatePostbackConversionValue:conversionValue.integerValue withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription]; + [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %ld failed\nDescription: %@", + conversionValue.integerValue, error.localizedDescription]; } else { - [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %d", conversionValue]; - [self writeLastSKAdNetworkUpdateConversionValue:[NSNumber numberWithInteger:conversionValue] + [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %ld", + conversionValue.integerValue]; + [self writeLastSKAdNetworkUpdateConversionValue:conversionValue coarseValue:nil lockWindow:nil timestamp:[NSDate date] source:source]; } - if (completion != nil) { - completion(error); - } + [self sendSkanCallResultWithConversionValue:conversionValue + coarseValue:nil + lockWindow:nil + apiInvocationError:error + toCompletionHandler:completion]; }]; } else { //if (@available(iOS 14.0, *)) { already checked in 'checkSKAdNetworkFrameworkAvailability' - [self updateConversionValue:conversionValue withCompletionHandler:^(NSError *error) { + [self updateConversionValue:conversionValue.integerValue withCompletionHandler:^(NSError *error) { if (error) { - [self.logger error:@"Update CV: call to SKAdNetwork's updateConversionValue: method with conversion value: %d failed\nDescription: %@", conversionValue, error.localizedDescription]; + [self.logger error:@"Update CV: call to SKAdNetwork's updateConversionValue: method with conversion value: %ld failed\nDescription: %@", + conversionValue.integerValue, error.localizedDescription]; } else { - [self.logger debug:@"Update CV: called SKAdNetwork's updateConversionValue: method with conversion value: %d", conversionValue]; - [self writeLastSKAdNetworkUpdateConversionValue:[NSNumber numberWithInteger:conversionValue] + [self.logger debug:@"Update CV: called SKAdNetwork's updateConversionValue: method with conversion value: %ld", + conversionValue.integerValue]; + [self writeLastSKAdNetworkUpdateConversionValue:conversionValue coarseValue:nil lockWindow:nil timestamp:[NSDate date] source:source]; } - if (completion != nil) { - completion(error); - } + [self sendSkanCallResultWithConversionValue:conversionValue + coarseValue:nil + lockWindow:nil + apiInvocationError:error + toCompletionHandler:completion]; }]; } } @@ -408,8 +479,8 @@ - (NSError *)checkSKAdNetworkMethodAvailability:(NSString *)methodName { return nil; } -- (void)asyncSendResultError:(NSError *_Nullable)error - toCompletionHandler:(void (^_Nullable)(NSError *_Nullable error))completion { +- (void)sendSkanCallError:(NSError *_Nullable)error + toCompletionHandler:(void (^_Nullable)(NSError *_Nullable error))completion { dispatch_async(self.internalQueue, ^{ if (completion != nil) { completion(error); @@ -417,6 +488,41 @@ - (void)asyncSendResultError:(NSError *_Nullable)error }); } +- (void)sendSkanCallResultWithConversionValue:(nonnull NSNumber *)conversionValue + coarseValue:(nullable NSString *)coarseValue + lockWindow:(nullable NSNumber *)lockWindow + apiInvocationError:(nullable NSError *)error + toCompletionHandler:(void (^_Nonnull)(NSDictionary *_Nonnull result))completion { + dispatch_async(self.internalQueue, ^{ + + // Create output result diictionary + NSMutableDictionary *result = [[NSMutableDictionary alloc] init]; + + // Create updated conversion data dictionary + NSMutableDictionary *conversionParams = [[NSMutableDictionary alloc] init]; + [conversionParams setObject:conversionValue.stringValue forKey:kSkanConversionValueCallbackKey]; + + if (coarseValue != nil) { + [conversionParams setObject:coarseValue forKey:kSkanCoarseValueCallbackKey]; + } + if (lockWindow != nil) { + NSString *val = (lockWindow.boolValue) ? @"true" : @"false"; + [conversionParams setObject:val forKey:kSkanLockWindowCallbackKey]; + } + if (error != nil) { + [conversionParams setObject:error.localizedDescription forKey:kSkanErrorCallbackKey]; + } + + // Add actual conversion params dictionary and error objects if present + [result setObject:conversionParams forKey:ADJSKAdNetworkCallActualConversionParamsKey]; + if (error != nil) { + [result setObject:error forKey:ADJSKAdNetworkCallErrorKey]; + } + + completion(result); + }); +} + - (void)writeSKAdNetworkRegisterCallTimestamp { NSDate *callTime = [NSDate date]; [ADJUserDefaults saveSkadRegisterCallTimestamp:callTime]; @@ -443,7 +549,7 @@ - (void)writeLastSKAdNetworkUpdateConversionValue:(NSNumber * _Nullable)conversi [skanUpdateData setObject:lockWindow forKey:@"lw"]; } [skanUpdateData setObject:[ADJUtil formatDate:timestamp] forKey:@"ts"]; - [skanUpdateData setObject:source forKey:@"source"]; + [skanUpdateData setObject:source forKey:@"src"]; [ADJUserDefaults saveLastSkanUpdateData:skanUpdateData]; } @@ -452,7 +558,8 @@ - (NSDictionary *)lastSKAdNetworkUpdateData { return [ADJUserDefaults getLastSkanUpdateData]; } -- (NSString *)getSKAdNetworkCoarseConversionValue:(NSString *)adjustCoarseValue { +- (NSString *)getSKAdNetworkCoarseConversionValue:(NSString *)adjustCoarseValue + withError:(NSError **)error { if (@available(iOS 16.1, *)) { if ([adjustCoarseValue isEqualToString:@"low"]) { NSString * __autoreleasing *lowValue = (NSString * __autoreleasing *)dlsym(RTLD_DEFAULT, "SKAdNetworkCoarseConversionValueLow"); @@ -464,9 +571,17 @@ - (NSString *)getSKAdNetworkCoarseConversionValue:(NSString *)adjustCoarseValue NSString * __autoreleasing *highValue = (NSString * __autoreleasing *)dlsym(RTLD_DEFAULT, "SKAdNetworkCoarseConversionValueHigh"); return *highValue; } else { + NSString *strError = [NSString stringWithFormat:@"Coarse value \"%@\" is invalid", adjustCoarseValue]; + *error = [NSError errorWithDomain:ADJSKAdNetworkDomain + code:ADJSKAdNetworkErrorInvalidCoarseValue + userInfo:@{ NSLocalizedDescriptionKey: strError }]; return nil; } } else { + NSString *strError = [NSString stringWithFormat:@"SKAdNetwork Coarse value is not available on this iOS version"]; + *error = [NSError errorWithDomain:ADJSKAdNetworkDomain + code:ADJSKAdNetworkErrorApiNotAvailable + userInfo:@{ NSLocalizedDescriptionKey: strError }]; return nil; } } From 0d627c0018be228559af24640028b81b1a64ec68 Mon Sep 17 00:00:00 2001 From: genadyb Date: Tue, 7 Jan 2025 09:53:21 +0100 Subject: [PATCH 08/15] chore: change dependency on AdjustSignature to be fixed 3.35.2 version --- Adjust.podspec | 4 ++-- Package.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Adjust.podspec b/Adjust.podspec index 8c5004a8a..694b75699 100644 --- a/Adjust.podspec +++ b/Adjust.podspec @@ -20,7 +20,7 @@ Pod::Spec.new do |s| adj.exclude_files = 'Adjust/include/**/*.h' adj.resource_bundle = {'Adjust' => ['Adjust/*.xcprivacy']} adj.header_dir = 'AdjustSdk' - adj.dependency 'AdjustSignature', '~> 3.18' + adj.dependency 'AdjustSignature', '3.35.2' end s.subspec 'AdjustWebBridge' do |awb| @@ -30,6 +30,6 @@ Pod::Spec.new do |s| awb.resource_bundle = {'Adjust' => ['Adjust/*.xcprivacy']} awb.header_dir = 'AdjustSdk' awb.ios.deployment_target = '12.0' - awb.dependency 'AdjustSignature', '~> 3.18' + awb.dependency 'AdjustSignature', '3.35.2' end end diff --git a/Package.swift b/Package.swift index 8e8b52c83..5b825027c 100644 --- a/Package.swift +++ b/Package.swift @@ -11,7 +11,7 @@ let package = Package( dependencies: [ .package( url: "https://github.com/adjust/adjust_signature_sdk.git", - .upToNextMajor(from: "3.18.0") + .exact("3.35.2") ) ], targets: [ From 38aa0a5c2fbdb3d7f16cf05cc6a47d64b987cb90 Mon Sep 17 00:00:00 2001 From: genadyb Date: Tue, 7 Jan 2025 09:59:15 +0100 Subject: [PATCH 09/15] feat: taking idfv usage out of COPPA limitations --- Adjust/Internal/ADJPackageBuilder.m | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Adjust/Internal/ADJPackageBuilder.m b/Adjust/Internal/ADJPackageBuilder.m index 269a1893a..43eeb16fa 100644 --- a/Adjust/Internal/ADJPackageBuilder.m +++ b/Adjust/Internal/ADJPackageBuilder.m @@ -1001,10 +1001,6 @@ - (NSMutableDictionary *)getPurchaseVerificationParameters { - (void)addIdfvIfPossibleToParameters:(NSMutableDictionary *)parameters { id logger = [ADJAdjustFactory logger]; - if (self.adjustConfig.isCoppaComplianceEnabled) { - [logger info:@"Cannot read IDFV with COPPA enabled"]; - return; - } if (self.adjustConfig.isIdfvReadingEnabled == NO) { return; } From 15cd8b95f135666bd855bffe69f312475b1af3de Mon Sep 17 00:00:00 2001 From: genadyb Date: Tue, 7 Jan 2025 10:24:58 +0100 Subject: [PATCH 10/15] chore: aligning keys sent to BE with client's SKAN callback keys --- Adjust/Internal/ADJSKAdNetwork.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Adjust/Internal/ADJSKAdNetwork.m b/Adjust/Internal/ADJSKAdNetwork.m index f17b80756..2058ec3a6 100644 --- a/Adjust/Internal/ADJSKAdNetwork.m +++ b/Adjust/Internal/ADJSKAdNetwork.m @@ -540,16 +540,16 @@ - (void)writeLastSKAdNetworkUpdateConversionValue:(NSNumber * _Nullable)conversi NSMutableDictionary *skanUpdateData = [NSMutableDictionary dictionary]; if (conversionValue != nil) { - [skanUpdateData setObject:conversionValue forKey:@"conv"]; + [skanUpdateData setObject:conversionValue forKey:kSkanConversionValueCallbackKey]; } if (coarseValue != nil) { - [skanUpdateData setObject:coarseValue forKey:@"coav"]; + [skanUpdateData setObject:coarseValue forKey:kSkanCoarseValueCallbackKey]; } if (lockWindow != nil) { - [skanUpdateData setObject:lockWindow forKey:@"lw"]; + [skanUpdateData setObject:lockWindow forKey:kSkanLockWindowCallbackKey]; } - [skanUpdateData setObject:[ADJUtil formatDate:timestamp] forKey:@"ts"]; - [skanUpdateData setObject:source forKey:@"src"]; + [skanUpdateData setObject:[ADJUtil formatDate:timestamp] forKey:@"timestamp"]; + [skanUpdateData setObject:source forKey:@"source"]; [ADJUserDefaults saveLastSkanUpdateData:skanUpdateData]; } From f08a3f9566380d4406ec015d265516b953e216cc Mon Sep 17 00:00:00 2001 From: uerceg Date: Fri, 10 Jan 2025 13:37:25 +0100 Subject: [PATCH 11/15] refac: clean up a bit --- Adjust/Adjust.m | 5 +- Adjust/Internal/ADJActivityHandler.m | 4 +- Adjust/Internal/ADJPackageBuilder.m | 2 +- Adjust/Internal/ADJSKAdNetwork.h | 13 +- Adjust/Internal/ADJSKAdNetwork.m | 466 +++++++++++++-------------- 5 files changed, 242 insertions(+), 248 deletions(-) diff --git a/Adjust/Adjust.m b/Adjust/Adjust.m index c38134ca8..01e77c5ed 100644 --- a/Adjust/Adjust.m +++ b/Adjust/Adjust.m @@ -625,17 +625,16 @@ - (void)updateSkanConversionValue:(NSInteger)conversionValue coarseValue:(nullable NSString *)coarseValue lockWindow:(nullable NSNumber *)lockWindow withCompletionHandler:(void (^_Nullable)(NSError *_Nullable error))completion { - [[ADJSKAdNetwork getInstance] updateConversionValue:[NSNumber numberWithInteger:conversionValue] coarseValue:coarseValue lockWindow:lockWindow - source:ADJSKAdNetworkCallSourceClient + source:ADJSkanSourceClient withCompletionHandler:^(NSDictionary * _Nonnull result) { if ([self checkActivityHandler]) { [self.activityHandler invokeClientSkanUpdateCallbackWithResult:result]; } if (completion != nil) { - completion([result objectForKey:ADJSKAdNetworkCallErrorKey]); + completion([result objectForKey:ADJSkanClientCompletionErrorKey]); } }]; } diff --git a/Adjust/Internal/ADJActivityHandler.m b/Adjust/Internal/ADJActivityHandler.m index 2b386fd58..c81bc2a09 100644 --- a/Adjust/Internal/ADJActivityHandler.m +++ b/Adjust/Internal/ADJActivityHandler.m @@ -2768,7 +2768,7 @@ - (void)checkConversionValue:(ADJResponseData *)responseData { [[ADJSKAdNetwork getInstance] updateConversionValue:conversionValue coarseValue:coarseValue lockWindow:lockWindow - source:ADJSKAdNetworkCallSourceBackend + source:ADJSkanSourceBackend withCompletionHandler:^(NSDictionary * _Nonnull result) { [self invokeClientSkanUpdateCallbackWithResult:result]; }]; @@ -2847,7 +2847,7 @@ - (BOOL)shouldDisableThirdPartySharingWhenCoppaEnabled:(ADJActivityHandler *)sel } - (void)invokeClientSkanUpdateCallbackWithResult:(NSDictionary * _Nonnull)result { - NSDictionary *conversionParams = [result objectForKey:ADJSKAdNetworkCallActualConversionParamsKey]; + NSDictionary *conversionParams = [result objectForKey:ADJSkanClientCallbackParamsKey]; // Ping the callback method if implemented if ([self.adjustDelegate respondsToSelector:@selector(adjustSkanUpdatedWithConversionData:)]) { [self.logger debug:@"Launching delegate's method adjustSkanUpdatedWithConversionData:"]; diff --git a/Adjust/Internal/ADJPackageBuilder.m b/Adjust/Internal/ADJPackageBuilder.m index 43eeb16fa..e389a1e3a 100644 --- a/Adjust/Internal/ADJPackageBuilder.m +++ b/Adjust/Internal/ADJPackageBuilder.m @@ -1040,7 +1040,7 @@ - (void)injectFeatureFlagsWithParameters:(NSMutableDictionary *)parameters { } - (void)injectLastSkanUpdateWithParameters:(NSMutableDictionary *)parameters { - NSDictionary *lastSkanUpdateData = [[ADJSKAdNetwork getInstance] lastSKAdNetworkUpdateData]; + NSDictionary *lastSkanUpdateData = [[ADJSKAdNetwork getInstance] lastSkanUpdateData]; if (lastSkanUpdateData != nil) { [ADJPackageBuilder parameters:parameters setDictionaryJson:lastSkanUpdateData forKey:@"last_skan_update"]; } diff --git a/Adjust/Internal/ADJSKAdNetwork.h b/Adjust/Internal/ADJSKAdNetwork.h index fedd1b6af..a1806dce1 100644 --- a/Adjust/Internal/ADJSKAdNetwork.h +++ b/Adjust/Internal/ADJSKAdNetwork.h @@ -10,11 +10,11 @@ @interface ADJSKAdNetwork : NSObject -extern NSString * _Nonnull const ADJSKAdNetworkCallSourceSdk; -extern NSString * _Nonnull const ADJSKAdNetworkCallSourceBackend; -extern NSString * _Nonnull const ADJSKAdNetworkCallSourceClient; -extern NSString * _Nonnull const ADJSKAdNetworkCallActualConversionParamsKey; -extern NSString * _Nonnull const ADJSKAdNetworkCallErrorKey; +extern NSString * _Nonnull const ADJSkanSourceSdk; +extern NSString * _Nonnull const ADJSkanSourceBackend; +extern NSString * _Nonnull const ADJSkanSourceClient; +extern NSString * _Nonnull const ADJSkanClientCallbackParamsKey; +extern NSString * _Nonnull const ADJSkanClientCompletionErrorKey; + (nullable instancetype)getInstance; @@ -29,5 +29,6 @@ extern NSString * _Nonnull const ADJSKAdNetworkCallErrorKey; source:(nonnull NSString *)source withCompletionHandler:(void (^_Nonnull)(NSDictionary *_Nonnull result))completion; -- (NSDictionary * _Nullable)lastSKAdNetworkUpdateData; +- (NSDictionary * _Nullable)lastSkanUpdateData; + @end diff --git a/Adjust/Internal/ADJSKAdNetwork.m b/Adjust/Internal/ADJSKAdNetwork.m index 2058ec3a6..94bcaa6be 100644 --- a/Adjust/Internal/ADJSKAdNetwork.m +++ b/Adjust/Internal/ADJSKAdNetwork.m @@ -14,30 +14,34 @@ #import "ADJLogger.h" #import "ADJUtil.h" -static const char * const kInternalQueueName = "io.adjust.SKAdNetworkQueue"; -static NSString * const ADJSKAdNetworkDomain = @"com.adjust.sdk.skadnetwork"; -typedef NS_ENUM(NSInteger, ADJSKAdNetworkError) { - ADJSKAdNetworkErrorOsNotSupported = -100, - ADJSKAdNetworkErrorFrameworkNotFound = -101, - ADJSKAdNetworkErrorApiNotAvailable = -102, - ADJSKAdNetworkErrorInvalidCoarseValue = -103 +static const char * const kInternalQueueName = "io.adjust.SkanQueue"; +static NSString * const ADJSkanDomain = @"com.adjust.sdk.skadnetwork"; + +typedef NS_ENUM(NSInteger, ADJSkanError) { + ADJSkanErrorOsNotSupported = -100, + ADJSkanErrorOsVersionNotSupported = -101, + ADJSkanErrorFrameworkNotFound = -102, + ADJSkanErrorApiNotAvailable = -103, + ADJSkanErrorInvalidCoarseValue = -104 }; // Externally Available constants -NSString * const ADJSKAdNetworkCallSourceSdk = @"sdk"; -NSString * const ADJSKAdNetworkCallSourceBackend = @"backend"; -NSString * const ADJSKAdNetworkCallSourceClient = @"client"; -NSString * const ADJSKAdNetworkCallActualConversionParamsKey = @"skan_call_actual_conversion_params"; -NSString * const ADJSKAdNetworkCallErrorKey = @"skan_call_error"; +NSString * const ADJSkanSourceSdk = @"sdk"; +NSString * const ADJSkanSourceBackend = @"backend"; +NSString * const ADJSkanSourceClient = @"client"; +NSString * const ADJSkanClientCallbackParamsKey = @"skan_client_callback_params"; +NSString * const ADJSkanClientCompletionErrorKey = @"skan_client_completion_error"; -static NSString * const kSkanConversionValueCallbackKey = @"conversion_value"; -static NSString * const kSkanCoarseValueCallbackKey = @"coarse_value"; -static NSString * const kSkanLockWindowCallbackKey = @"lock_window"; -static NSString * const kSkanErrorCallbackKey = @"error"; +static NSString * const kSkanCallbackConversionValueKey = @"conversion_value"; +static NSString * const kSkanCallbackCoarseValueKey = @"coarse_value"; +static NSString * const kSkanCallbackLockWindowKey = @"lock_window"; +static NSString * const kSkanCallbackErrorKey = @"error"; @interface ADJSKAdNetwork() + @property (nonatomic, weak) id logger; @property (nonatomic, strong) dispatch_queue_t internalQueue; + @end @implementation ADJSKAdNetwork @@ -65,122 +69,13 @@ - (instancetype)init { return self; } -#pragma mark - SKAdNetwork API - -- (void)registerAppForAdNetworkAttributionWithCompletionHandler:(void (^)(NSError *error))completion { - - NSError *error = [self checkSKAdNetworkMethodAvailability:@"registerAppForAdNetworkAttribution"]; - if (error != nil) { - [self sendSkanCallError:error toCompletionHandler:completion]; - return; - } - - Class class = NSClassFromString(@"SKAdNetwork"); - SEL selector = NSSelectorFromString(@"registerAppForAdNetworkAttribution"); - NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; - [invocation setSelector:selector]; - [invocation setTarget:class]; - [invocation invoke]; - [self.logger verbose:@"Call to SKAdNetwork's registerAppForAdNetworkAttribution method made"]; - [self sendSkanCallError:error toCompletionHandler:completion]; -} - -- (void)updateConversionValue:(NSInteger)conversionValue - withCompletionHandler:(void (^)(NSError *error))completion { - - NSError *error = [self checkSKAdNetworkMethodAvailability:@"updateConversionValue:"]; - if (error != nil) { - [self sendSkanCallError:error toCompletionHandler:completion]; - return; - } - - Class class = NSClassFromString(@"SKAdNetwork"); - SEL selector = NSSelectorFromString(@"updateConversionValue:"); - NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; - [invocation setSelector:selector]; - [invocation setTarget:class]; - [invocation setArgument:&conversionValue atIndex:2]; - [invocation invoke]; - [self.logger verbose:@"Call to SKAdNetwork's updateConversionValue: method made with value %d", conversionValue]; - [self sendSkanCallError:error toCompletionHandler:completion]; -} - -- (void)updatePostbackConversionValue:(NSInteger)conversionValue - withCompletionHandler:(void (^)(NSError *error))completion { - - NSError *error = [self checkSKAdNetworkMethodAvailability:@"updatePostbackConversionValue:completionHandler:"]; - if (error != nil) { - [self sendSkanCallError:error toCompletionHandler:completion]; - return; - } - - Class class = NSClassFromString(@"SKAdNetwork"); - SEL selector = NSSelectorFromString(@"updatePostbackConversionValue:completionHandler:"); - NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; - [invocation setSelector:selector]; - [invocation setTarget:class]; - [invocation setArgument:&conversionValue atIndex:2]; - [invocation setArgument:&completion atIndex:3]; - [invocation invoke]; -} - -- (void)updatePostbackConversionValue:(NSInteger)fineValue - coarseValue:(NSString *)coarseValue - withCompletionHandler:(void (^)(NSError *error))completion { - - NSError *error = [self checkSKAdNetworkMethodAvailability:@"updatePostbackConversionValue:coarseValue:completionHandler:"]; - if (error != nil) { - [self sendSkanCallError:error toCompletionHandler:completion]; - return; - } - - Class class = NSClassFromString(@"SKAdNetwork"); - SEL selector = NSSelectorFromString(@"updatePostbackConversionValue:coarseValue:completionHandler:"); - NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; - [invocation setSelector:selector]; - [invocation setTarget:class]; - [invocation setArgument:&fineValue atIndex:2]; - [invocation setArgument:&coarseValue atIndex:3]; - [invocation setArgument:&completion atIndex:4]; - [invocation invoke]; -} - -- (void)updatePostbackConversionValue:(NSInteger)fineValue - coarseValue:(NSString *)coarseValue - lockWindow:(BOOL)lockWindow - withCompletionHandler:(void (^)(NSError *error))completion { - - NSError *error = [self checkSKAdNetworkMethodAvailability:@"updatePostbackConversionValue:coarseValue:lockWindow:completionHandler:"]; - if (error != nil) { - [self sendSkanCallError:error toCompletionHandler:completion]; - return; - } - - Class class = NSClassFromString(@"SKAdNetwork"); - SEL selector = NSSelectorFromString(@"updatePostbackConversionValue:coarseValue:lockWindow:completionHandler:"); - NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; - [invocation setSelector:selector]; - [invocation setTarget:class]; - [invocation setArgument:&fineValue atIndex:2]; - [invocation setArgument:&coarseValue atIndex:3]; - [invocation setArgument:&lockWindow atIndex:4]; - [invocation setArgument:&completion atIndex:5]; - [invocation invoke]; -} - -#pragma mark - Adjust helper methods +#pragma mark - Public API - (void)registerWithConversionValue:(nonnull NSNumber *)conversionValue coarseValue:(nonnull NSString *)coarseValue lockWindow:(nonnull NSNumber *)lockWindow withCompletionHandler:(void (^_Nonnull)(NSDictionary *_Nonnull result))completion { - - NSDate *skanRegisterDate = [self skadNetworkRegisterCallTimestamp]; + NSDate *skanRegisterDate = [self skanRegisterCallTimestamp]; if (skanRegisterDate != nil) { [self.logger debug:@"Call to register app with SKAdNetwork already made for this install"]; return; @@ -188,7 +83,7 @@ - (void)registerWithConversionValue:(nonnull NSNumber *)conversionValue NSError *error = nil; // Check iOS 14.0+ / NON-tvOS / SKAdNetwork framework available - if (![self checkSKAdNetworkFrameworkAvailability:&error]) { + if (![self checkSkanFrameworkAvailability:&error]) { [self.logger debug:error.localizedDescription]; [self sendSkanCallResultWithConversionValue:conversionValue coarseValue:coarseValue @@ -200,8 +95,8 @@ - (void)registerWithConversionValue:(nonnull NSNumber *)conversionValue if (@available(iOS 16.1, *)) { NSError *error = nil; - NSString *skanCoarseValue = [self getSKAdNetworkCoarseConversionValue:coarseValue - withError:&error]; + NSString *skanCoarseValue = [self getSkanCoarseConversionValue:coarseValue + withError:&error]; if (skanCoarseValue == nil) { [self.logger debug:error.localizedDescription]; [self sendSkanCallResultWithConversionValue:conversionValue @@ -217,20 +112,20 @@ - (void)registerWithConversionValue:(nonnull NSNumber *)conversionValue lockWindow:lockWindow.boolValue withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Registration: call to SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %ld, coarse value: %@, lock window: %d failed\nDescription: %@", + [self.logger error:@"Call to SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: (registration) method with { conversion value: %ld, coarse value: %@, lock window: %d } failed. Error: %@", conversionValue.integerValue, skanCoarseValue, lockWindow.boolValue, error.localizedDescription]; } else { - [self.logger debug:@"Registration: called SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %ld, coarse value: %@, lock window: %d", + [self.logger debug:@"Called SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: (registration) method with { conversion value: %ld, coarse value: %@, lock window: %d }", conversionValue.integerValue, skanCoarseValue, lockWindow.boolValue]; } if (error == nil) { - [self writeSKAdNetworkRegisterCallTimestamp]; - [self writeLastSKAdNetworkUpdateConversionValue:conversionValue - coarseValue:skanCoarseValue - lockWindow:lockWindow - timestamp:[NSDate date] - source:ADJSKAdNetworkCallSourceSdk]; + [self writeskanRegisterCallTimestamp]; + [self writeLastSkanUpdateConversionValue:conversionValue + coarseValue:skanCoarseValue + lockWindow:lockWindow + timestamp:[NSDate date] + source:ADJSkanSourceSdk]; } [self sendSkanCallResultWithConversionValue:conversionValue coarseValue:skanCoarseValue @@ -242,19 +137,19 @@ - (void)registerWithConversionValue:(nonnull NSNumber *)conversionValue [self updatePostbackConversionValue:conversionValue.integerValue withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Registration: call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %ld failed\nDescription: %@", + [self.logger error:@"Call to SKAdNetwork's updatePostbackConversionValue:completionHandler: (registration) method with { conversion value: %ld } failed. Error: %@", conversionValue.integerValue, error.localizedDescription]; } else { - [self.logger debug:@"Registration: called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %ld", + [self.logger debug:@"Called SKAdNetwork's updatePostbackConversionValue:completionHandler: (registration) method with { conversion value: %ld }", conversionValue.integerValue]; } if (error == nil) { - [self writeSKAdNetworkRegisterCallTimestamp]; - [self writeLastSKAdNetworkUpdateConversionValue:conversionValue - coarseValue:nil - lockWindow:nil - timestamp:[NSDate date] - source:ADJSKAdNetworkCallSourceSdk]; + [self writeskanRegisterCallTimestamp]; + [self writeLastSkanUpdateConversionValue:conversionValue + coarseValue:nil + lockWindow:nil + timestamp:[NSDate date] + source:ADJSkanSourceSdk]; } [self sendSkanCallResultWithConversionValue:conversionValue coarseValue:nil @@ -262,20 +157,20 @@ - (void)registerWithConversionValue:(nonnull NSNumber *)conversionValue apiInvocationError:error toCompletionHandler:completion]; }]; - } else { // if (@available(iOS 14.0, *)) { already checked in 'checkSKAdNetworkFrameworkAvailability' + } else { // if (@available(iOS 14.0, *)) { already checked in 'checkSkanFrameworkAvailability' [self registerAppForAdNetworkAttributionWithCompletionHandler:^(NSError *error) { if (error) { - [self.logger error:@"Registration: call to SKAdNetwork's registerAppForAdNetworkAttribution method failed\nDescription: %@", error.localizedDescription]; + [self.logger error:@"Call to SKAdNetwork's registerAppForAdNetworkAttribution method failed. Error: %@", error.localizedDescription]; } else { - [self.logger debug:@"Registration: called SKAdNetwork's registerAppForAdNetworkAttribution method"]; + [self.logger debug:@"Called SKAdNetwork's registerAppForAdNetworkAttribution method"]; } if (error == nil) { - [self writeSKAdNetworkRegisterCallTimestamp]; - [self writeLastSKAdNetworkUpdateConversionValue:conversionValue - coarseValue:nil - lockWindow:nil - timestamp:[NSDate date] - source:ADJSKAdNetworkCallSourceSdk]; + [self writeskanRegisterCallTimestamp]; + [self writeLastSkanUpdateConversionValue:conversionValue + coarseValue:nil + lockWindow:nil + timestamp:[NSDate date] + source:ADJSkanSourceSdk]; } [self sendSkanCallResultWithConversionValue:conversionValue coarseValue:nil @@ -291,10 +186,9 @@ - (void)updateConversionValue:(nonnull NSNumber *)conversionValue lockWindow:(nullable NSNumber *)lockWindow source:(nonnull NSString *)source withCompletionHandler:(void (^_Nonnull)(NSDictionary *_Nonnull result))completion { - NSError *error = nil; // Check iOS 14.0+ / NON-tvOS / SKAdNetwork framework available - if (![self checkSKAdNetworkFrameworkAvailability:&error]) { + if (![self checkSkanFrameworkAvailability:&error]) { [self.logger debug:error.localizedDescription]; [self sendSkanCallResultWithConversionValue:conversionValue coarseValue:coarseValue @@ -304,13 +198,12 @@ - (void)updateConversionValue:(nonnull NSNumber *)conversionValue return; } - if (@available(iOS 16.1, *)) { // let's check if coarseValue and lockWindow make sense if (coarseValue != nil) { NSError *error = nil; - NSString *skanCoarseValue = [self getSKAdNetworkCoarseConversionValue:coarseValue - withError:&error]; + NSString *skanCoarseValue = [self getSkanCoarseConversionValue:coarseValue + withError:&error]; if (skanCoarseValue == nil) { [self.logger debug:error.localizedDescription]; [self sendSkanCallResultWithConversionValue:conversionValue @@ -328,15 +221,15 @@ - (void)updateConversionValue:(nonnull NSNumber *)conversionValue lockWindow:lockWindow.boolValue withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %ld, coarse value: %@, lock window: %d failed\nDescription: %@", conversionValue.integerValue, skanCoarseValue, lockWindow.boolValue, error.localizedDescription]; + [self.logger error:@"Call to SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with { conversion value: %ld, coarse value: %@, lock window: %d } failed. Error: %@", conversionValue.integerValue, skanCoarseValue, lockWindow.boolValue, error.localizedDescription]; } else { - [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with conversion value: %d, coarse value: %@, lock window: %d", + [self.logger debug:@"Called SKAdNetwork's updatePostbackConversionValue:coarseValue:lockWindow:completionHandler: method with { conversion value: %d, coarse value: %@, lock window: %d }", conversionValue.integerValue, skanCoarseValue, lockWindow.boolValue]; - [self writeLastSKAdNetworkUpdateConversionValue:conversionValue - coarseValue:skanCoarseValue - lockWindow:lockWindow - timestamp:[NSDate date] - source:source]; + [self writeLastSkanUpdateConversionValue:conversionValue + coarseValue:skanCoarseValue + lockWindow:lockWindow + timestamp:[NSDate date] + source:source]; } [self sendSkanCallResultWithConversionValue:conversionValue coarseValue:skanCoarseValue @@ -350,16 +243,16 @@ - (void)updateConversionValue:(nonnull NSNumber *)conversionValue coarseValue:skanCoarseValue withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method with conversion value: %ld, coarse value: %@ failed\nDescription: %@", + [self.logger error:@"Call to SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method with { conversion value: %ld, coarse value: %@ } failed. Error: %@", conversionValue.integerValue, skanCoarseValue, error.localizedDescription]; } else { - [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method with conversion value: %ld, coarse value: %@", + [self.logger debug:@"Called SKAdNetwork's updatePostbackConversionValue:coarseValue:completionHandler: method with { conversion value: %ld, coarse value: %@ }", conversionValue.integerValue, skanCoarseValue]; - [self writeLastSKAdNetworkUpdateConversionValue:conversionValue - coarseValue:skanCoarseValue - lockWindow:nil - timestamp:[NSDate date] - source:source]; + [self writeLastSkanUpdateConversionValue:conversionValue + coarseValue:skanCoarseValue + lockWindow:nil + timestamp:[NSDate date] + source:source]; } [self sendSkanCallResultWithConversionValue:conversionValue coarseValue:skanCoarseValue @@ -374,16 +267,16 @@ - (void)updateConversionValue:(nonnull NSNumber *)conversionValue [self updatePostbackConversionValue:conversionValue.integerValue withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %ld failed\nDescription: %@", + [self.logger error:@"Call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with { conversion value: %ld } failed. Error: %@", conversionValue.integerValue, error.localizedDescription]; } else { - [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %ld", + [self.logger debug:@"Called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with { conversion value: %ld }", conversionValue.integerValue]; - [self writeLastSKAdNetworkUpdateConversionValue:conversionValue - coarseValue:nil - lockWindow:nil - timestamp:[NSDate date] - source:source]; + [self writeLastSkanUpdateConversionValue:conversionValue + coarseValue:nil + lockWindow:nil + timestamp:[NSDate date] + source:source]; } [self sendSkanCallResultWithConversionValue:conversionValue coarseValue:nil @@ -396,16 +289,16 @@ - (void)updateConversionValue:(nonnull NSNumber *)conversionValue [self updatePostbackConversionValue:conversionValue.integerValue withCompletionHandler:^(NSError * _Nullable error) { if (error) { - [self.logger error:@"Update CV: call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %ld failed\nDescription: %@", + [self.logger error:@"Call to SKAdNetwork's updatePostbackConversionValue:completionHandler: method with { conversion value: %ld } failed. Error: %@", conversionValue.integerValue, error.localizedDescription]; } else { - [self.logger debug:@"Update CV: called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with conversion value: %ld", + [self.logger debug:@"Called SKAdNetwork's updatePostbackConversionValue:completionHandler: method with { conversion value: %ld }", conversionValue.integerValue]; - [self writeLastSKAdNetworkUpdateConversionValue:conversionValue - coarseValue:nil - lockWindow:nil - timestamp:[NSDate date] - source:source]; + [self writeLastSkanUpdateConversionValue:conversionValue + coarseValue:nil + lockWindow:nil + timestamp:[NSDate date] + source:source]; } [self sendSkanCallResultWithConversionValue:conversionValue coarseValue:nil @@ -413,19 +306,19 @@ - (void)updateConversionValue:(nonnull NSNumber *)conversionValue apiInvocationError:error toCompletionHandler:completion]; }]; - } else { //if (@available(iOS 14.0, *)) { already checked in 'checkSKAdNetworkFrameworkAvailability' + } else { //if (@available(iOS 14.0, *)) { already checked in 'checkSkanFrameworkAvailability' [self updateConversionValue:conversionValue.integerValue withCompletionHandler:^(NSError *error) { if (error) { - [self.logger error:@"Update CV: call to SKAdNetwork's updateConversionValue: method with conversion value: %ld failed\nDescription: %@", + [self.logger error:@"Call to SKAdNetwork's updateConversionValue: method with { conversion value: %ld } failed. Error: %@", conversionValue.integerValue, error.localizedDescription]; } else { - [self.logger debug:@"Update CV: called SKAdNetwork's updateConversionValue: method with conversion value: %ld", + [self.logger debug:@"Called SKAdNetwork's updateConversionValue: method with { conversion value: %ld }", conversionValue.integerValue]; - [self writeLastSKAdNetworkUpdateConversionValue:conversionValue - coarseValue:nil - lockWindow:nil - timestamp:[NSDate date] - source:source]; + [self writeLastSkanUpdateConversionValue:conversionValue + coarseValue:nil + lockWindow:nil + timestamp:[NSDate date] + source:source]; } [self sendSkanCallResultWithConversionValue:conversionValue coarseValue:nil @@ -436,43 +329,150 @@ - (void)updateConversionValue:(nonnull NSNumber *)conversionValue } } +- (NSDictionary *)lastSkanUpdateData { + return [ADJUserDefaults getLastSkanUpdateData]; +} + +#pragma mark - SKAdNetwork API + +- (void)registerAppForAdNetworkAttributionWithCompletionHandler:(void (^)(NSError *error))completion { + NSError *error = [self checkSkanMethodAvailability:@"registerAppForAdNetworkAttribution"]; + if (error != nil) { + [self sendSkanCallError:error toCompletionHandler:completion]; + return; + } + + Class class = NSClassFromString(@"SKAdNetwork"); + SEL selector = NSSelectorFromString(@"registerAppForAdNetworkAttribution"); + NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + [invocation setSelector:selector]; + [invocation setTarget:class]; + [invocation invoke]; + [self.logger verbose:@"Call to SKAdNetwork's registerAppForAdNetworkAttribution method made"]; + [self sendSkanCallError:error toCompletionHandler:completion]; +} + +- (void)updateConversionValue:(NSInteger)conversionValue + withCompletionHandler:(void (^)(NSError *error))completion { + NSError *error = [self checkSkanMethodAvailability:@"updateConversionValue:"]; + if (error != nil) { + [self sendSkanCallError:error toCompletionHandler:completion]; + return; + } + + Class class = NSClassFromString(@"SKAdNetwork"); + SEL selector = NSSelectorFromString(@"updateConversionValue:"); + NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + [invocation setSelector:selector]; + [invocation setTarget:class]; + [invocation setArgument:&conversionValue atIndex:2]; + [invocation invoke]; + [self.logger verbose:@"Call to SKAdNetwork's updateConversionValue: method made with value %d", conversionValue]; + [self sendSkanCallError:error toCompletionHandler:completion]; +} + +- (void)updatePostbackConversionValue:(NSInteger)conversionValue + withCompletionHandler:(void (^)(NSError *error))completion { + NSError *error = [self checkSkanMethodAvailability:@"updatePostbackConversionValue:completionHandler:"]; + if (error != nil) { + [self sendSkanCallError:error toCompletionHandler:completion]; + return; + } + + Class class = NSClassFromString(@"SKAdNetwork"); + SEL selector = NSSelectorFromString(@"updatePostbackConversionValue:completionHandler:"); + NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + [invocation setSelector:selector]; + [invocation setTarget:class]; + [invocation setArgument:&conversionValue atIndex:2]; + [invocation setArgument:&completion atIndex:3]; + [invocation invoke]; +} + +- (void)updatePostbackConversionValue:(NSInteger)fineValue + coarseValue:(NSString *)coarseValue + withCompletionHandler:(void (^)(NSError *error))completion { + NSError *error = [self checkSkanMethodAvailability:@"updatePostbackConversionValue:coarseValue:completionHandler:"]; + if (error != nil) { + [self sendSkanCallError:error toCompletionHandler:completion]; + return; + } + + Class class = NSClassFromString(@"SKAdNetwork"); + SEL selector = NSSelectorFromString(@"updatePostbackConversionValue:coarseValue:completionHandler:"); + NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + [invocation setSelector:selector]; + [invocation setTarget:class]; + [invocation setArgument:&fineValue atIndex:2]; + [invocation setArgument:&coarseValue atIndex:3]; + [invocation setArgument:&completion atIndex:4]; + [invocation invoke]; +} + +- (void)updatePostbackConversionValue:(NSInteger)fineValue + coarseValue:(NSString *)coarseValue + lockWindow:(BOOL)lockWindow + withCompletionHandler:(void (^)(NSError *error))completion { + NSError *error = [self checkSkanMethodAvailability:@"updatePostbackConversionValue:coarseValue:lockWindow:completionHandler:"]; + if (error != nil) { + [self sendSkanCallError:error toCompletionHandler:completion]; + return; + } + + Class class = NSClassFromString(@"SKAdNetwork"); + SEL selector = NSSelectorFromString(@"updatePostbackConversionValue:coarseValue:lockWindow:completionHandler:"); + NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; + [invocation setSelector:selector]; + [invocation setTarget:class]; + [invocation setArgument:&fineValue atIndex:2]; + [invocation setArgument:&coarseValue atIndex:3]; + [invocation setArgument:&lockWindow atIndex:4]; + [invocation setArgument:&completion atIndex:5]; + [invocation invoke]; +} + #pragma mark - Private -- (BOOL)checkSKAdNetworkFrameworkAvailability:(NSError **)error { +- (BOOL)checkSkanFrameworkAvailability:(NSError **)error { #if !(TARGET_OS_TV) if (@available(iOS 14.0, *)) { if (NSClassFromString(@"SKAdNetwork") == nil) { NSString *strError = @"SKAdNetwork class not found. Check StoreKit.framework availability."; - *error = [NSError errorWithDomain:ADJSKAdNetworkDomain - code:ADJSKAdNetworkErrorFrameworkNotFound + *error = [NSError errorWithDomain:ADJSkanDomain + code:ADJSkanErrorFrameworkNotFound userInfo:@{ NSLocalizedDescriptionKey: strError }]; return NO; } return YES; } else { NSString *strError = @"SKAdNetwork API not available on this iOS version"; - *error = [NSError errorWithDomain:ADJSKAdNetworkDomain - code:ADJSKAdNetworkErrorOsNotSupported + *error = [NSError errorWithDomain:ADJSkanDomain + code:ADJSkanErrorOsVersionNotSupported userInfo:@{ NSLocalizedDescriptionKey: strError }]; return NO; } #else NSString *strError = @"SKAdNetwork is not supported on tvOS"; - *error = [NSError errorWithDomain:ADJSKAdNetworkDomain - code:ADJSKAdNetworkErrorOsNotSupported + *error = [NSError errorWithDomain:ADJSkanDomain + code:ADJSkanErrorOsNotSupported userInfo:@{ NSLocalizedDescriptionKey: strError }]; return NO; #endif } -- (NSError *)checkSKAdNetworkMethodAvailability:(NSString *)methodName { +- (NSError *)checkSkanMethodAvailability:(NSString *)methodName { Class class = NSClassFromString(@"SKAdNetwork"); SEL selector = NSSelectorFromString(methodName); if ([class respondsToSelector:selector] == NO) { NSString *strError = [NSString stringWithFormat:@"Implementation of %@ not found in SKAdNetwork", methodName]; - NSError *error = [NSError errorWithDomain:ADJSKAdNetworkDomain - code:ADJSKAdNetworkErrorApiNotAvailable + NSError *error = [NSError errorWithDomain:ADJSkanDomain + code:ADJSkanErrorApiNotAvailable userInfo:@{ NSLocalizedDescriptionKey: strError }]; return error; } @@ -494,59 +494,57 @@ - (void)sendSkanCallResultWithConversionValue:(nonnull NSNumber *)conversionValu apiInvocationError:(nullable NSError *)error toCompletionHandler:(void (^_Nonnull)(NSDictionary *_Nonnull result))completion { dispatch_async(self.internalQueue, ^{ - // Create output result diictionary NSMutableDictionary *result = [[NSMutableDictionary alloc] init]; // Create updated conversion data dictionary NSMutableDictionary *conversionParams = [[NSMutableDictionary alloc] init]; - [conversionParams setObject:conversionValue.stringValue forKey:kSkanConversionValueCallbackKey]; + [conversionParams setObject:conversionValue.stringValue forKey:kSkanCallbackConversionValueKey]; if (coarseValue != nil) { - [conversionParams setObject:coarseValue forKey:kSkanCoarseValueCallbackKey]; + [conversionParams setObject:coarseValue forKey:kSkanCallbackCoarseValueKey]; } if (lockWindow != nil) { NSString *val = (lockWindow.boolValue) ? @"true" : @"false"; - [conversionParams setObject:val forKey:kSkanLockWindowCallbackKey]; + [conversionParams setObject:val forKey:kSkanCallbackLockWindowKey]; } if (error != nil) { - [conversionParams setObject:error.localizedDescription forKey:kSkanErrorCallbackKey]; + [conversionParams setObject:error.localizedDescription forKey:kSkanCallbackErrorKey]; } - // Add actual conversion params dictionary and error objects if present - [result setObject:conversionParams forKey:ADJSKAdNetworkCallActualConversionParamsKey]; + // add client callback params dictionary and error objects if present + [result setObject:conversionParams forKey:ADJSkanClientCallbackParamsKey]; if (error != nil) { - [result setObject:error forKey:ADJSKAdNetworkCallErrorKey]; + [result setObject:error forKey:ADJSkanClientCompletionErrorKey]; } completion(result); }); } -- (void)writeSKAdNetworkRegisterCallTimestamp { +- (void)writeskanRegisterCallTimestamp { NSDate *callTime = [NSDate date]; [ADJUserDefaults saveSkadRegisterCallTimestamp:callTime]; } -- (NSDate *)skadNetworkRegisterCallTimestamp { +- (NSDate *)skanRegisterCallTimestamp { return [ADJUserDefaults getSkadRegisterCallTimestamp]; } -- (void)writeLastSKAdNetworkUpdateConversionValue:(NSNumber * _Nullable)conversionValue - coarseValue:(NSString * _Nullable)coarseValue - lockWindow:(NSNumber * _Nullable)lockWindow - timestamp:(NSDate * _Nonnull)timestamp - source:(NSString * _Nonnull)source { - +- (void)writeLastSkanUpdateConversionValue:(NSNumber * _Nullable)conversionValue + coarseValue:(NSString * _Nullable)coarseValue + lockWindow:(NSNumber * _Nullable)lockWindow + timestamp:(NSDate * _Nonnull)timestamp + source:(NSString * _Nonnull)source { NSMutableDictionary *skanUpdateData = [NSMutableDictionary dictionary]; if (conversionValue != nil) { - [skanUpdateData setObject:conversionValue forKey:kSkanConversionValueCallbackKey]; + [skanUpdateData setObject:conversionValue forKey:kSkanCallbackConversionValueKey]; } if (coarseValue != nil) { - [skanUpdateData setObject:coarseValue forKey:kSkanCoarseValueCallbackKey]; + [skanUpdateData setObject:coarseValue forKey:kSkanCallbackCoarseValueKey]; } if (lockWindow != nil) { - [skanUpdateData setObject:lockWindow forKey:kSkanLockWindowCallbackKey]; + [skanUpdateData setObject:lockWindow forKey:kSkanCallbackLockWindowKey]; } [skanUpdateData setObject:[ADJUtil formatDate:timestamp] forKey:@"timestamp"]; [skanUpdateData setObject:source forKey:@"source"]; @@ -554,12 +552,8 @@ - (void)writeLastSKAdNetworkUpdateConversionValue:(NSNumber * _Nullable)conversi [ADJUserDefaults saveLastSkanUpdateData:skanUpdateData]; } -- (NSDictionary *)lastSKAdNetworkUpdateData { - return [ADJUserDefaults getLastSkanUpdateData]; -} - -- (NSString *)getSKAdNetworkCoarseConversionValue:(NSString *)adjustCoarseValue - withError:(NSError **)error { +- (NSString *)getSkanCoarseConversionValue:(NSString *)adjustCoarseValue + withError:(NSError **)error { if (@available(iOS 16.1, *)) { if ([adjustCoarseValue isEqualToString:@"low"]) { NSString * __autoreleasing *lowValue = (NSString * __autoreleasing *)dlsym(RTLD_DEFAULT, "SKAdNetworkCoarseConversionValueLow"); @@ -572,15 +566,15 @@ - (NSString *)getSKAdNetworkCoarseConversionValue:(NSString *)adjustCoarseValue return *highValue; } else { NSString *strError = [NSString stringWithFormat:@"Coarse value \"%@\" is invalid", adjustCoarseValue]; - *error = [NSError errorWithDomain:ADJSKAdNetworkDomain - code:ADJSKAdNetworkErrorInvalidCoarseValue + *error = [NSError errorWithDomain:ADJSkanDomain + code:ADJSkanErrorInvalidCoarseValue userInfo:@{ NSLocalizedDescriptionKey: strError }]; return nil; } } else { - NSString *strError = [NSString stringWithFormat:@"SKAdNetwork Coarse value is not available on this iOS version"]; - *error = [NSError errorWithDomain:ADJSKAdNetworkDomain - code:ADJSKAdNetworkErrorApiNotAvailable + NSString *strError = [NSString stringWithFormat:@"SKAdNetwork цoarse value is not available on this iOS version"]; + *error = [NSError errorWithDomain:ADJSkanDomain + code:ADJSkanErrorApiNotAvailable userInfo:@{ NSLocalizedDescriptionKey: strError }]; return nil; } From ce4fa288f7e11f6ae02416e96d2f33d6bf5b4e88 Mon Sep 17 00:00:00 2001 From: genadyb Date: Fri, 10 Jan 2025 15:51:15 +0100 Subject: [PATCH 12/15] chore: version bump to 5.0.2 --- Adjust.podspec | 2 +- Adjust/Adjust.h | 2 +- Adjust/Internal/ADJUtil.m | 2 +- AdjustBridge/AdjustBridgeRegister.m | 2 +- VERSION | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Adjust.podspec b/Adjust.podspec index 694b75699..f04631004 100644 --- a/Adjust.podspec +++ b/Adjust.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "Adjust" s.module_name = "AdjustSdk" - s.version = "5.0.1" + s.version = "5.0.2" s.summary = "This is the iOS SDK of Adjust. You can read more about it at https://adjust.com." s.homepage = "https://github.com/adjust/ios_sdk" s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/Adjust/Adjust.h b/Adjust/Adjust.h index 8b780a6c1..6f11f1d66 100644 --- a/Adjust/Adjust.h +++ b/Adjust/Adjust.h @@ -2,7 +2,7 @@ // Adjust.h // Adjust SDK // -// V5.0.1 +// V5.0.2 // Created by Christian Wellenbrock (@wellle) on 23rd July 2013. // Copyright (c) 2012-Present Adjust GmbH. All rights reserved. // diff --git a/Adjust/Internal/ADJUtil.m b/Adjust/Internal/ADJUtil.m index 8b06e2033..45cee2394 100644 --- a/Adjust/Internal/ADJUtil.m +++ b/Adjust/Internal/ADJUtil.m @@ -31,7 +31,7 @@ static NSRegularExpression *goLinkUniversalLinkRegex = nil; static NSRegularExpression *excludedDeeplinkRegex = nil; -static NSString * const kClientSdk = @"ios5.0.1"; +static NSString * const kClientSdk = @"ios5.0.2"; static NSString * const kDeeplinkParam = @"deep_link="; static NSString * const kSchemeDelimiter = @"://"; static NSString * const kDefaultScheme = @"AdjustUniversalScheme"; diff --git a/AdjustBridge/AdjustBridgeRegister.m b/AdjustBridge/AdjustBridgeRegister.m index 36b12eac7..d9ac3d694 100644 --- a/AdjustBridge/AdjustBridgeRegister.m +++ b/AdjustBridge/AdjustBridgeRegister.m @@ -176,7 +176,7 @@ function canSend(okCheck, errReason) { if (this.sdkPrefix) { return this.sdkPrefix; } else { - return 'web-bridge5.0.1'; + return 'web-bridge5.0.2'; } }, diff --git a/VERSION b/VERSION index 6b244dcd6..a1ef0cae1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.0.1 +5.0.2 From 7c06a773641043fa39072b703025951cf93730ce Mon Sep 17 00:00:00 2001 From: uerceg Date: Fri, 10 Jan 2025 15:55:58 +0100 Subject: [PATCH 13/15] docs: update changelog --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16c484ebc..b4b00150a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +### Version 5.0.2 (10th January 2025) +#### Added +- Added sending of the aditional parameter to improve troubleshooting of `SKAdNetwork` related issues. + +#### Fixed +- Fixed occasional occurences in which ATT waiting interval timer was not being started. + +#### Changed +- Pinned version 3.35.2 of the Adjust signature library, which addresses occasional crashes on iOS 18 (https://github.com/adjust/ios_sdk/issues/742). + +--- + ### Version 5.0.1 (14th September 2024) #### Fixed - Fixed `Adjust.modulemap not found` error in certain CocoaPods integration cases. From 8051b7bdfa0226b23754dc89e826f2f7cfcc5ac9 Mon Sep 17 00:00:00 2001 From: uerceg Date: Fri, 10 Jan 2025 15:57:33 +0100 Subject: [PATCH 14/15] refac: remove unused variable --- Adjust/Internal/ADJPackageBuilder.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/Adjust/Internal/ADJPackageBuilder.m b/Adjust/Internal/ADJPackageBuilder.m index e389a1e3a..5b94ad82e 100644 --- a/Adjust/Internal/ADJPackageBuilder.m +++ b/Adjust/Internal/ADJPackageBuilder.m @@ -999,8 +999,6 @@ - (NSMutableDictionary *)getPurchaseVerificationParameters { } - (void)addIdfvIfPossibleToParameters:(NSMutableDictionary *)parameters { - id logger = [ADJAdjustFactory logger]; - if (self.adjustConfig.isIdfvReadingEnabled == NO) { return; } From 9431332f4b5f82ce68f14778ba0367ca9f94281a Mon Sep 17 00:00:00 2001 From: uerceg Date: Fri, 10 Jan 2025 16:55:37 +0100 Subject: [PATCH 15/15] docs: fix typos in changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4b00150a..8d1aee6ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,9 @@ ### Version 5.0.2 (10th January 2025) #### Added -- Added sending of the aditional parameter to improve troubleshooting of `SKAdNetwork` related issues. +- Added sending of the additional parameter to improve troubleshooting of `SKAdNetwork` related issues. #### Fixed -- Fixed occasional occurences in which ATT waiting interval timer was not being started. +- Fixed occasional occurrences in which ATT waiting interval timer was not being started. #### Changed - Pinned version 3.35.2 of the Adjust signature library, which addresses occasional crashes on iOS 18 (https://github.com/adjust/ios_sdk/issues/742).