From d0cc98f16abd88d866b9d2015d1fed8da14efd0f Mon Sep 17 00:00:00 2001 From: uerceg Date: Thu, 16 Apr 2020 02:56:13 +0200 Subject: [PATCH 01/35] Initial subscription tracking implementation --- Adjust.xcodeproj/project.pbxproj | 40 ++++++ Adjust/ADJActivityHandler.h | 3 + Adjust/ADJActivityHandler.m | 42 ++++++ Adjust/ADJActivityKind.h | 21 +-- Adjust/ADJActivityKind.m | 4 + Adjust/ADJAdjustFactory.h | 2 + Adjust/ADJAdjustFactory.m | 10 ++ Adjust/ADJPackageBuilder.h | 3 + Adjust/ADJPackageBuilder.m | 97 +++++++++++++ Adjust/ADJPackageHandler.h | 1 + Adjust/ADJPackageHandler.m | 6 + Adjust/ADJRequestHandler.m | 10 ++ Adjust/ADJSubscription.h | 43 ++++++ Adjust/ADJSubscription.m | 135 ++++++++++++++++++ Adjust/Adjust.h | 12 ++ Adjust/Adjust.m | 18 +++ AdjustSdk/AdjustSdk.h | 1 + AdjustSdkIm/AdjustSdkIm.h | 1 + AdjustSdkTv/AdjustSdkTv.h | 1 + AdjustSdkWebBridge/AdjustSdkWebBridge.h | 1 + .../AdjustTestApp.xcodeproj/project.pbxproj | 6 + .../AdjustTestApp/ATAAdjustCommandExecutor.m | 7 + .../AdjustTestApp/ViewController.h | 1 + .../project.pbxproj | 6 + .../project.pbxproj | 6 + .../project.pbxproj | 6 + .../project.pbxproj | 6 + .../project.pbxproj | 6 + .../project.pbxproj | 6 + .../project.pbxproj | 6 + 30 files changed, 497 insertions(+), 10 deletions(-) create mode 100644 Adjust/ADJSubscription.h create mode 100644 Adjust/ADJSubscription.m diff --git a/Adjust.xcodeproj/project.pbxproj b/Adjust.xcodeproj/project.pbxproj index 5faf90ca2..84695aeec 100644 --- a/Adjust.xcodeproj/project.pbxproj +++ b/Adjust.xcodeproj/project.pbxproj @@ -216,6 +216,16 @@ 9D0E2EB9210B575600133B4F /* WKWebViewJavascriptBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D0E2E68210B575600133B4F /* WKWebViewJavascriptBridge.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9D0E2EBA210B575600133B4F /* AdjustBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D0E2E69210B575600133B4F /* AdjustBridge.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9D0E2EBB210B575600133B4F /* AdjustBridgeRegister.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D0E2E6A210B575600133B4F /* AdjustBridgeRegister.m */; }; + 9D2F23E22447CE5C00B7CA90 /* ADJSubscription.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D2F23E02447CE5C00B7CA90 /* ADJSubscription.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D2F23E32447CE5C00B7CA90 /* ADJSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2F23E12447CE5C00B7CA90 /* ADJSubscription.m */; }; + 9D2F23F82447DCE800B7CA90 /* ADJSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2F23F62447DCE800B7CA90 /* ADJSubscription.m */; }; + 9D2F23F92447DCE800B7CA90 /* ADJSubscription.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D2F23F72447DCE800B7CA90 /* ADJSubscription.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D2F23FC2447DD2500B7CA90 /* ADJSubscription.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D2F23FA2447DD2500B7CA90 /* ADJSubscription.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D2F23FD2447DD2500B7CA90 /* ADJSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2F23FB2447DD2500B7CA90 /* ADJSubscription.m */; }; + 9D2F24002447DD3700B7CA90 /* ADJSubscription.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D2F23FE2447DD3600B7CA90 /* ADJSubscription.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D2F24012447DD3700B7CA90 /* ADJSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2F23FF2447DD3700B7CA90 /* ADJSubscription.m */; }; + 9D2F24042447DD6000B7CA90 /* ADJSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2F24022447DD6000B7CA90 /* ADJSubscription.m */; }; + 9D2F24052447DD6000B7CA90 /* ADJSubscription.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D2F24032447DD6000B7CA90 /* ADJSubscription.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9D363AC31BDA50FA00B47FE9 /* ADJLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 96E5E37318BBB48A008E7B30 /* ADJLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9D7431EA1EB9F9B700969F14 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D7431E91EB9F9B700969F14 /* main.m */; }; 9D7431ED1EB9F9B700969F14 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D7431EC1EB9F9B700969F14 /* AppDelegate.m */; }; @@ -806,6 +816,16 @@ 9D0E2E68210B575600133B4F /* WKWebViewJavascriptBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebViewJavascriptBridge.h; sourceTree = ""; }; 9D0E2E69210B575600133B4F /* AdjustBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdjustBridge.h; sourceTree = ""; }; 9D0E2E6A210B575600133B4F /* AdjustBridgeRegister.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AdjustBridgeRegister.m; sourceTree = ""; }; + 9D2F23E02447CE5C00B7CA90 /* ADJSubscription.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ADJSubscription.h; sourceTree = ""; }; + 9D2F23E12447CE5C00B7CA90 /* ADJSubscription.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ADJSubscription.m; sourceTree = ""; }; + 9D2F23F62447DCE800B7CA90 /* ADJSubscription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSubscription.m; sourceTree = ""; }; + 9D2F23F72447DCE800B7CA90 /* ADJSubscription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSubscription.h; sourceTree = ""; }; + 9D2F23FA2447DD2500B7CA90 /* ADJSubscription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSubscription.h; sourceTree = ""; }; + 9D2F23FB2447DD2500B7CA90 /* ADJSubscription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSubscription.m; sourceTree = ""; }; + 9D2F23FE2447DD3600B7CA90 /* ADJSubscription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSubscription.h; sourceTree = ""; }; + 9D2F23FF2447DD3700B7CA90 /* ADJSubscription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSubscription.m; sourceTree = ""; }; + 9D2F24022447DD6000B7CA90 /* ADJSubscription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSubscription.m; sourceTree = ""; }; + 9D2F24032447DD6000B7CA90 /* ADJSubscription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSubscription.h; sourceTree = ""; }; 9D449DB31E6ED23400E7E80B /* AdjustExample-iWatch.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "AdjustExample-iWatch.xcodeproj"; path = "examples/AdjustExample-iWatch/AdjustExample-iWatch.xcodeproj"; sourceTree = ""; }; 9D449DBF1E6ED23900E7E80B /* AdjustExample-Swift.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "AdjustExample-Swift.xcodeproj"; path = "examples/AdjustExample-Swift/AdjustExample-Swift.xcodeproj"; sourceTree = ""; }; 9D449DC51E6ED24000E7E80B /* AdjustExample-tvOS.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "AdjustExample-tvOS.xcodeproj"; path = "examples/AdjustExample-tvOS/AdjustExample-tvOS.xcodeproj"; sourceTree = ""; }; @@ -1334,6 +1354,8 @@ 6FCC84F71F278CF300D6A0ED /* ADJReachability.m */, 9DD0E9AC1F44690B00B2A759 /* ADJUserDefaults.h */, 9DD0E9AD1F44690B00B2A759 /* ADJUserDefaults.m */, + 9D2F23E02447CE5C00B7CA90 /* ADJSubscription.h */, + 9D2F23E12447CE5C00B7CA90 /* ADJSubscription.m */, ); path = Adjust; sourceTree = ""; @@ -1434,6 +1456,8 @@ 9D0E2E58210B575600133B4F /* ADJTimerCycle.h */, 9D0E2E59210B575600133B4F /* ADJActivityHandler.m */, 9D0E2E5A210B575600133B4F /* ADJReachability.m */, + 9D2F24032447DD6000B7CA90 /* ADJSubscription.h */, + 9D2F24022447DD6000B7CA90 /* ADJSubscription.m */, ); path = Adjust; sourceTree = SOURCE_ROOT; @@ -1638,6 +1662,8 @@ 9DEAF0F2210072BC005CAEDB /* ADJTimerCycle.h */, 9DEAF0F3210072BC005CAEDB /* ADJActivityHandler.m */, 9DEAF0F4210072BC005CAEDB /* ADJReachability.m */, + 9D2F23FA2447DD2500B7CA90 /* ADJSubscription.h */, + 9D2F23FB2447DD2500B7CA90 /* ADJSubscription.m */, ); path = Adjust; sourceTree = SOURCE_ROOT; @@ -1717,6 +1743,8 @@ 96B671131D788F4A0090A023 /* ADJSessionParameters.m */, 6FCC85021F27944600D6A0ED /* ADJReachability.h */, 6FCC85031F27944600D6A0ED /* ADJReachability.m */, + 9D2F23F72447DCE800B7CA90 /* ADJSubscription.h */, + 9D2F23F62447DCE800B7CA90 /* ADJSubscription.m */, ); path = Adjust; sourceTree = SOURCE_ROOT; @@ -1816,6 +1844,8 @@ 96B671171D788F7A0090A023 /* ADJSessionParameters.m */, 6FCC85071F27948700D6A0ED /* ADJReachability.h */, 6FCC85061F27948700D6A0ED /* ADJReachability.m */, + 9D2F23FE2447DD3600B7CA90 /* ADJSubscription.h */, + 9D2F23FF2447DD3700B7CA90 /* ADJSubscription.m */, ); path = Adjust; sourceTree = SOURCE_ROOT; @@ -1845,6 +1875,7 @@ 96BCFBD01AC9923F005A65C5 /* ADJConfig.h in Headers */, 9D363AC31BDA50FA00B47FE9 /* ADJLogger.h in Headers */, 96BCFBD11AC99246005A65C5 /* ADJAttribution.h in Headers */, + 9D2F23E22447CE5C00B7CA90 /* ADJSubscription.h in Headers */, 9601CAE81C74BAAE00670879 /* ADJEventFailure.h in Headers */, 9601CAE41C74B70600670879 /* ADJEventSuccess.h in Headers */, 6FCC85011F278CF300D6A0ED /* ADJReachability.h in Headers */, @@ -1890,6 +1921,7 @@ 9D0E2E6B210B575600133B4F /* ADJConfig.h in Headers */, 9D0E2E8F210B575600133B4F /* ADJEvent.h in Headers */, 9D0E2E73210B575600133B4F /* ADJAttribution.h in Headers */, + 9D2F24052447DD6000B7CA90 /* ADJSubscription.h in Headers */, 9D0E2EA2210B575600133B4F /* ADJEventFailure.h in Headers */, 9D0E2EA1210B575600133B4F /* ADJEventSuccess.h in Headers */, 9D0E2E9E210B575600133B4F /* ADJSessionFailure.h in Headers */, @@ -1931,6 +1963,7 @@ 9DEAF0F9210072BC005CAEDB /* Adjust.h in Headers */, 9DEAF0F5210072BC005CAEDB /* ADJConfig.h in Headers */, 9DEAF119210072BC005CAEDB /* ADJEvent.h in Headers */, + 9D2F23FC2447DD2500B7CA90 /* ADJSubscription.h in Headers */, 9DEAF0FD210072BC005CAEDB /* ADJAttribution.h in Headers */, 9DEAF12E210072BC005CAEDB /* ADJSessionSuccess.h in Headers */, 9DEAF128210072BC005CAEDB /* ADJSessionFailure.h in Headers */, @@ -1973,6 +2006,7 @@ 9DF9C91F1D6F3CA5008E362F /* ADJConfig.h in Headers */, 9DF9C92B1D6F3CA5008E362F /* ADJLogger.h in Headers */, 9DF9C9191D6F3CA5008E362F /* ADJAttribution.h in Headers */, + 9D2F23F92447DCE800B7CA90 /* ADJSubscription.h in Headers */, 9DF9C9251D6F3CA5008E362F /* ADJEventFailure.h in Headers */, 9DF9C9271D6F3CA5008E362F /* ADJEventSuccess.h in Headers */, 9DF9C9371D6F3CA5008E362F /* ADJSessionFailure.h in Headers */, @@ -2014,6 +2048,7 @@ 9DFB06701D7470C0006D48FC /* ADJConfig.h in Headers */, 9DFB067C1D7470C0006D48FC /* ADJLogger.h in Headers */, 9DFB066A1D7470C0006D48FC /* ADJAttribution.h in Headers */, + 9D2F24002447DD3700B7CA90 /* ADJSubscription.h in Headers */, 9DFB06761D7470C0006D48FC /* ADJEventFailure.h in Headers */, 9DFB06781D7470C0006D48FC /* ADJEventSuccess.h in Headers */, 9DFB06881D7470C0006D48FC /* ADJSessionFailure.h in Headers */, @@ -2528,6 +2563,7 @@ 96E5E39418BBB48A008E7B30 /* ADJPackageBuilder.m in Sources */, 6FCC85001F278CF300D6A0ED /* ADJReachability.m in Sources */, 96E5E39618BBB48A008E7B30 /* ADJRequestHandler.m in Sources */, + 9D2F23E32447CE5C00B7CA90 /* ADJSubscription.m in Sources */, 96E5E39918BBB48A008E7B30 /* ADJUtil.m in Sources */, 9609BC6A19EEA55800E02303 /* ADJEvent.m in Sources */, 965307F61A000DA400107FF9 /* ADJDeviceInfo.m in Sources */, @@ -2614,6 +2650,7 @@ 9D0E2E6D210B575600133B4F /* ADJTimerOnce.m in Sources */, 9D0E2E77210B575600133B4F /* ADJEvent.m in Sources */, 9D0E2E8D210B575600133B4F /* ADJConfig.m in Sources */, + 9D2F24042447DD6000B7CA90 /* ADJSubscription.m in Sources */, 9D0E2E6E210B575600133B4F /* ADJAttributionHandler.m in Sources */, 9D0E2E87210B575600133B4F /* ADJBackoffStrategy.m in Sources */, 9D0E2EBB210B575600133B4F /* AdjustBridgeRegister.m in Sources */, @@ -2657,6 +2694,7 @@ 9DEAF10A210072BC005CAEDB /* ADJSessionFailure.m in Sources */, 9DEAF121210072BC005CAEDB /* UIDevice+ADJAdditions.m in Sources */, 9DEAF105210072BC005CAEDB /* ADJSessionSuccess.m in Sources */, + 9D2F23FD2447DD2500B7CA90 /* ADJSubscription.m in Sources */, 9DEAF124210072BC005CAEDB /* ADJSystemProfile.m in Sources */, 9DEAF0FB210072BC005CAEDB /* ADJRequestHandler.m in Sources */, 9DEAF11B210072BC005CAEDB /* ADJActivityKind.m in Sources */, @@ -2697,6 +2735,7 @@ 9DF9C92E1D6F3CA5008E362F /* ADJPackageBuilder.m in Sources */, 9DF9C9301D6F3CA5008E362F /* ADJPackageHandler.m in Sources */, 6FCC85051F27946100D6A0ED /* ADJReachability.m in Sources */, + 9D2F23F82447DCE800B7CA90 /* ADJSubscription.m in Sources */, 9DF9C9321D6F3CA5008E362F /* ADJRequestHandler.m in Sources */, 9DF9C9461D6F3CA5008E362F /* ADJUtil.m in Sources */, 9DF9C9241D6F3CA5008E362F /* ADJEvent.m in Sources */, @@ -2737,6 +2776,7 @@ 9DFB067F1D7470C0006D48FC /* ADJPackageBuilder.m in Sources */, 9DFB06811D7470C0006D48FC /* ADJPackageHandler.m in Sources */, 6FCC85091F27949000D6A0ED /* ADJReachability.m in Sources */, + 9D2F24012447DD3700B7CA90 /* ADJSubscription.m in Sources */, 9DFB06831D7470C0006D48FC /* ADJRequestHandler.m in Sources */, 9DFB06971D7470C0006D48FC /* ADJUtil.m in Sources */, 9DFB06751D7470C0006D48FC /* ADJEvent.m in Sources */, diff --git a/Adjust/ADJActivityHandler.h b/Adjust/ADJActivityHandler.h index da2787fb7..9a96dd4fa 100644 --- a/Adjust/ADJActivityHandler.h +++ b/Adjust/ADJActivityHandler.h @@ -46,6 +46,7 @@ @property (nonatomic, assign) BOOL offline; @property (nonatomic, copy) NSString *basePath; @property (nonatomic, copy) NSString *gdprPath; +@property (nonatomic, copy) NSString *subscriptionPath; - (id)init; @@ -97,8 +98,10 @@ - (void)resetSessionPartnerParameters; - (void)trackAdRevenue:(NSString *)soruce payload:(NSData *)payload; - (void)disableThirdPartySharing; +- (void)trackSubscription:(ADJSubscription *)subscription; - (NSString *)getBasePath; - (NSString *)getGdprPath; +- (NSString *)getSubscriptionPath; - (ADJDeviceInfo *)deviceInfo; - (ADJActivityState *)activityState; diff --git a/Adjust/ADJActivityHandler.m b/Adjust/ADJActivityHandler.m index 6f8311c21..009e74916 100644 --- a/Adjust/ADJActivityHandler.m +++ b/Adjust/ADJActivityHandler.m @@ -99,6 +99,7 @@ @interface ADJActivityHandler() @property (nonatomic, copy) NSData* deviceTokenData; @property (nonatomic, copy) NSString* basePath; @property (nonatomic, copy) NSString* gdprPath; +@property (nonatomic, copy) NSString* subscriptionPath; @end @@ -201,6 +202,9 @@ - (id)initWithConfig:(ADJConfig *)adjustConfig if (savedPreLaunch.gdprPath != nil) { self.gdprPath = savedPreLaunch.gdprPath; } + if (savedPreLaunch.subscriptionPath != nil) { + self.subscriptionPath = savedPreLaunch.subscriptionPath; + } self.iAdRetriesLeft = kiAdRetriesCount; @@ -607,6 +611,14 @@ - (void)trackAdRevenue:(NSString *)source payload:(NSData *)payload { }]; } +- (void)trackSubscription:(ADJSubscription *)subscription { + [ADJUtil launchInQueue:self.internalQueue + selfInject:self + block:^(ADJActivityHandler * selfI) { + [selfI trackSubscriptionI:selfI subscription:subscription]; + }]; +} + - (void)disableThirdPartySharing { [ADJUtil launchInQueue:self.internalQueue selfInject:self @@ -623,6 +635,10 @@ - (NSString *)getGdprPath { return _gdprPath; } +- (NSString *)getSubscriptionPath { + return _subscriptionPath; +} + - (void)teardown { [ADJAdjustFactory.logger verbose:@"ADJActivityHandler teardown"]; @@ -1022,6 +1038,32 @@ - (void)adRevenueI:(ADJActivityHandler *)selfI [selfI.packageHandler sendFirstPackage]; } +- (void)trackSubscriptionI:(ADJActivityHandler *)selfI + subscription:(ADJSubscription *)subscription { + if (!selfI.activityState) { + return; + } + if (![selfI isEnabledI:selfI]) { + return; + } + if (selfI.activityState.isGdprForgotten) { + return; + } + + double now = [NSDate.date timeIntervalSince1970]; + + // Create and submit ad revenue package. + ADJPackageBuilder *subscriptionBuilder = [[ADJPackageBuilder alloc] initWithDeviceInfo:selfI.deviceInfo + activityState:selfI.activityState + config:selfI.adjustConfig + sessionParameters:selfI.sessionParameters + createdAt:now]; + ADJActivityPackage *subscriptionPackage = [subscriptionBuilder buildSubscriptionPackage:subscription + isInDelay:[selfI.internalState isInDelayedStart]]; + [selfI.packageHandler addPackage:subscriptionPackage]; + [selfI.packageHandler sendFirstPackage]; +} + - (void)disableThirdPartySharingI:(ADJActivityHandler *)selfI { // cache the disable third party sharing request, so that the request order maintains // even this call returns before making server request diff --git a/Adjust/ADJActivityKind.h b/Adjust/ADJActivityKind.h index 6a13128c0..1f83c99d0 100644 --- a/Adjust/ADJActivityKind.h +++ b/Adjust/ADJActivityKind.h @@ -13,16 +13,17 @@ #endif typedef NS_ENUM(int, ADJActivityKind) { - ADJActivityKindUnknown = 0, - ADJActivityKindSession = 1, - ADJActivityKindEvent = 2, -// ADJActivityKindRevenue = 3, - ADJActivityKindClick = 4, - ADJActivityKindAttribution = 5, - ADJActivityKindInfo = 6, - ADJActivityKindGdpr = 7, - ADJActivityKindAdRevenue = 8, - ADJActivityKindDisableThirdPartySharing = 9 + ADJActivityKindUnknown = 0, + ADJActivityKindSession = 1, + ADJActivityKindEvent = 2, + // ADJActivityKindRevenue = 3, + ADJActivityKindClick = 4, + ADJActivityKindAttribution = 5, + ADJActivityKindInfo = 6, + ADJActivityKindGdpr = 7, + ADJActivityKindAdRevenue = 8, + ADJActivityKindDisableThirdPartySharing = 9, + ADJActivityKindSubscription = 10 }; @interface ADJActivityKindUtil : NSObject diff --git a/Adjust/ADJActivityKind.m b/Adjust/ADJActivityKind.m index 694ff623f..7c8cb862d 100644 --- a/Adjust/ADJActivityKind.m +++ b/Adjust/ADJActivityKind.m @@ -29,6 +29,8 @@ + (ADJActivityKind)activityKindFromString:(NSString *)activityKindString { return ADJActivityKindAdRevenue; } else if ([@"disable_third_party_sharing" isEqualToString:activityKindString]) { return ADJActivityKindDisableThirdPartySharing; + } else if ([@"subscription" isEqualToString:activityKindString]) { + return ADJActivityKindSubscription; } else { return ADJActivityKindUnknown; } @@ -52,6 +54,8 @@ + (NSString *)activityKindToString:(ADJActivityKind)activityKind { return @"ad_revenue"; case ADJActivityKindDisableThirdPartySharing: return @"disable_third_party_sharing"; + case ADJActivityKindSubscription: + return @"subscription"; default: return @"unknown"; } diff --git a/Adjust/ADJAdjustFactory.h b/Adjust/ADJAdjustFactory.h index fab71f48f..fce9560b3 100644 --- a/Adjust/ADJAdjustFactory.h +++ b/Adjust/ADJAdjustFactory.h @@ -42,6 +42,7 @@ + (NSTimeInterval)maxDelayStart; + (NSString *)baseUrl; + (NSString *)gdprUrl; ++ (NSString *)subscriptionUrl; + (BOOL)iAdFrameworkEnabled; + (void)setPackageHandler:(id)packageHandler; @@ -61,6 +62,7 @@ + (void)setMaxDelayStart:(NSTimeInterval)maxDelayStart; + (void)setBaseUrl:(NSString *)baseUrl; + (void)setGdprUrl:(NSString *)gdprUrl; ++ (void)setSubscriptionUrl:(NSString *)subscriptionUrl; + (void)enableSigning; + (void)disableSigning; diff --git a/Adjust/ADJAdjustFactory.m b/Adjust/ADJAdjustFactory.m index 2c59c67bd..e58e0f0f2 100644 --- a/Adjust/ADJAdjustFactory.m +++ b/Adjust/ADJAdjustFactory.m @@ -30,6 +30,8 @@ static NSString * internalBaseUrl = @"https://app.adjust.com"; static NSString * const kGdprUrl = @"https://gdpr.adjust.com"; static NSString * internalGdprUrl = @"https://gdpr.adjust.com"; +static NSString * const kSubscriptionUrl = @"https://staging-api-sub.adjust.com"; +static NSString * internalSubscriptionUrl = @"https://staging-api-sub.adjust.com"; @implementation ADJAdjustFactory @@ -166,6 +168,10 @@ + (NSString *)gdprUrl { return internalGdprUrl; } ++ (NSString *)subscriptionUrl { + return internalSubscriptionUrl; +} + + (void)setPackageHandler:(id)packageHandler { internalPackageHandler = packageHandler; } @@ -234,6 +240,10 @@ + (void)setGdprUrl:(NSString *)gdprUrl { internalGdprUrl = gdprUrl; } ++ (void)setSubscriptionUrl:(NSString *)subscriptionUrl { + internalSubscriptionUrl = subscriptionUrl; +} + + (void)enableSigning { Class signerClass = NSClassFromString(@"ADJSigner"); if (signerClass == nil) { diff --git a/Adjust/ADJPackageBuilder.h b/Adjust/ADJPackageBuilder.h index 026079dc9..3b1349dd1 100644 --- a/Adjust/ADJPackageBuilder.h +++ b/Adjust/ADJPackageBuilder.h @@ -51,6 +51,9 @@ - (ADJActivityPackage *)buildDisableThirdPartySharingPackage; +- (ADJActivityPackage *)buildSubscriptionPackage:(ADJSubscription *)subscription + isInDelay:(BOOL)isInDelay; + + (void)parameters:(NSMutableDictionary *)parameters setDictionary:(NSDictionary *)dictionary forKey:(NSString *)key; diff --git a/Adjust/ADJPackageBuilder.m b/Adjust/ADJPackageBuilder.m index 6d67f92dc..6c67236be 100644 --- a/Adjust/ADJPackageBuilder.m +++ b/Adjust/ADJPackageBuilder.m @@ -163,6 +163,25 @@ - (ADJActivityPackage *)buildDisableThirdPartySharingPackage { return dtpsPackage; } +- (ADJActivityPackage *)buildSubscriptionPackage:(ADJSubscription *)subscription + isInDelay:(BOOL)isInDelay { + NSMutableDictionary *parameters = [self getSubscriptionParameters:isInDelay forSubscriptionPackage:subscription]; + ADJActivityPackage *subscriptionPackage = [self defaultActivityPackage]; + subscriptionPackage.path = @"/v2/purchase"; + subscriptionPackage.activityKind = ADJActivityKindEvent; + subscriptionPackage.suffix = @""; + subscriptionPackage.parameters = parameters; + + if (isInDelay) { + subscriptionPackage.callbackParameters = subscriptionPackage.callbackParameters; + subscriptionPackage.partnerParameters = subscriptionPackage.partnerParameters; + } + + [self signWithSigV2Plugin:subscriptionPackage]; + + return subscriptionPackage; +} + + (void)parameters:(NSMutableDictionary *)parameters setDictionary:(NSDictionary *)dictionary forKey:(NSString *)key { if (dictionary == nil) { return; @@ -726,6 +745,84 @@ - (NSMutableDictionary *)getDisableThirdPartySharingParameters { return parameters; } +- (NSMutableDictionary *)getSubscriptionParameters:(BOOL)isInDelay forSubscriptionPackage:(ADJSubscription *)subscription { + NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; + + [ADJPackageBuilder parameters:parameters setString:self.adjustConfig.appSecret forKey:@"app_secret"]; + [ADJPackageBuilder parameters:parameters setString:self.adjustConfig.appToken forKey:@"app_token"]; + [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.bundleVersion forKey:@"app_version"]; + [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.bundleShortVersion forKey:@"app_version_short"]; + [ADJPackageBuilder parameters:parameters setBool:YES forKey:@"attribution_deeplink"]; + [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.bundeIdentifier forKey:@"bundle_id"]; + [ADJPackageBuilder parameters:parameters setNumberInt:[ADJUtil readReachabilityFlags] forKey:@"connectivity_type"]; + [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.countryCode forKey:@"country"]; + [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.cpuSubtype forKey:@"cpu_type"]; + [ADJPackageBuilder parameters:parameters setDate1970:self.createdAt forKey:@"created_at"]; + [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.deviceName forKey:@"device_name"]; + [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.deviceType forKey:@"device_type"]; + [ADJPackageBuilder parameters:parameters setString:self.adjustConfig.environment forKey:@"environment"]; + [ADJPackageBuilder parameters:parameters setBool:self.adjustConfig.eventBufferingEnabled forKey:@"event_buffering_enabled"]; + [ADJPackageBuilder parameters:parameters setString:self.adjustConfig.externalDeviceId forKey:@"external_device_id"]; + [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.fbAnonymousId forKey:@"fb_anon_id"]; + [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.machineModel forKey:@"hardware_name"]; + if (self.adjustConfig.allowIdfaReading == YES) { + [ADJPackageBuilder parameters:parameters setString:UIDevice.currentDevice.adjIdForAdvertisers forKey:@"idfa"]; + } + [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.vendorId forKey:@"idfv"]; + [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.installReceiptBase64 forKey:@"install_receipt"]; + [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.languageCode forKey:@"language"]; + [ADJPackageBuilder parameters:parameters setBool:YES forKey:@"needs_response_details"]; + [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.osBuild forKey:@"os_build"]; + [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.osName forKey:@"os_name"]; + [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.systemVersion forKey:@"os_version"]; + [ADJPackageBuilder parameters:parameters setString:self.adjustConfig.secretId forKey:@"secret_id"]; + [ADJPackageBuilder parameters:parameters setInt:UIDevice.currentDevice.adjTrackingEnabled forKey:@"tracking_enabled"]; + + if (self.adjustConfig.isDeviceKnown) { + [ADJPackageBuilder parameters:parameters setBool:self.adjustConfig.isDeviceKnown forKey:@"device_known"]; + } + + if (self.activityState != nil) { + [ADJPackageBuilder parameters:parameters setInt:self.activityState.eventCount forKey:@"event_count"]; + [ADJPackageBuilder parameters:parameters setString:self.activityState.deviceToken forKey:@"push_token"]; + [ADJPackageBuilder parameters:parameters setInt:self.activityState.sessionCount forKey:@"session_count"]; + [ADJPackageBuilder parameters:parameters setDuration:self.activityState.sessionLength forKey:@"session_length"]; + [ADJPackageBuilder parameters:parameters setInt:self.activityState.subsessionCount forKey:@"subsession_count"]; + [ADJPackageBuilder parameters:parameters setDuration:self.activityState.timeSpent forKey:@"time_spent"]; + if (self.activityState.isPersisted) { + [ADJPackageBuilder parameters:parameters setString:self.activityState.uuid forKey:@"persistent_ios_uuid"]; + } else { + [ADJPackageBuilder parameters:parameters setString:self.activityState.uuid forKey:@"ios_uuid"]; + } + } + + if (!isInDelay) { + NSDictionary *mergedCallbackParameters = [ADJUtil mergeParameters:self.sessionParameters.callbackParameters + source:subscription.callbackParameters + parameterName:@"Callback"]; + NSDictionary *mergedPartnerParameters = [ADJUtil mergeParameters:self.sessionParameters.partnerParameters + source:subscription.partnerParameters + parameterName:@"Partner"]; + + [ADJPackageBuilder parameters:parameters setDictionary:mergedCallbackParameters forKey:@"callback_params"]; + [ADJPackageBuilder parameters:parameters setDictionary:mergedPartnerParameters forKey:@"partner_params"]; + } + + [ADJPackageBuilder parameters:parameters setNumber:subscription.revenue forKey:@"revenue"]; + [ADJPackageBuilder parameters:parameters setString:subscription.currency forKey:@"currency"]; + [ADJPackageBuilder parameters:parameters setDate1970:[subscription.transactionDate doubleValue] forKey:@"transaction_date"]; + [ADJPackageBuilder parameters:parameters setString:subscription.transactionId forKey:@"transaction_id"]; + [ADJPackageBuilder parameters:parameters setString:[subscription.receipt adjEncodeBase64] forKey:@"receipt"]; + [ADJPackageBuilder parameters:parameters setString:subscription.billingStore forKey:@"billing_store"]; + +#if !TARGET_OS_TV && !TARGET_OS_MACCATALYST + [ADJPackageBuilder parameters:parameters setString:[ADJUtil readMCC] forKey:@"mcc"]; + [ADJPackageBuilder parameters:parameters setString:[ADJUtil readMNC] forKey:@"mnc"]; + [ADJPackageBuilder parameters:parameters setString:[ADJUtil readCurrentRadioAccessTechnology] forKey:@"network_type"]; +#endif + + return parameters; +} - (ADJActivityPackage *)defaultActivityPackage { ADJActivityPackage *activityPackage = [[ADJActivityPackage alloc] init]; diff --git a/Adjust/ADJPackageHandler.h b/Adjust/ADJPackageHandler.h index a69a2df97..12d4f3a01 100644 --- a/Adjust/ADJPackageHandler.h +++ b/Adjust/ADJPackageHandler.h @@ -29,6 +29,7 @@ - (void)flush; - (NSString *)getBasePath; - (NSString *)getGdprPath; +- (NSString *)getSubscriptionPath; - (void)teardown; + (void)deleteState; diff --git a/Adjust/ADJPackageHandler.m b/Adjust/ADJPackageHandler.m index 6bf96692b..c918f4dce 100644 --- a/Adjust/ADJPackageHandler.m +++ b/Adjust/ADJPackageHandler.m @@ -33,6 +33,7 @@ @interface ADJPackageHandler() @property (nonatomic, weak) id logger; @property (nonatomic, copy) NSString *basePath; @property (nonatomic, copy) NSString *gdprPath; +@property (nonatomic, copy) NSString *subscriptionPath; @property (nonatomic, assign) NSInteger lastPackageRetriesCount; @end @@ -57,6 +58,7 @@ - (id)initWithActivityHandler:(id)activityHandler self.backoffStrategyForInstallSession = [ADJAdjustFactory installSessionBackoffStrategy]; self.basePath = [activityHandler getBasePath]; self.gdprPath = [activityHandler getGdprPath]; + self.subscriptionPath = [activityHandler getSubscriptionPath]; self.lastPackageRetriesCount = 0; [ADJUtil launchInQueue:self.internalQueue @@ -165,6 +167,10 @@ - (NSString *)getGdprPath { return _gdprPath; } +- (NSString *)getSubscriptionPath { + return _subscriptionPath; +} + - (void)teardown { [ADJAdjustFactory.logger verbose:@"ADJPackageHandler teardown"]; if (self.sendingSemaphore != nil) { diff --git a/Adjust/ADJRequestHandler.m b/Adjust/ADJRequestHandler.m index 5e8e1bc90..260c7b466 100644 --- a/Adjust/ADJRequestHandler.m +++ b/Adjust/ADJRequestHandler.m @@ -30,6 +30,8 @@ @interface ADJRequestHandler() @property (nonatomic, copy) NSString *gdprPath; +@property (nonatomic, copy) NSString *subscriptionPath; + @end @implementation ADJRequestHandler @@ -56,6 +58,7 @@ - (id)initWithPackageHandler:(id)packageHandler self.logger = ADJAdjustFactory.logger; self.basePath = [packageHandler getBasePath]; self.gdprPath = [packageHandler getGdprPath]; + self.gdprPath = [packageHandler getSubscriptionPath]; return self; } @@ -89,6 +92,13 @@ - (void)sendI:(ADJRequestHandler *)selfI activityPackage:(ADJActivityPackage *)a } else { url = [NSURL URLWithString:gdprUrl]; } + } else if (activityPackage.activityKind == ADJActivityKindGdpr) { + NSString *subscriptionUrl = [ADJAdjustFactory subscriptionUrl]; + if (selfI.subscriptionPath != nil) { + url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", subscriptionUrl, selfI.subscriptionPath]]; + } else { + url = [NSURL URLWithString:subscriptionUrl]; + } } else { NSString *baseUrl = [ADJAdjustFactory baseUrl]; if (selfI.basePath != nil) { diff --git a/Adjust/ADJSubscription.h b/Adjust/ADJSubscription.h new file mode 100644 index 000000000..0e7eea10d --- /dev/null +++ b/Adjust/ADJSubscription.h @@ -0,0 +1,43 @@ +// +// ADJSubscription.h +// Adjust +// +// Created by Uglješa Erceg on 16.04.20. +// Copyright © 2020 adjust GmbH. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ADJSubscription : NSObject + +@property (nonatomic, copy, readonly, nonnull) NSNumber *revenue; + +@property (nonatomic, copy, readonly, nonnull) NSString *currency; + +@property (nonatomic, copy, readonly, nonnull) NSNumber *transactionDate; + +@property (nonatomic, copy, readonly, nonnull) NSString *transactionId; + +@property (nonatomic, copy, readonly, nonnull) NSData *receipt; + +@property (nonatomic, copy, readonly, nonnull) NSString *billingStore; + +@property (nonatomic, readonly, nonnull) NSDictionary *partnerParameters; + +@property (nonatomic, readonly, nonnull) NSDictionary *callbackParameters; + +- (nullable id)initWithRevenue:(double)revenue + currency:(nonnull NSString *)currency + transactionDate:(double)transactionDate + transactionId:(nonnull NSString *)transactionId + andReceipt:(nonnull NSData *)receipt; + +- (void)addCallbackParameter:(nonnull NSString *)key value:(nonnull NSString *)value; + +- (void)addPartnerParameter:(nonnull NSString *)key value:(nonnull NSString *)value; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Adjust/ADJSubscription.m b/Adjust/ADJSubscription.m new file mode 100644 index 000000000..42e01f754 --- /dev/null +++ b/Adjust/ADJSubscription.m @@ -0,0 +1,135 @@ +// +// ADJSubscription.m +// Adjust +// +// Created by Uglješa Erceg on 16.04.20. +// Copyright © 2020 adjust GmbH. All rights reserved. +// + +#import "ADJUtil.h" +#import "ADJSubscription.h" +#import "ADJAdjustFactory.h" + +@interface ADJSubscription() + +@property (nonatomic, weak) id logger; + +@property (nonatomic, strong) NSMutableDictionary *mutableCallbackParameters; + +@property (nonatomic, strong) NSMutableDictionary *mutablePartnerParameters; + +@end + +@implementation ADJSubscription + +- (nullable id)initWithRevenue:(double)revenue + currency:(nonnull NSString *)currency + transactionDate:(double)transactionDate + transactionId:(nonnull NSString *)transactionId + andReceipt:(nonnull NSData *)receipt { + self = [super init]; + if (self == nil) { + return nil; + } + + _revenue = [NSNumber numberWithDouble:revenue]; + _currency = currency; + _transactionDate = [NSNumber numberWithDouble:transactionDate]; + _transactionId = transactionId; + _receipt = receipt; + _billingStore = @"iOS"; + + self.logger = ADJAdjustFactory.logger; + + if (![self isValid]) { + return nil; + } + + return self; +} + +- (void)addCallbackParameter:(NSString *)key value:(NSString *)value { + if (![ADJUtil isValidParameter:key + attributeType:@"key" + parameterName:@"Callback"]) { + return; + } + if (![ADJUtil isValidParameter:value + attributeType:@"value" + parameterName:@"Callback"]) { + return; + } + + if (self.mutableCallbackParameters == nil) { + self.mutableCallbackParameters = [[NSMutableDictionary alloc] init]; + } + + if ([self.mutableCallbackParameters objectForKey:key]) { + [self.logger warn:@"key %@ was overwritten", key]; + } + + [self.mutableCallbackParameters setObject:value forKey:key]; +} + +- (void)addPartnerParameter:(NSString *)key value:(NSString *)value { + if (![ADJUtil isValidParameter:key + attributeType:@"key" + parameterName:@"Partner"]) { + return; + } + if (![ADJUtil isValidParameter:value + attributeType:@"value" + parameterName:@"Partner"]) { + return; + } + + if (self.mutablePartnerParameters == nil) { + self.mutablePartnerParameters = [[NSMutableDictionary alloc] init]; + } + + if ([self.mutablePartnerParameters objectForKey:key]) { + [self.logger warn:@"key %@ was overwritten", key]; + } + + [self.mutablePartnerParameters setObject:value forKey:key]; +} + +- (BOOL)isValid { + if (_revenue == nil) { + return NO; + } + if (_currency == nil) { + return NO; + } + if (_transactionDate == nil) { + return NO; + } + if (_transactionId == nil) { + return NO; + } + if (_receipt == nil) { + return NO; + } + if (_billingStore == nil) { + return NO; + } + + return YES; +} + +- (id)copyWithZone:(NSZone *)zone { + ADJSubscription *copy = [[[self class] allocWithZone:zone] init]; + if (copy) { + copy->_revenue = [self.revenue copyWithZone:zone]; + copy->_currency = [self.currency copyWithZone:zone]; + copy->_transactionDate = [self.receipt copyWithZone:zone]; + copy->_transactionId = [self.transactionId copyWithZone:zone]; + copy->_receipt = [self.receipt copyWithZone:zone]; + copy->_billingStore = [self.receipt copyWithZone:zone]; + copy.mutableCallbackParameters = [self.mutableCallbackParameters copyWithZone:zone]; + copy.mutablePartnerParameters = [self.mutablePartnerParameters copyWithZone:zone]; + } + return copy; +} + +@end diff --git a/Adjust/Adjust.h b/Adjust/Adjust.h index 6e9c5ad79..c6c55a5f6 100644 --- a/Adjust/Adjust.h +++ b/Adjust/Adjust.h @@ -10,13 +10,16 @@ #import "ADJEvent.h" #import "ADJConfig.h" #import "ADJAttribution.h" +#import "ADJSubscription.h" @interface AdjustTestOptions : NSObject @property (nonatomic, copy, nullable) NSString *baseUrl; @property (nonatomic, copy, nullable) NSString *gdprUrl; +@property (nonatomic, copy, nullable) NSString *subscriptionUrl; @property (nonatomic, copy, nullable) NSString *basePath; @property (nonatomic, copy, nullable) NSString *gdprPath; +@property (nonatomic, copy, nullable) NSString *subscriptionPath; @property (nonatomic, copy, nullable) NSNumber *timerIntervalInMilliseconds; @property (nonatomic, copy, nullable) NSNumber *timerStartInMilliseconds; @property (nonatomic, copy, nullable) NSNumber *sessionIntervalInMilliseconds; @@ -266,6 +269,13 @@ extern NSString * __nonnull const ADJAdRevenueSourceTapdaq; */ + (void)disableThirdPartySharing; +/** + * @brief Track subscription. + * + * @param subscription Subscription object. + */ ++ (void)trackSubscription:(nonnull ADJSubscription *)subscription; + /** * Obtain singleton Adjust object. */ @@ -311,6 +321,8 @@ extern NSString * __nonnull const ADJAdRevenueSourceTapdaq; - (void)trackAdRevenue:(nonnull NSString *)source payload:(nonnull NSData *)payload; +- (void)trackSubscription:(nonnull ADJSubscription *)subscription; + - (BOOL)isEnabled; - (nullable NSString *)adid; diff --git a/Adjust/Adjust.m b/Adjust/Adjust.m index 228d5615f..836836f96 100644 --- a/Adjust/Adjust.m +++ b/Adjust/Adjust.m @@ -227,6 +227,10 @@ + (void)disableThirdPartySharing { } } ++ (void)trackSubscription:(nonnull ADJSubscription *)subscription { + [[Adjust getInstance] trackSubscription:subscription]; +} + + (ADJAttribution *)attribution { @synchronized (self) { return [[Adjust getInstance] attribution]; @@ -480,6 +484,14 @@ - (void)disableThirdPartySharing { [self.activityHandler disableThirdPartySharing]; } +- (void)trackSubscription:(ADJSubscription *)subscription { + if (![self checkActivityHandler]) { + return; + } + + [self.activityHandler trackSubscription:subscription]; +} + - (ADJAttribution *)attribution { if (![self checkActivityHandler]) { return nil; @@ -517,12 +529,18 @@ - (void)setTestOptions:(AdjustTestOptions *)testOptions { if (testOptions.gdprPath != nil) { self.savedPreLaunch.gdprPath = testOptions.gdprPath; } + if (testOptions.subscriptionPath != nil) { + self.savedPreLaunch.subscriptionPath = testOptions.subscriptionPath; + } if (testOptions.baseUrl != nil) { [ADJAdjustFactory setBaseUrl:testOptions.baseUrl]; } if (testOptions.gdprUrl != nil) { [ADJAdjustFactory setGdprUrl:testOptions.gdprUrl]; } + if (testOptions.subscriptionUrl != nil) { + [ADJAdjustFactory setSubscriptionUrl:testOptions.subscriptionUrl]; + } if (testOptions.timerIntervalInMilliseconds != nil) { NSTimeInterval timerIntervalInSeconds = [testOptions.timerIntervalInMilliseconds intValue] / 1000.0; [ADJAdjustFactory setTimerInterval:timerIntervalInSeconds]; diff --git a/AdjustSdk/AdjustSdk.h b/AdjustSdk/AdjustSdk.h index 405e288ec..7004b4f6a 100644 --- a/AdjustSdk/AdjustSdk.h +++ b/AdjustSdk/AdjustSdk.h @@ -21,6 +21,7 @@ FOUNDATION_EXPORT const unsigned char AdjustSdkVersionString[]; #import #import #import +#import #import #import #import diff --git a/AdjustSdkIm/AdjustSdkIm.h b/AdjustSdkIm/AdjustSdkIm.h index c0d84c2a3..38b59b571 100644 --- a/AdjustSdkIm/AdjustSdkIm.h +++ b/AdjustSdkIm/AdjustSdkIm.h @@ -21,6 +21,7 @@ FOUNDATION_EXPORT const unsigned char AdjustSdkImVersionString[]; #import #import #import +#import #import #import #import diff --git a/AdjustSdkTv/AdjustSdkTv.h b/AdjustSdkTv/AdjustSdkTv.h index bf083fa5a..31947ac54 100644 --- a/AdjustSdkTv/AdjustSdkTv.h +++ b/AdjustSdkTv/AdjustSdkTv.h @@ -21,6 +21,7 @@ FOUNDATION_EXPORT const unsigned char AdjustSdkTvVersionString[]; #import #import #import +#import #import #import #import diff --git a/AdjustSdkWebBridge/AdjustSdkWebBridge.h b/AdjustSdkWebBridge/AdjustSdkWebBridge.h index ccebc3f81..123b03d18 100644 --- a/AdjustSdkWebBridge/AdjustSdkWebBridge.h +++ b/AdjustSdkWebBridge/AdjustSdkWebBridge.h @@ -22,6 +22,7 @@ FOUNDATION_EXPORT const unsigned char AdjustSdkWebBridgeVersionString[]; #import #import #import +#import #import #import #import diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp.xcodeproj/project.pbxproj b/AdjustTests/AdjustTestApp/AdjustTestApp.xcodeproj/project.pbxproj index fff02e305..dc20b90fb 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp.xcodeproj/project.pbxproj +++ b/AdjustTests/AdjustTestApp/AdjustTestApp.xcodeproj/project.pbxproj @@ -71,6 +71,7 @@ 9D1D8E9E219246E50088E3CF /* iAd.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D1D8E9D219246E50088E3CF /* iAd.framework */; }; 9D1D8EA0219246EA0088E3CF /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D1D8E9F219246EA0088E3CF /* AdSupport.framework */; }; 9D1D8EA2219246EF0088E3CF /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D1D8EA1219246EF0088E3CF /* CoreTelephony.framework */; }; + 9D2F24082447DDCB00B7CA90 /* ADJSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2F24072447DDCA00B7CA90 /* ADJSubscription.m */; }; 9D75AFDB210217FF0079A36C /* ATAAdjustDelegateDeferredDeeplink.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D75AFDA210217FF0079A36C /* ATAAdjustDelegateDeferredDeeplink.m */; }; /* End PBXBuildFile section */ @@ -203,6 +204,8 @@ 9D1D8E9D219246E50088E3CF /* iAd.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = iAd.framework; path = System/Library/Frameworks/iAd.framework; sourceTree = SDKROOT; }; 9D1D8E9F219246EA0088E3CF /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; 9D1D8EA1219246EF0088E3CF /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; }; + 9D2F24062447DDCA00B7CA90 /* ADJSubscription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSubscription.h; sourceTree = ""; }; + 9D2F24072447DDCA00B7CA90 /* ADJSubscription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSubscription.m; sourceTree = ""; }; 9D75AFD9210217FF0079A36C /* ATAAdjustDelegateDeferredDeeplink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ATAAdjustDelegateDeferredDeeplink.h; sourceTree = ""; }; 9D75AFDA210217FF0079A36C /* ATAAdjustDelegateDeferredDeeplink.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ATAAdjustDelegateDeferredDeeplink.m; sourceTree = ""; }; /* End PBXFileReference section */ @@ -324,6 +327,8 @@ 6F3A5E6B2018CE14000AACD0 /* ADJTimerCycle.h */, 6F3A5E6C2018CE14000AACD0 /* ADJActivityHandler.m */, 6F3A5E6D2018CE14000AACD0 /* ADJReachability.m */, + 9D2F24062447DDCA00B7CA90 /* ADJSubscription.h */, + 9D2F24072447DDCA00B7CA90 /* ADJSubscription.m */, ); name = Adjust; path = ../../../Adjust; @@ -542,6 +547,7 @@ 6F3A5E872018CE14000AACD0 /* ADJActivityPackage.m in Sources */, 6FFCFE71200797D100467F01 /* ATAAdjustDelegateEventSuccess.m in Sources */, 6F3A5E6F2018CE14000AACD0 /* ADJTimerOnce.m in Sources */, + 9D2F24082447DDCB00B7CA90 /* ADJSubscription.m in Sources */, 6FFCFE6F200797D100467F01 /* ATAAdjustDelegateSessionFailure.m in Sources */, 6F3A5E7D2018CE14000AACD0 /* ADJBackoffStrategy.m in Sources */, 6F3A5E8F2018CE14000AACD0 /* ADJReachability.m in Sources */, diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m index 3fb6de374..c43b14b45 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m @@ -22,6 +22,7 @@ @interface ATAAdjustCommandExecutor () @property (nonatomic, copy) NSString *basePath; @property (nonatomic, copy) NSString *gdprPath; +@property (nonatomic, copy) NSString *subscriptionPath; @property (nonatomic, strong) NSMutableDictionary *savedConfigs; @property (nonatomic, strong) NSMutableDictionary *savedEvents; @property (nonatomic, strong) NSObject *adjustDelegate; @@ -42,6 +43,7 @@ - (id)init { self.adjustDelegate = nil; self.basePath = nil; self.gdprPath = nil; + self.subscriptionPath = nil; return self; } @@ -100,10 +102,12 @@ - (void)testOptions:(NSDictionary *)parameters { AdjustTestOptions *testOptions = [[AdjustTestOptions alloc] init]; testOptions.baseUrl = baseUrl; testOptions.gdprUrl = gdprUrl; + testOptions.subscriptionUrl = subscriptionUrl; if ([parameters objectForKey:@"basePath"]) { self.basePath = [parameters objectForKey:@"basePath"][0]; self.gdprPath = [parameters objectForKey:@"basePath"][0]; + self.subscriptionPath = [parameters objectForKey:@"basePath"][0]; } if ([parameters objectForKey:@"timerInterval"]) { NSString *timerIntervalMilliS = [parameters objectForKey:@"timerInterval"][0]; @@ -157,6 +161,7 @@ - (void)testOptions:(NSDictionary *)parameters { testOptions.teardown = YES; testOptions.basePath = self.basePath; testOptions.gdprPath = self.gdprPath; + testOptions.subscriptionPath = self.subscriptionPath; } if ([teardownOption isEqualToString:@"deleteState"]) { testOptions.deleteState = YES; @@ -174,6 +179,7 @@ - (void)testOptions:(NSDictionary *)parameters { testOptions.teardown = YES; testOptions.basePath = nil; testOptions.gdprPath = nil; + testOptions.subscriptionPath = nil; } if ([teardownOption isEqualToString:@"test"]) { self.savedConfigs = nil; @@ -181,6 +187,7 @@ - (void)testOptions:(NSDictionary *)parameters { self.adjustDelegate = nil; self.basePath = nil; self.gdprPath = nil; + self.subscriptionPath = nil; testOptions.timerIntervalInMilliseconds = [NSNumber numberWithInt:-1000]; testOptions.timerStartInMilliseconds = [NSNumber numberWithInt:-1000]; testOptions.sessionIntervalInMilliseconds = [NSNumber numberWithInt:-1000]; diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.h b/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.h index 08e568f54..8dcedac10 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.h +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.h @@ -10,6 +10,7 @@ static NSString * baseUrl = @"http://127.0.0.1:8080"; static NSString * gdprUrl = @"http://127.0.0.1:8080"; +static NSString * subscriptionUrl = @"http://127.0.0.1:8080"; static NSString * controlUrl = @"ws://127.0.0.1:1987"; @interface ViewController : UIViewController diff --git a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.pbxproj b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.pbxproj index 18beec1e0..d3e84d6ae 100644 --- a/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.pbxproj +++ b/examples/AdjustExample-FbPixel/AdjustExample-FbPixel.xcodeproj/project.pbxproj @@ -46,6 +46,7 @@ 9D0F16CA2193F96F00F5140E /* ADJUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D0F169E2193F96F00F5140E /* ADJUserDefaults.m */; }; 9D0F16CC2193F96F00F5140E /* ADJActivityHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D0F16A42193F96F00F5140E /* ADJActivityHandler.m */; }; 9D0F16CD2193F96F00F5140E /* ADJReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D0F16A52193F96F00F5140E /* ADJReachability.m */; }; + 9D2F241D2447DE5A00B7CA90 /* ADJSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2F241B2447DE5A00B7CA90 /* ADJSubscription.m */; }; 9D9D1533212EB3920081445E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D9D1532212EB3920081445E /* AppDelegate.m */; }; 9D9D1539212EB3920081445E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9D9D1537212EB3920081445E /* Main.storyboard */; }; 9D9D153B212EB3940081445E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9D9D153A212EB3940081445E /* Assets.xcassets */; }; @@ -139,6 +140,8 @@ 9D0F16A32193F96F00F5140E /* ADJTimerCycle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJTimerCycle.h; sourceTree = ""; }; 9D0F16A42193F96F00F5140E /* ADJActivityHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJActivityHandler.m; sourceTree = ""; }; 9D0F16A52193F96F00F5140E /* ADJReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJReachability.m; sourceTree = ""; }; + 9D2F241B2447DE5A00B7CA90 /* ADJSubscription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSubscription.m; sourceTree = ""; }; + 9D2F241C2447DE5A00B7CA90 /* ADJSubscription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSubscription.h; sourceTree = ""; }; 9D9D152E212EB3920081445E /* AdjustExample-FbPixel.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "AdjustExample-FbPixel.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 9D9D1531212EB3920081445E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 9D9D1532212EB3920081445E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -273,6 +276,8 @@ 9D0F16A32193F96F00F5140E /* ADJTimerCycle.h */, 9D0F16A42193F96F00F5140E /* ADJActivityHandler.m */, 9D0F16A52193F96F00F5140E /* ADJReachability.m */, + 9D2F241C2447DE5A00B7CA90 /* ADJSubscription.h */, + 9D2F241B2447DE5A00B7CA90 /* ADJSubscription.m */, ); name = Adjust; path = ../../../../Adjust; @@ -441,6 +446,7 @@ 9D0F16BE2193F96F00F5140E /* ADJPackageHandler.m in Sources */, 9D0F16B72193F96F00F5140E /* ADJSessionFailure.m in Sources */, 9D0F16C22193F96F00F5140E /* UIDevice+ADJAdditions.m in Sources */, + 9D2F241D2447DE5A00B7CA90 /* ADJSubscription.m in Sources */, 9D0F16B62193F96F00F5140E /* ADJActivityState.m in Sources */, 9D0F16CC2193F96F00F5140E /* ADJActivityHandler.m in Sources */, 9D0F16A72193F96F00F5140E /* WebViewJavascriptBridgeBase.m in Sources */, diff --git a/examples/AdjustExample-ObjC/AdjustExample-ObjC.xcodeproj/project.pbxproj b/examples/AdjustExample-ObjC/AdjustExample-ObjC.xcodeproj/project.pbxproj index 0543794db..1477a31bc 100644 --- a/examples/AdjustExample-ObjC/AdjustExample-ObjC.xcodeproj/project.pbxproj +++ b/examples/AdjustExample-ObjC/AdjustExample-ObjC.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 9639094F1BCBFCF300A2E8A4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9639094D1BCBFCF300A2E8A4 /* LaunchScreen.storyboard */; }; 9639095F1BCBFD3B00A2E8A4 /* iAd.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9639095E1BCBFD3B00A2E8A4 /* iAd.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 963909611BCBFD4200A2E8A4 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 963909601BCBFD4200A2E8A4 /* AdSupport.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 9D2F240B2447DDE100B7CA90 /* ADJSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2F240A2447DDE100B7CA90 /* ADJSubscription.m */; }; 9D449E131E6ED88F00E7E80B /* NSString+ADJAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D449DD21E6ED88F00E7E80B /* NSString+ADJAdditions.m */; }; 9D449E141E6ED88F00E7E80B /* UIDevice+ADJAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D449DD41E6ED88F00E7E80B /* UIDevice+ADJAdditions.m */; }; 9D449E151E6ED88F00E7E80B /* NSData+ADJAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D449DD61E6ED88F00E7E80B /* NSData+ADJAdditions.m */; }; @@ -65,6 +66,8 @@ 9639095E1BCBFD3B00A2E8A4 /* iAd.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = iAd.framework; path = System/Library/Frameworks/iAd.framework; sourceTree = SDKROOT; }; 963909601BCBFD4200A2E8A4 /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; 964E17FC1D50C6250097770B /* SafariServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SafariServices.framework; path = System/Library/Frameworks/SafariServices.framework; sourceTree = SDKROOT; }; + 9D2F24092447DDE100B7CA90 /* ADJSubscription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSubscription.h; sourceTree = ""; }; + 9D2F240A2447DDE100B7CA90 /* ADJSubscription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSubscription.m; sourceTree = ""; }; 9D449DD11E6ED88F00E7E80B /* NSString+ADJAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+ADJAdditions.h"; sourceTree = ""; }; 9D449DD21E6ED88F00E7E80B /* NSString+ADJAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+ADJAdditions.m"; sourceTree = ""; }; 9D449DD31E6ED88F00E7E80B /* UIDevice+ADJAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIDevice+ADJAdditions.h"; sourceTree = ""; }; @@ -271,6 +274,8 @@ 6FCC850A1F2794A300D6A0ED /* ADJReachability.m */, 9DD0E9BC1F457EF800B2A759 /* ADJUserDefaults.h */, 9DD0E9BD1F457EF800B2A759 /* ADJUserDefaults.m */, + 9D2F24092447DDE100B7CA90 /* ADJSubscription.h */, + 9D2F240A2447DDE100B7CA90 /* ADJSubscription.m */, ); name = Adjust; path = ../../../Adjust; @@ -369,6 +374,7 @@ 9D449E201E6ED88F00E7E80B /* ADJUtil.m in Sources */, 9D449E241E6ED88F00E7E80B /* ADJAttribution.m in Sources */, 9DC95F2A1C10515300138E4B /* Constants.m in Sources */, + 9D2F240B2447DDE100B7CA90 /* ADJSubscription.m in Sources */, 963909441BCBFCF300A2E8A4 /* AppDelegate.m in Sources */, 9D449E311E6ED88F00E7E80B /* ADJSessionParameters.m in Sources */, 9D449E171E6ED88F00E7E80B /* ADJActivityHandler.m in Sources */, diff --git a/examples/AdjustExample-Swift/AdjustExample-Swift.xcodeproj/project.pbxproj b/examples/AdjustExample-Swift/AdjustExample-Swift.xcodeproj/project.pbxproj index 72daadca3..f7791b4e5 100644 --- a/examples/AdjustExample-Swift/AdjustExample-Swift.xcodeproj/project.pbxproj +++ b/examples/AdjustExample-Swift/AdjustExample-Swift.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 6FCC850F1F2794C600D6A0ED /* ADJReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FCC850E1F2794BE00D6A0ED /* ADJReachability.m */; }; + 9D2F240E2447DDF600B7CA90 /* ADJSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2F240C2447DDF600B7CA90 /* ADJSubscription.m */; }; 9D449E761E6EDC3D00E7E80B /* ADJActivityHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D449E351E6EDC3D00E7E80B /* ADJActivityHandler.m */; }; 9D449E771E6EDC3D00E7E80B /* ADJActivityKind.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D449E371E6EDC3D00E7E80B /* ADJActivityKind.m */; }; 9D449E781E6EDC3D00E7E80B /* ADJActivityPackage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D449E391E6EDC3D00E7E80B /* ADJActivityPackage.m */; }; @@ -52,6 +53,8 @@ /* Begin PBXFileReference section */ 6FCC850D1F2794BE00D6A0ED /* ADJReachability.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ADJReachability.h; sourceTree = ""; }; 6FCC850E1F2794BE00D6A0ED /* ADJReachability.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ADJReachability.m; sourceTree = ""; }; + 9D2F240C2447DDF600B7CA90 /* ADJSubscription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSubscription.m; sourceTree = ""; }; + 9D2F240D2447DDF600B7CA90 /* ADJSubscription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSubscription.h; sourceTree = ""; }; 9D319B9823054502000E28A6 /* AdjustExample-Swift.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "AdjustExample-Swift.entitlements"; sourceTree = ""; }; 9D449E341E6EDC3D00E7E80B /* ADJActivityHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJActivityHandler.h; sourceTree = ""; }; 9D449E351E6EDC3D00E7E80B /* ADJActivityHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJActivityHandler.m; sourceTree = ""; }; @@ -206,6 +209,8 @@ 6FCC850E1F2794BE00D6A0ED /* ADJReachability.m */, 9DD0E9BF1F45879A00B2A759 /* ADJUserDefaults.h */, 9DD0E9C01F45879A00B2A759 /* ADJUserDefaults.m */, + 9D2F240D2447DDF600B7CA90 /* ADJSubscription.h */, + 9D2F240C2447DDF600B7CA90 /* ADJSubscription.m */, ); name = Adjust; path = ../../../Adjust; @@ -365,6 +370,7 @@ 9D449E841E6EDC3D00E7E80B /* ADJEvent.m in Sources */, 9D449E951E6EDC3D00E7E80B /* ADJUtil.m in Sources */, 9D449E7C1E6EDC3D00E7E80B /* UIDevice+ADJAdditions.m in Sources */, + 9D2F240E2447DDF600B7CA90 /* ADJSubscription.m in Sources */, 9D449E851E6EDC3D00E7E80B /* ADJEventFailure.m in Sources */, 9D449E7B1E6EDC3D00E7E80B /* NSString+ADJAdditions.m in Sources */, 9D449E7D1E6EDC3D00E7E80B /* ADJAdjustFactory.m in Sources */, diff --git a/examples/AdjustExample-WebView/AdjustExample-WebView.xcodeproj/project.pbxproj b/examples/AdjustExample-WebView/AdjustExample-WebView.xcodeproj/project.pbxproj index ccd8d6ae0..09f61ce42 100644 --- a/examples/AdjustExample-WebView/AdjustExample-WebView.xcodeproj/project.pbxproj +++ b/examples/AdjustExample-WebView/AdjustExample-WebView.xcodeproj/project.pbxproj @@ -20,6 +20,7 @@ 9D10833F1CFDDBF50050568B /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9D10833E1CFDDBF50050568B /* Default-568h@2x.png */; }; 9D1083411CFDE2470050568B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D1083401CFDE2470050568B /* UIKit.framework */; }; 9D1083431CFDE29A0050568B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D1083421CFDE29A0050568B /* Foundation.framework */; }; + 9D2F24112447DE0A00B7CA90 /* ADJSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2F24102447DE0A00B7CA90 /* ADJSubscription.m */; }; 9D449EDA1E6EDD4100E7E80B /* ADJActivityHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D449E991E6EDD4100E7E80B /* ADJActivityHandler.m */; }; 9D449EDB1E6EDD4100E7E80B /* ADJActivityKind.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D449E9B1E6EDD4100E7E80B /* ADJActivityKind.m */; }; 9D449EDC1E6EDD4100E7E80B /* ADJActivityPackage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D449E9D1E6EDD4100E7E80B /* ADJActivityPackage.m */; }; @@ -78,6 +79,8 @@ 9D10833E1CFDDBF50050568B /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 9D1083401CFDE2470050568B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 9D1083421CFDE29A0050568B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 9D2F240F2447DE0A00B7CA90 /* ADJSubscription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSubscription.h; sourceTree = ""; }; + 9D2F24102447DE0A00B7CA90 /* ADJSubscription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSubscription.m; sourceTree = ""; }; 9D449E981E6EDD4100E7E80B /* ADJActivityHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJActivityHandler.h; sourceTree = ""; }; 9D449E991E6EDD4100E7E80B /* ADJActivityHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJActivityHandler.m; sourceTree = ""; }; 9D449E9A1E6EDD4100E7E80B /* ADJActivityKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJActivityKind.h; sourceTree = ""; }; @@ -293,6 +296,8 @@ 6FCC85111F2794D600D6A0ED /* ADJReachability.m */, 9DD0E9C21F4587C600B2A759 /* ADJUserDefaults.h */, 9DD0E9C31F4587C600B2A759 /* ADJUserDefaults.m */, + 9D2F240F2447DE0A00B7CA90 /* ADJSubscription.h */, + 9D2F24102447DE0A00B7CA90 /* ADJSubscription.m */, ); name = Adjust; path = ../../../Adjust; @@ -448,6 +453,7 @@ 9D449EF01E6EDD4100E7E80B /* ADJResponseData.m in Sources */, 9D1082A91CFDAF8E0050568B /* main.m in Sources */, 9D449EF91E6EDD4100E7E80B /* ADJUtil.m in Sources */, + 9D2F24112447DE0A00B7CA90 /* ADJSubscription.m in Sources */, 9D449EEE1E6EDD4100E7E80B /* ADJPackageHandler.m in Sources */, 9D449EE91E6EDD4100E7E80B /* ADJEventFailure.m in Sources */, 9D449EF41E6EDD4100E7E80B /* ADJSessionSuccess.m in Sources */, diff --git a/examples/AdjustExample-iMessage/AdjustExample-iMessage.xcodeproj/project.pbxproj b/examples/AdjustExample-iMessage/AdjustExample-iMessage.xcodeproj/project.pbxproj index 6c88f2ed5..14d923840 100644 --- a/examples/AdjustExample-iMessage/AdjustExample-iMessage.xcodeproj/project.pbxproj +++ b/examples/AdjustExample-iMessage/AdjustExample-iMessage.xcodeproj/project.pbxproj @@ -46,6 +46,7 @@ 9D01687420FF88F60029CFFF /* ADJUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D01684E20FF88F60029CFFF /* ADJUserDefaults.m */; }; 9D01687620FF88F60029CFFF /* ADJActivityHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D01685420FF88F60029CFFF /* ADJActivityHandler.m */; }; 9D01687720FF88F60029CFFF /* ADJReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D01685520FF88F60029CFFF /* ADJReachability.m */; }; + 9D2F241A2447DE4700B7CA90 /* ADJSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2F24192447DE4700B7CA90 /* ADJSubscription.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -149,6 +150,8 @@ 9D01685320FF88F60029CFFF /* ADJTimerCycle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJTimerCycle.h; sourceTree = ""; }; 9D01685420FF88F60029CFFF /* ADJActivityHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJActivityHandler.m; sourceTree = ""; }; 9D01685520FF88F60029CFFF /* ADJReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJReachability.m; sourceTree = ""; }; + 9D2F24182447DE4700B7CA90 /* ADJSubscription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSubscription.h; sourceTree = ""; }; + 9D2F24192447DE4700B7CA90 /* ADJSubscription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSubscription.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -276,6 +279,8 @@ 9D01685320FF88F60029CFFF /* ADJTimerCycle.h */, 9D01685420FF88F60029CFFF /* ADJActivityHandler.m */, 9D01685520FF88F60029CFFF /* ADJReachability.m */, + 9D2F24182447DE4700B7CA90 /* ADJSubscription.h */, + 9D2F24192447DE4700B7CA90 /* ADJSubscription.m */, ); name = Adjust; path = ../../../Adjust; @@ -423,6 +428,7 @@ 9D01686B20FF88F60029CFFF /* NSData+ADJAdditions.m in Sources */, 9D01685C20FF88F60029CFFF /* ADJEvent.m in Sources */, 9D01687320FF88F60029CFFF /* ADJPackageBuilder.m in Sources */, + 9D2F241A2447DE4700B7CA90 /* ADJSubscription.m in Sources */, 9D01685620FF88F60029CFFF /* ADJDeviceInfo.m in Sources */, 9D01686620FF88F60029CFFF /* Adjust.m in Sources */, 9D01685D20FF88F60029CFFF /* ADJSessionSuccess.m in Sources */, diff --git a/examples/AdjustExample-iWatch/AdjustExample-iWatch.xcodeproj/project.pbxproj b/examples/AdjustExample-iWatch/AdjustExample-iWatch.xcodeproj/project.pbxproj index c09d332ec..9a61fa748 100644 --- a/examples/AdjustExample-iWatch/AdjustExample-iWatch.xcodeproj/project.pbxproj +++ b/examples/AdjustExample-iWatch/AdjustExample-iWatch.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 6FCC85181F27950000D6A0ED /* ADJReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FCC85171F2794F800D6A0ED /* ADJReachability.m */; }; + 9D2F24172447DE3400B7CA90 /* ADJSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2F24152447DE3400B7CA90 /* ADJSubscription.m */; }; 9D449FA31E6EE72000E7E80B /* ADJActivityHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D449F621E6EE72000E7E80B /* ADJActivityHandler.m */; }; 9D449FA41E6EE72000E7E80B /* ADJActivityKind.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D449F641E6EE72000E7E80B /* ADJActivityKind.m */; }; 9D449FA51E6EE72000E7E80B /* ADJActivityPackage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D449F661E6EE72000E7E80B /* ADJActivityPackage.m */; }; @@ -107,6 +108,8 @@ /* Begin PBXFileReference section */ 6FCC85161F2794F800D6A0ED /* ADJReachability.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ADJReachability.h; sourceTree = ""; }; 6FCC85171F2794F800D6A0ED /* ADJReachability.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ADJReachability.m; sourceTree = ""; }; + 9D2F24152447DE3400B7CA90 /* ADJSubscription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSubscription.m; sourceTree = ""; }; + 9D2F24162447DE3400B7CA90 /* ADJSubscription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSubscription.h; sourceTree = ""; }; 9D449F611E6EE72000E7E80B /* ADJActivityHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJActivityHandler.h; sourceTree = ""; }; 9D449F621E6EE72000E7E80B /* ADJActivityHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJActivityHandler.m; sourceTree = ""; }; 9D449F631E6EE72000E7E80B /* ADJActivityKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJActivityKind.h; sourceTree = ""; }; @@ -290,6 +293,8 @@ 6FCC85171F2794F800D6A0ED /* ADJReachability.m */, 9DD0E9C51F45949600B2A759 /* ADJUserDefaults.h */, 9DD0E9C61F45949600B2A759 /* ADJUserDefaults.m */, + 9D2F24162447DE3400B7CA90 /* ADJSubscription.h */, + 9D2F24152447DE3400B7CA90 /* ADJSubscription.m */, ); name = Adjust; path = ../../../Adjust; @@ -555,6 +560,7 @@ 9DF7AC191CB4FEDB00D3591F /* main.m in Sources */, 9D449FB41E6EE72000E7E80B /* ADJKeychain.m in Sources */, 9D449FA91E6EE72000E7E80B /* UIDevice+ADJAdditions.m in Sources */, + 9D2F24172447DE3400B7CA90 /* ADJSubscription.m in Sources */, 9D449FBE1E6EE72000E7E80B /* ADJSystemProfile.m in Sources */, 9D449FAD1E6EE72000E7E80B /* ADJBackoffStrategy.m in Sources */, 9D449FBC1E6EE72000E7E80B /* ADJSessionParameters.m in Sources */, diff --git a/examples/AdjustExample-tvOS/AdjustExample-tvOS.xcodeproj/project.pbxproj b/examples/AdjustExample-tvOS/AdjustExample-tvOS.xcodeproj/project.pbxproj index 007a76f48..6972902d0 100644 --- a/examples/AdjustExample-tvOS/AdjustExample-tvOS.xcodeproj/project.pbxproj +++ b/examples/AdjustExample-tvOS/AdjustExample-tvOS.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 963909C01BCC0D8300A2E8A4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 963909BE1BCC0D8300A2E8A4 /* Main.storyboard */; }; 963909C21BCC0D8300A2E8A4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 963909C11BCC0D8300A2E8A4 /* Assets.xcassets */; }; 963909D01BCC0DA600A2E8A4 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 963909CF1BCC0DA600A2E8A4 /* AdSupport.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 9D2F24142447DE1F00B7CA90 /* ADJSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D2F24122447DE1E00B7CA90 /* ADJSubscription.m */; }; 9D449F3F1E6EE6C500E7E80B /* ADJActivityHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D449EFE1E6EE6C500E7E80B /* ADJActivityHandler.m */; }; 9D449F401E6EE6C500E7E80B /* ADJActivityKind.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D449F001E6EE6C500E7E80B /* ADJActivityKind.m */; }; 9D449F411E6EE6C500E7E80B /* ADJActivityPackage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D449F021E6EE6C500E7E80B /* ADJActivityPackage.m */; }; @@ -75,6 +76,8 @@ 963909C11BCC0D8300A2E8A4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 963909C31BCC0D8300A2E8A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 963909CF1BCC0DA600A2E8A4 /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; + 9D2F24122447DE1E00B7CA90 /* ADJSubscription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJSubscription.m; sourceTree = ""; }; + 9D2F24132447DE1F00B7CA90 /* ADJSubscription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJSubscription.h; sourceTree = ""; }; 9D449EFD1E6EE6C400E7E80B /* ADJActivityHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJActivityHandler.h; sourceTree = ""; }; 9D449EFE1E6EE6C500E7E80B /* ADJActivityHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ADJActivityHandler.m; sourceTree = ""; }; 9D449EFF1E6EE6C500E7E80B /* ADJActivityKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ADJActivityKind.h; sourceTree = ""; }; @@ -262,6 +265,8 @@ 6FCC85131F2794E800D6A0ED /* ADJReachability.m */, 9DD0E9CD1F459ECE00B2A759 /* ADJUserDefaults.h */, 9DD0E9CE1F459ECE00B2A759 /* ADJUserDefaults.m */, + 9D2F24132447DE1F00B7CA90 /* ADJSubscription.h */, + 9D2F24122447DE1E00B7CA90 /* ADJSubscription.m */, ); name = Adjust; path = ../../../Adjust; @@ -371,6 +376,7 @@ 9D449F4F1E6EE6C500E7E80B /* ADJEventSuccess.m in Sources */, 9D449F5B1E6EE6C500E7E80B /* ADJTimerCycle.m in Sources */, 9D449F471E6EE6C500E7E80B /* ADJAttribution.m in Sources */, + 9D2F24142447DE1F00B7CA90 /* ADJSubscription.m in Sources */, 9D449F421E6EE6C500E7E80B /* ADJActivityState.m in Sources */, 9DC95F2F1C10596500138E4B /* Constants.m in Sources */, 963909BD1BCC0D8300A2E8A4 /* ViewControllertvOS.m in Sources */, From 8ec63c72171f1d5f7acb3bfe841470857d80bc0b Mon Sep 17 00:00:00 2001 From: uerceg Date: Thu, 16 Apr 2020 03:02:12 +0200 Subject: [PATCH 02/35] Use subscription activity kind for package --- Adjust/ADJPackageBuilder.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adjust/ADJPackageBuilder.m b/Adjust/ADJPackageBuilder.m index 6c67236be..cb96619b8 100644 --- a/Adjust/ADJPackageBuilder.m +++ b/Adjust/ADJPackageBuilder.m @@ -168,7 +168,7 @@ - (ADJActivityPackage *)buildSubscriptionPackage:(ADJSubscription *)subscription NSMutableDictionary *parameters = [self getSubscriptionParameters:isInDelay forSubscriptionPackage:subscription]; ADJActivityPackage *subscriptionPackage = [self defaultActivityPackage]; subscriptionPackage.path = @"/v2/purchase"; - subscriptionPackage.activityKind = ADJActivityKindEvent; + subscriptionPackage.activityKind = ADJActivityKindSubscription; subscriptionPackage.suffix = @""; subscriptionPackage.parameters = parameters; From 43c8f2ae6ad282864c27d970979b03bd2ff7c5de Mon Sep 17 00:00:00 2001 From: uerceg Date: Thu, 16 Apr 2020 03:03:29 +0200 Subject: [PATCH 03/35] Fix activity kind for subscription package in request handler --- Adjust/ADJRequestHandler.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adjust/ADJRequestHandler.m b/Adjust/ADJRequestHandler.m index 260c7b466..dfa56fa5a 100644 --- a/Adjust/ADJRequestHandler.m +++ b/Adjust/ADJRequestHandler.m @@ -92,7 +92,7 @@ - (void)sendI:(ADJRequestHandler *)selfI activityPackage:(ADJActivityPackage *)a } else { url = [NSURL URLWithString:gdprUrl]; } - } else if (activityPackage.activityKind == ADJActivityKindGdpr) { + } else if (activityPackage.activityKind == ADJActivityKindSubscription) { NSString *subscriptionUrl = [ADJAdjustFactory subscriptionUrl]; if (selfI.subscriptionPath != nil) { url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", subscriptionUrl, selfI.subscriptionPath]]; From 464c993079429fa647c02821b45e635e2a29e19e Mon Sep 17 00:00:00 2001 From: uerceg Date: Thu, 16 Apr 2020 03:09:16 +0200 Subject: [PATCH 04/35] Track subscription in example app --- .../AdjustExample-ObjC/ViewControllerObjC.m | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/examples/AdjustExample-ObjC/AdjustExample-ObjC/ViewControllerObjC.m b/examples/AdjustExample-ObjC/AdjustExample-ObjC/ViewControllerObjC.m index 938f4778f..57e1d6a74 100644 --- a/examples/AdjustExample-ObjC/AdjustExample-ObjC/ViewControllerObjC.m +++ b/examples/AdjustExample-ObjC/AdjustExample-ObjC/ViewControllerObjC.m @@ -35,12 +35,18 @@ - (void)didReceiveMemoryWarning { } - (IBAction)clickTrackSimpleEvent:(UIButton *)sender { - ADJEvent *event = [ADJEvent eventWithEventToken:kEventToken1]; - - // Attach callback ID to event. - [event setCallbackId:@"RandomCallbackId"]; - - [Adjust trackEvent:event]; + ADJSubscription *subscription = [[ADJSubscription alloc] + initWithRevenue:6.66 + currency:@"CAD" + transactionDate:1234567890 + transactionId:@"random-transaction-id" + andReceipt:[@"random-receipt" dataUsingEncoding:NSUTF8StringEncoding]]; + [subscription addCallbackParameter:@"foo" value:@"bar"]; + [subscription addCallbackParameter:@"key" value:@"value"]; + [subscription addPartnerParameter:@"foo" value:@"bar"]; + [subscription addPartnerParameter:@"key" value:@"value"]; + + [Adjust trackSubscription:subscription]; } - (IBAction)clickTrackRevenueEvent:(UIButton *)sender { From 2049e13da921e12f8270edb3d58b949c5ad87a3b Mon Sep 17 00:00:00 2001 From: uerceg Date: Tue, 21 Apr 2020 11:10:07 +0200 Subject: [PATCH 05/35] Set subscription endpoint URL --- Adjust/ADJAdjustFactory.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Adjust/ADJAdjustFactory.m b/Adjust/ADJAdjustFactory.m index e58e0f0f2..c14c248c7 100644 --- a/Adjust/ADJAdjustFactory.m +++ b/Adjust/ADJAdjustFactory.m @@ -30,8 +30,8 @@ static NSString * internalBaseUrl = @"https://app.adjust.com"; static NSString * const kGdprUrl = @"https://gdpr.adjust.com"; static NSString * internalGdprUrl = @"https://gdpr.adjust.com"; -static NSString * const kSubscriptionUrl = @"https://staging-api-sub.adjust.com"; -static NSString * internalSubscriptionUrl = @"https://staging-api-sub.adjust.com"; +static NSString * const kSubscriptionUrl = @"https://subscription.adjust.com"; +static NSString * internalSubscriptionUrl = @"https://subscription.adjust.com"; @implementation ADJAdjustFactory From 84a93ae8cbab99f7623f6758ecf6273e3f4b0aaf Mon Sep 17 00:00:00 2001 From: uerceg Date: Wed, 22 Apr 2020 15:55:57 +0200 Subject: [PATCH 06/35] Synchronise public API methods access --- .../AdjustExample-ObjC/ViewControllerObjC.m | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/examples/AdjustExample-ObjC/AdjustExample-ObjC/ViewControllerObjC.m b/examples/AdjustExample-ObjC/AdjustExample-ObjC/ViewControllerObjC.m index 57e1d6a74..ac3a27650 100644 --- a/examples/AdjustExample-ObjC/AdjustExample-ObjC/ViewControllerObjC.m +++ b/examples/AdjustExample-ObjC/AdjustExample-ObjC/ViewControllerObjC.m @@ -50,12 +50,27 @@ - (IBAction)clickTrackSimpleEvent:(UIButton *)sender { } - (IBAction)clickTrackRevenueEvent:(UIButton *)sender { - ADJEvent *event = [ADJEvent eventWithEventToken:kEventToken2]; - - // Add revenue 1 cent of an EURO. - [event setRevenue:0.01 currency:@"EUR"]; - - [Adjust trackEvent:event]; + NSURL __block *url = [NSURL URLWithString:@"random-url"]; +// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ +// // Add revenue 1 cent of an EURO. +// for (int i = 0; i < 30000; i += 1) { +// [event setRevenue:i currency:@"EUR"]; +// [event setCallbackId:[NSString stringWithFormat:@"%@%d", @"random-id", i]]; +// [event addCallbackParameter:@"foo" value:[NSString stringWithFormat:@"%@%d", @"bar", i]]; +// [event addCallbackParameter:@"key" value:[NSString stringWithFormat:@"%@%d", @"value", i]]; +// } +// }); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + for (int i = 0; i < 300; i += 1) { + [Adjust appWillOpenUrl:[NSURL URLWithString:[NSString stringWithFormat:@"random-url-%d", i]]]; + } + }); +// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ +// // Add revenue 1 cent of an EURO. +// for (int i = 30000; i < 60000; i += 1) { +// url = [NSURL URLWithString:[NSString stringWithFormat:@"random-url-%d", i]]; +// } +// }); } - (IBAction)clickTrackCallbackEvent:(UIButton *)sender { From d3ea191b5897af81b336683b5a727691e365090e Mon Sep 17 00:00:00 2001 From: uerceg Date: Thu, 23 Apr 2020 02:38:15 +0200 Subject: [PATCH 07/35] Synchronise trackSubscription: method --- Adjust/Adjust.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Adjust/Adjust.m b/Adjust/Adjust.m index 836836f96..873afa13d 100644 --- a/Adjust/Adjust.m +++ b/Adjust/Adjust.m @@ -228,7 +228,9 @@ + (void)disableThirdPartySharing { } + (void)trackSubscription:(nonnull ADJSubscription *)subscription { - [[Adjust getInstance] trackSubscription:subscription]; + @synchronized (self) { + [[Adjust getInstance] trackSubscription:subscription]; + } } + (ADJAttribution *)attribution { From 8fd4ea8ef97f4526016d49bc8c7f6d26157f01c7 Mon Sep 17 00:00:00 2001 From: uerceg Date: Thu, 23 Apr 2020 11:55:41 +0200 Subject: [PATCH 08/35] Reinitialise internalSubscriptionUrl in teardown method --- Adjust/ADJAdjustFactory.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Adjust/ADJAdjustFactory.m b/Adjust/ADJAdjustFactory.m index c14c248c7..70ad0b4d2 100644 --- a/Adjust/ADJAdjustFactory.m +++ b/Adjust/ADJAdjustFactory.m @@ -298,7 +298,7 @@ + (void)teardown:(BOOL)deleteState { internalAttributionHandler = nil; internalSdkClickHandler = nil; - internalSessionInterval = -1; + internalSessionInterval = -1; intervalSubsessionInterval = -1; internalTimerInterval = -1; intervalTimerStart = -1; @@ -308,6 +308,7 @@ + (void)teardown:(BOOL)deleteState { internalMaxDelayStart = -1; internalBaseUrl = kBaseUrl; internalGdprUrl = kGdprUrl; + internalSubscriptionUrl = kSubscriptionUrl; internaliAdFrameworkEnabled = YES; } @end From 8921382855fff32f576f6d7f9542d2d7a7c0e2d6 Mon Sep 17 00:00:00 2001 From: nonelse Date: Thu, 23 Apr 2020 14:50:30 +0200 Subject: [PATCH 09/35] Refac subscription --- Adjust/ADJSubscription.h | 4 ---- Adjust/ADJSubscription.m | 28 ++++++++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Adjust/ADJSubscription.h b/Adjust/ADJSubscription.h index 0e7eea10d..2725f6225 100644 --- a/Adjust/ADJSubscription.h +++ b/Adjust/ADJSubscription.h @@ -8,8 +8,6 @@ #import -NS_ASSUME_NONNULL_BEGIN - @interface ADJSubscription : NSObject @property (nonatomic, copy, readonly, nonnull) NSNumber *revenue; @@ -39,5 +37,3 @@ NS_ASSUME_NONNULL_BEGIN - (void)addPartnerParameter:(nonnull NSString *)key value:(nonnull NSString *)value; @end - -NS_ASSUME_NONNULL_END diff --git a/Adjust/ADJSubscription.m b/Adjust/ADJSubscription.m index 42e01f754..1b57da5b8 100644 --- a/Adjust/ADJSubscription.m +++ b/Adjust/ADJSubscription.m @@ -33,13 +33,13 @@ - (nullable id)initWithRevenue:(double)revenue } _revenue = [NSNumber numberWithDouble:revenue]; - _currency = currency; + _currency = [currency copy]; _transactionDate = [NSNumber numberWithDouble:transactionDate]; - _transactionId = transactionId; - _receipt = receipt; + _transactionId = [transactionId copy]; + _receipt = [receipt copy]; _billingStore = @"iOS"; - self.logger = ADJAdjustFactory.logger; + _logger = ADJAdjustFactory.logger; if (![self isValid]) { return nil; @@ -48,7 +48,9 @@ - (nullable id)initWithRevenue:(double)revenue return self; } -- (void)addCallbackParameter:(NSString *)key value:(NSString *)value { +- (void)addCallbackParameter:(nonnull NSString *)key + value:(nonnull NSString *)value +{ if (![ADJUtil isValidParameter:key attributeType:@"key" parameterName:@"Callback"]) { @@ -71,7 +73,9 @@ - (void)addCallbackParameter:(NSString *)key value:(NSString *)value { [self.mutableCallbackParameters setObject:value forKey:key]; } -- (void)addPartnerParameter:(NSString *)key value:(NSString *)value { +- (void)addPartnerParameter:(nonnull NSString *)key + value:(nonnull NSString *)value +{ if (![ADJUtil isValidParameter:key attributeType:@"key" parameterName:@"Partner"]) { @@ -95,22 +99,22 @@ - (void)addPartnerParameter:(NSString *)key value:(NSString *)value { } - (BOOL)isValid { - if (_revenue == nil) { + if (self.revenue == nil) { return NO; } - if (_currency == nil) { + if (self.currency == nil) { return NO; } - if (_transactionDate == nil) { + if (self.transactionDate == nil) { return NO; } - if (_transactionId == nil) { + if (self.transactionId == nil) { return NO; } - if (_receipt == nil) { + if (self.receipt == nil) { return NO; } - if (_billingStore == nil) { + if (self.billingStore == nil) { return NO; } From 8c6ecff470ed6aa67af0d12921a3872308fb6de8 Mon Sep 17 00:00:00 2001 From: nonelse Date: Thu, 23 Apr 2020 14:50:57 +0200 Subject: [PATCH 10/35] Link read-only subscription parameters with mutable --- Adjust/ADJSubscription.h | 4 ++-- Adjust/ADJSubscription.m | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Adjust/ADJSubscription.h b/Adjust/ADJSubscription.h index 2725f6225..7ff580ac9 100644 --- a/Adjust/ADJSubscription.h +++ b/Adjust/ADJSubscription.h @@ -22,9 +22,9 @@ @property (nonatomic, copy, readonly, nonnull) NSString *billingStore; -@property (nonatomic, readonly, nonnull) NSDictionary *partnerParameters; +@property (nonatomic, copy, readonly, nonnull) NSDictionary *partnerParameters; -@property (nonatomic, readonly, nonnull) NSDictionary *callbackParameters; +@property (nonatomic, copy, readonly, nonnull) NSDictionary *callbackParameters; - (nullable id)initWithRevenue:(double)revenue currency:(nonnull NSString *)currency diff --git a/Adjust/ADJSubscription.m b/Adjust/ADJSubscription.m index 1b57da5b8..59fb160e8 100644 --- a/Adjust/ADJSubscription.m +++ b/Adjust/ADJSubscription.m @@ -121,6 +121,14 @@ - (BOOL)isValid { return YES; } +- (nonnull NSDictionary *)callbackParameters { + return [self.mutableCallbackParameters copy]; +} + +- (nonnull NSDictionary *)partnerParameters { + return [self.mutablePartnerParameters copy]; +} + - (id)copyWithZone:(NSZone *)zone { ADJSubscription *copy = [[[self class] allocWithZone:zone] init]; if (copy) { From d3d3ea3a5c04865ae04f18656500c4129e962146 Mon Sep 17 00:00:00 2001 From: nonelse Date: Thu, 23 Apr 2020 14:51:40 +0200 Subject: [PATCH 11/35] Add syncronized to subscription parameters --- Adjust/ADJSubscription.m | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/Adjust/ADJSubscription.m b/Adjust/ADJSubscription.m index 59fb160e8..fe5820dfb 100644 --- a/Adjust/ADJSubscription.m +++ b/Adjust/ADJSubscription.m @@ -62,15 +62,17 @@ - (void)addCallbackParameter:(nonnull NSString *)key return; } - if (self.mutableCallbackParameters == nil) { - self.mutableCallbackParameters = [[NSMutableDictionary alloc] init]; - } + @synchronized (self) { + if (self.mutableCallbackParameters == nil) { + self.mutableCallbackParameters = [[NSMutableDictionary alloc] init]; + } - if ([self.mutableCallbackParameters objectForKey:key]) { - [self.logger warn:@"key %@ was overwritten", key]; - } + if ([self.mutableCallbackParameters objectForKey:key]) { + [self.logger warn:@"key %@ was overwritten", key]; + } - [self.mutableCallbackParameters setObject:value forKey:key]; + [self.mutableCallbackParameters setObject:value forKey:key]; + } } - (void)addPartnerParameter:(nonnull NSString *)key @@ -87,15 +89,17 @@ - (void)addPartnerParameter:(nonnull NSString *)key return; } - if (self.mutablePartnerParameters == nil) { - self.mutablePartnerParameters = [[NSMutableDictionary alloc] init]; - } + @synchronized (self) { + if (self.mutablePartnerParameters == nil) { + self.mutablePartnerParameters = [[NSMutableDictionary alloc] init]; + } - if ([self.mutablePartnerParameters objectForKey:key]) { - [self.logger warn:@"key %@ was overwritten", key]; - } + if ([self.mutablePartnerParameters objectForKey:key]) { + [self.logger warn:@"key %@ was overwritten", key]; + } - [self.mutablePartnerParameters setObject:value forKey:key]; + [self.mutablePartnerParameters setObject:value forKey:key]; + } } - (BOOL)isValid { From 95877842e01aab175951c2c37a2c19daf9f7153a Mon Sep 17 00:00:00 2001 From: nonelse Date: Thu, 23 Apr 2020 17:11:14 +0200 Subject: [PATCH 12/35] Fix typo --- Adjust/ADJRequestHandler.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adjust/ADJRequestHandler.m b/Adjust/ADJRequestHandler.m index dfa56fa5a..ec2fb6eb1 100644 --- a/Adjust/ADJRequestHandler.m +++ b/Adjust/ADJRequestHandler.m @@ -58,7 +58,7 @@ - (id)initWithPackageHandler:(id)packageHandler self.logger = ADJAdjustFactory.logger; self.basePath = [packageHandler getBasePath]; self.gdprPath = [packageHandler getGdprPath]; - self.gdprPath = [packageHandler getSubscriptionPath]; + self.subscriptionPath = [packageHandler getSubscriptionPath]; return self; } From cc7ea43485fdbdc7fd11250dda600c856c560367 Mon Sep 17 00:00:00 2001 From: nonelse Date: Thu, 23 Apr 2020 17:11:41 +0200 Subject: [PATCH 13/35] Add subscription test handling --- .../AdjustTestApp/ATAAdjustCommandExecutor.m | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m index c43b14b45..40a7d531f 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m @@ -95,7 +95,9 @@ - (void)executeCommand:(NSString *)className [self trackAdRevenue:parameters]; } else if ([methodName isEqualToString:@"disableThirdPartySharing"]) { [self disableThirdPartySharing:parameters]; - } + } else if ([methodName isEqualToString:@"trackSubscription"]) { + [self trackSubscription:parameters]; + } } - (void)testOptions:(NSDictionary *)parameters { @@ -548,4 +550,57 @@ - (void)disableThirdPartySharing:(NSDictionary *)parameters { [Adjust disableThirdPartySharing]; } +- (void)trackSubscription:(NSDictionary *)parameters { + double revenue = 0; + NSString *currency; + double transactionDate = 0; + NSString *transactionId; + NSData *receipt; + + if ([parameters objectForKey:@"revenue"]) { + revenue = [[parameters objectForKey:@"revenue"][0] doubleValue]; + } + if ([parameters objectForKey:@"currency"]) { + currency = [parameters objectForKey:@"currency"][0]; + } + if ([parameters objectForKey:@"transactionDate"]) { + transactionDate = [[parameters objectForKey:@"transactionDate"][0] doubleValue]; + } + if ([parameters objectForKey:@"transactionId"]) { + transactionId = [parameters objectForKey:@"transactionId"][0]; + } + if ([parameters objectForKey:@"receipt"]) { + NSString *receiptString = [parameters objectForKey:@"receipt"][0]; + receipt = [receiptString dataUsingEncoding:NSUTF8StringEncoding]; + } + + ADJSubscription *subscription = + [[ADJSubscription alloc] + initWithRevenue:revenue + currency:currency + transactionDate:transactionDate + transactionId:transactionId + andReceipt:receipt]; + + if ([parameters objectForKey:@"callbackParams"]) { + NSArray *callbackParams = [parameters objectForKey:@"callbackParams"]; + for (int i = 0; i < callbackParams.count; i = i + 2) { + NSString *key = callbackParams[i]; + NSString *value = callbackParams[i + 1]; + [subscription addCallbackParameter:key value:value]; + } + } + + if ([parameters objectForKey:@"partnerParams"]) { + NSArray *partnerParams = [parameters objectForKey:@"partnerParams"]; + for (int i = 0; i < partnerParams.count; i = i + 2) { + NSString *key = partnerParams[i]; + NSString *value = partnerParams[i + 1]; + [subscription addPartnerParameter:key value:value]; + } + } + + [Adjust trackSubscription:subscription]; +} + @end From 08fd2d5670970584d07fe09b8d48fb6b2b5d8146 Mon Sep 17 00:00:00 2001 From: uerceg Date: Tue, 28 Apr 2020 01:39:51 +0200 Subject: [PATCH 14/35] Clean up examlple Obj-C app --- .../AdjustExample-ObjC/ViewControllerObjC.m | 42 ++++--------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/examples/AdjustExample-ObjC/AdjustExample-ObjC/ViewControllerObjC.m b/examples/AdjustExample-ObjC/AdjustExample-ObjC/ViewControllerObjC.m index ac3a27650..80d0025ff 100644 --- a/examples/AdjustExample-ObjC/AdjustExample-ObjC/ViewControllerObjC.m +++ b/examples/AdjustExample-ObjC/AdjustExample-ObjC/ViewControllerObjC.m @@ -35,42 +35,18 @@ - (void)didReceiveMemoryWarning { } - (IBAction)clickTrackSimpleEvent:(UIButton *)sender { - ADJSubscription *subscription = [[ADJSubscription alloc] - initWithRevenue:6.66 - currency:@"CAD" - transactionDate:1234567890 - transactionId:@"random-transaction-id" - andReceipt:[@"random-receipt" dataUsingEncoding:NSUTF8StringEncoding]]; - [subscription addCallbackParameter:@"foo" value:@"bar"]; - [subscription addCallbackParameter:@"key" value:@"value"]; - [subscription addPartnerParameter:@"foo" value:@"bar"]; - [subscription addPartnerParameter:@"key" value:@"value"]; - - [Adjust trackSubscription:subscription]; + ADJEvent *event = [ADJEvent eventWithEventToken:kEventToken1]; + + [Adjust trackEvent:event]; } - (IBAction)clickTrackRevenueEvent:(UIButton *)sender { - NSURL __block *url = [NSURL URLWithString:@"random-url"]; -// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ -// // Add revenue 1 cent of an EURO. -// for (int i = 0; i < 30000; i += 1) { -// [event setRevenue:i currency:@"EUR"]; -// [event setCallbackId:[NSString stringWithFormat:@"%@%d", @"random-id", i]]; -// [event addCallbackParameter:@"foo" value:[NSString stringWithFormat:@"%@%d", @"bar", i]]; -// [event addCallbackParameter:@"key" value:[NSString stringWithFormat:@"%@%d", @"value", i]]; -// } -// }); - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - for (int i = 0; i < 300; i += 1) { - [Adjust appWillOpenUrl:[NSURL URLWithString:[NSString stringWithFormat:@"random-url-%d", i]]]; - } - }); -// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ -// // Add revenue 1 cent of an EURO. -// for (int i = 30000; i < 60000; i += 1) { -// url = [NSURL URLWithString:[NSString stringWithFormat:@"random-url-%d", i]]; -// } -// }); + ADJEvent *event = [ADJEvent eventWithEventToken:kEventToken2]; + + // Add revenue 1 cent of an EURO. + [event setRevenue:0.01 currency:@"EUR"]; + + [Adjust trackEvent:event]; } - (IBAction)clickTrackCallbackEvent:(UIButton *)sender { From 0d32df2ee1ed1f604b8ecc2ddbb1e83ab842c2d0 Mon Sep 17 00:00:00 2001 From: uerceg Date: Tue, 28 Apr 2020 01:41:34 +0200 Subject: [PATCH 15/35] Change price (double->NSDecimalNumber) and transactionDate (double->NSDate) type --- Adjust/ADJPackageBuilder.m | 4 +- Adjust/ADJSubscription.h | 14 ++--- Adjust/ADJSubscription.m | 62 +++++++++---------- .../AdjustTestApp/ATAAdjustCommandExecutor.m | 20 +++--- .../AdjustTestApp/ViewController.m | 2 +- 5 files changed, 50 insertions(+), 52 deletions(-) diff --git a/Adjust/ADJPackageBuilder.m b/Adjust/ADJPackageBuilder.m index cb96619b8..2a40b3644 100644 --- a/Adjust/ADJPackageBuilder.m +++ b/Adjust/ADJPackageBuilder.m @@ -808,9 +808,9 @@ - (NSMutableDictionary *)getSubscriptionParameters:(BOOL)isInDelay forSubscripti [ADJPackageBuilder parameters:parameters setDictionary:mergedPartnerParameters forKey:@"partner_params"]; } - [ADJPackageBuilder parameters:parameters setNumber:subscription.revenue forKey:@"revenue"]; + [ADJPackageBuilder parameters:parameters setNumber:subscription.price forKey:@"revenue"]; [ADJPackageBuilder parameters:parameters setString:subscription.currency forKey:@"currency"]; - [ADJPackageBuilder parameters:parameters setDate1970:[subscription.transactionDate doubleValue] forKey:@"transaction_date"]; + [ADJPackageBuilder parameters:parameters setDate:subscription.transactionDate forKey:@"transaction_date"]; [ADJPackageBuilder parameters:parameters setString:subscription.transactionId forKey:@"transaction_id"]; [ADJPackageBuilder parameters:parameters setString:[subscription.receipt adjEncodeBase64] forKey:@"receipt"]; [ADJPackageBuilder parameters:parameters setString:subscription.billingStore forKey:@"billing_store"]; diff --git a/Adjust/ADJSubscription.h b/Adjust/ADJSubscription.h index 7ff580ac9..0409cb508 100644 --- a/Adjust/ADJSubscription.h +++ b/Adjust/ADJSubscription.h @@ -10,11 +10,11 @@ @interface ADJSubscription : NSObject -@property (nonatomic, copy, readonly, nonnull) NSNumber *revenue; +@property (nonatomic, copy, readonly, nonnull) NSDecimalNumber *price; @property (nonatomic, copy, readonly, nonnull) NSString *currency; -@property (nonatomic, copy, readonly, nonnull) NSNumber *transactionDate; +@property (nonatomic, copy, readonly, nonnull) NSDate *transactionDate; @property (nonatomic, copy, readonly, nonnull) NSString *transactionId; @@ -26,11 +26,11 @@ @property (nonatomic, copy, readonly, nonnull) NSDictionary *callbackParameters; -- (nullable id)initWithRevenue:(double)revenue - currency:(nonnull NSString *)currency - transactionDate:(double)transactionDate - transactionId:(nonnull NSString *)transactionId - andReceipt:(nonnull NSData *)receipt; +- (nullable id)initWithPrice:(nonnull NSDecimalNumber *)price + currency:(nonnull NSString *)currency + transactionDate:(nonnull NSDate *)transactionDate + transactionId:(nonnull NSString *)transactionId + andReceipt:(nonnull NSData *)receipt; - (void)addCallbackParameter:(nonnull NSString *)key value:(nonnull NSString *)value; diff --git a/Adjust/ADJSubscription.m b/Adjust/ADJSubscription.m index fe5820dfb..eaf3aa898 100644 --- a/Adjust/ADJSubscription.m +++ b/Adjust/ADJSubscription.m @@ -22,19 +22,19 @@ @interface ADJSubscription() @implementation ADJSubscription -- (nullable id)initWithRevenue:(double)revenue - currency:(nonnull NSString *)currency - transactionDate:(double)transactionDate - transactionId:(nonnull NSString *)transactionId - andReceipt:(nonnull NSData *)receipt { +- (nullable id)initWithPrice:(nonnull NSDecimalNumber *)price + currency:(nonnull NSString *)currency + transactionDate:(nonnull NSDate *)transactionDate + transactionId:(nonnull NSString *)transactionId + andReceipt:(nonnull NSData *)receipt { self = [super init]; if (self == nil) { return nil; } - _revenue = [NSNumber numberWithDouble:revenue]; + _price = [price copy]; _currency = [currency copy]; - _transactionDate = [NSNumber numberWithDouble:transactionDate]; + _transactionDate = [transactionDate copy]; _transactionId = [transactionId copy]; _receipt = [receipt copy]; _billingStore = @"iOS"; @@ -51,18 +51,18 @@ - (nullable id)initWithRevenue:(double)revenue - (void)addCallbackParameter:(nonnull NSString *)key value:(nonnull NSString *)value { - if (![ADJUtil isValidParameter:key - attributeType:@"key" - parameterName:@"Callback"]) { - return; - } - if (![ADJUtil isValidParameter:value - attributeType:@"value" - parameterName:@"Callback"]) { - return; - } - @synchronized (self) { + if (![ADJUtil isValidParameter:key + attributeType:@"key" + parameterName:@"Callback"]) { + return; + } + if (![ADJUtil isValidParameter:value + attributeType:@"value" + parameterName:@"Callback"]) { + return; + } + if (self.mutableCallbackParameters == nil) { self.mutableCallbackParameters = [[NSMutableDictionary alloc] init]; } @@ -78,18 +78,18 @@ - (void)addCallbackParameter:(nonnull NSString *)key - (void)addPartnerParameter:(nonnull NSString *)key value:(nonnull NSString *)value { - if (![ADJUtil isValidParameter:key - attributeType:@"key" - parameterName:@"Partner"]) { - return; - } - if (![ADJUtil isValidParameter:value - attributeType:@"value" - parameterName:@"Partner"]) { - return; - } - @synchronized (self) { + if (![ADJUtil isValidParameter:key + attributeType:@"key" + parameterName:@"Partner"]) { + return; + } + if (![ADJUtil isValidParameter:value + attributeType:@"value" + parameterName:@"Partner"]) { + return; + } + if (self.mutablePartnerParameters == nil) { self.mutablePartnerParameters = [[NSMutableDictionary alloc] init]; } @@ -103,7 +103,7 @@ - (void)addPartnerParameter:(nonnull NSString *)key } - (BOOL)isValid { - if (self.revenue == nil) { + if (self.price == nil) { return NO; } if (self.currency == nil) { @@ -136,7 +136,7 @@ - (nonnull NSDictionary *)partnerParameters { - (id)copyWithZone:(NSZone *)zone { ADJSubscription *copy = [[[self class] allocWithZone:zone] init]; if (copy) { - copy->_revenue = [self.revenue copyWithZone:zone]; + copy->_price = [self.price copyWithZone:zone]; copy->_currency = [self.currency copyWithZone:zone]; copy->_transactionDate = [self.receipt copyWithZone:zone]; copy->_transactionId = [self.transactionId copyWithZone:zone]; diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m index 40a7d531f..7387a3155 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m @@ -551,20 +551,20 @@ - (void)disableThirdPartySharing:(NSDictionary *)parameters { } - (void)trackSubscription:(NSDictionary *)parameters { - double revenue = 0; + NSDecimalNumber *price; NSString *currency; - double transactionDate = 0; + NSDate *transactionDate; NSString *transactionId; NSData *receipt; if ([parameters objectForKey:@"revenue"]) { - revenue = [[parameters objectForKey:@"revenue"][0] doubleValue]; + price = [[NSDecimalNumber alloc] initWithDouble:[[parameters objectForKey:@"revenue"][0] doubleValue]]; } if ([parameters objectForKey:@"currency"]) { currency = [parameters objectForKey:@"currency"][0]; } if ([parameters objectForKey:@"transactionDate"]) { - transactionDate = [[parameters objectForKey:@"transactionDate"][0] doubleValue]; + transactionDate = [NSDate dateWithTimeIntervalSince1970:[[parameters objectForKey:@"transactionDate"][0] doubleValue]]; } if ([parameters objectForKey:@"transactionId"]) { transactionId = [parameters objectForKey:@"transactionId"][0]; @@ -574,13 +574,11 @@ - (void)trackSubscription:(NSDictionary *)parameters { receipt = [receiptString dataUsingEncoding:NSUTF8StringEncoding]; } - ADJSubscription *subscription = - [[ADJSubscription alloc] - initWithRevenue:revenue - currency:currency - transactionDate:transactionDate - transactionId:transactionId - andReceipt:receipt]; + ADJSubscription *subscription = [[ADJSubscription alloc] initWithPrice:price + currency:currency + transactionDate:transactionDate + transactionId:transactionId + andReceipt:receipt]; if ([parameters objectForKey:@"callbackParams"]) { NSArray *callbackParams = [parameters objectForKey:@"callbackParams"]; diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.m b/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.m index f42dc99cc..9eb837814 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.m @@ -31,7 +31,7 @@ - (void)viewDidLoad { [self.adjustCommandExecutor setTestLibrary:self.testLibrary]; // [self.testLibrary addTestDirectory:@"current/third-party-sharing"]; - // [self.testLibrary addTest:@"Test_GdprForgetMe_after_install_kill_before_install"]; + [self.testLibrary addTest:@"Test_iOs_Subscription_subscription"]; // [self.testLibrary doNotExitAfterEnd]; [self startTestSession]; From f644c71c4df44dff9c3d00371b2b2f6176e59f25 Mon Sep 17 00:00:00 2001 From: uerceg Date: Wed, 29 Apr 2020 02:13:28 +0200 Subject: [PATCH 16/35] No need for event_count in subscription package --- Adjust/ADJPackageBuilder.m | 1 - 1 file changed, 1 deletion(-) diff --git a/Adjust/ADJPackageBuilder.m b/Adjust/ADJPackageBuilder.m index 2a40b3644..139fa4042 100644 --- a/Adjust/ADJPackageBuilder.m +++ b/Adjust/ADJPackageBuilder.m @@ -783,7 +783,6 @@ - (NSMutableDictionary *)getSubscriptionParameters:(BOOL)isInDelay forSubscripti } if (self.activityState != nil) { - [ADJPackageBuilder parameters:parameters setInt:self.activityState.eventCount forKey:@"event_count"]; [ADJPackageBuilder parameters:parameters setString:self.activityState.deviceToken forKey:@"push_token"]; [ADJPackageBuilder parameters:parameters setInt:self.activityState.sessionCount forKey:@"session_count"]; [ADJPackageBuilder parameters:parameters setDuration:self.activityState.sessionLength forKey:@"session_length"]; From 313681c1066c9893e81130dba28b24ff56c80938 Mon Sep 17 00:00:00 2001 From: uerceg Date: Wed, 29 Apr 2020 02:14:13 +0200 Subject: [PATCH 17/35] Make mandatory fields to be softly mandatory --- Adjust/ADJSubscription.m | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/Adjust/ADJSubscription.m b/Adjust/ADJSubscription.m index eaf3aa898..86f4a8f03 100644 --- a/Adjust/ADJSubscription.m +++ b/Adjust/ADJSubscription.m @@ -41,10 +41,6 @@ - (nullable id)initWithPrice:(nonnull NSDecimalNumber *)price _logger = ADJAdjustFactory.logger; - if (![self isValid]) { - return nil; - } - return self; } @@ -102,29 +98,6 @@ - (void)addPartnerParameter:(nonnull NSString *)key } } -- (BOOL)isValid { - if (self.price == nil) { - return NO; - } - if (self.currency == nil) { - return NO; - } - if (self.transactionDate == nil) { - return NO; - } - if (self.transactionId == nil) { - return NO; - } - if (self.receipt == nil) { - return NO; - } - if (self.billingStore == nil) { - return NO; - } - - return YES; -} - - (nonnull NSDictionary *)callbackParameters { return [self.mutableCallbackParameters copy]; } @@ -135,6 +108,7 @@ - (nonnull NSDictionary *)partnerParameters { - (id)copyWithZone:(NSZone *)zone { ADJSubscription *copy = [[[self class] allocWithZone:zone] init]; + if (copy) { copy->_price = [self.price copyWithZone:zone]; copy->_currency = [self.currency copyWithZone:zone]; @@ -145,6 +119,7 @@ - (id)copyWithZone:(NSZone *)zone { copy.mutableCallbackParameters = [self.mutableCallbackParameters copyWithZone:zone]; copy.mutablePartnerParameters = [self.mutablePartnerParameters copyWithZone:zone]; } + return copy; } From 0328aef5482b0705b089aa1c3dea009fa74c34bb Mon Sep 17 00:00:00 2001 From: uerceg Date: Tue, 5 May 2020 02:04:12 +0200 Subject: [PATCH 18/35] Remove install_receipt from subscription payload --- Adjust/ADJPackageBuilder.m | 1 - 1 file changed, 1 deletion(-) diff --git a/Adjust/ADJPackageBuilder.m b/Adjust/ADJPackageBuilder.m index 139fa4042..b3e04a6ee 100644 --- a/Adjust/ADJPackageBuilder.m +++ b/Adjust/ADJPackageBuilder.m @@ -769,7 +769,6 @@ - (NSMutableDictionary *)getSubscriptionParameters:(BOOL)isInDelay forSubscripti [ADJPackageBuilder parameters:parameters setString:UIDevice.currentDevice.adjIdForAdvertisers forKey:@"idfa"]; } [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.vendorId forKey:@"idfv"]; - [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.installReceiptBase64 forKey:@"install_receipt"]; [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.languageCode forKey:@"language"]; [ADJPackageBuilder parameters:parameters setBool:YES forKey:@"needs_response_details"]; [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.osBuild forKey:@"os_build"]; From 1fdf4aff5508b39ddc5e64dca23960c4d083b3ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uglje=C5=A1a=20Erceg?= Date: Tue, 12 May 2020 23:04:17 +0200 Subject: [PATCH 19/35] Update README.md --- README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/README.md b/README.md index e2ade75b1..f3678992b 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ Read this in other languages: [English][en-readme], [中文][zh-readme], [日本 * [Delay start](#delay-start) * [Attribution callback](#attribution-callback) * [Ad revenue tracking](#ad-revenue) + * [Subscriptions tracking](#subscriptions) * [Event and session callbacks](#event-session-callbacks) * [Disable tracking](#disable-tracking) * [Offline mode](#offline-mode) @@ -518,6 +519,29 @@ Currently we support the below `source` parameter values: - `ADJAdRevenueSourceMopub` - representing MoPub mediation platform (for more information, check [integration guide][sdk2sdk-mopub]) +### Subscriptions tracking + +**Note**: This feature is available only in the native SDK v4.22.0 and above. + +You can track App Store subscriptions and verify their validity with Adjust SDK. After subscription has been successfully purchased, you need to make following call to Adjust SDK: + +```objc +ADJSubscription *subscription = [[ADJSubscription alloc] initWithPrice:price + currency:currency + transactionDate:transactionDate + transactionId:transactionId + andReceipt:receipt]; +[Adjust trackSubscription:subscription]; +``` + +Subscription parameters you need to pass to the method are: + +- [price](https://developer.apple.com/documentation/storekit/skproduct/1506094-price?language=objc) +- currency (you need to pass [currencyCode](https://developer.apple.com/documentation/foundation/nslocale/1642836-currencycode?language=objc) of the [priceLocale](https://developer.apple.com/documentation/storekit/skproduct/1506145-pricelocale?language=objc) object) +- [transactionDate](https://developer.apple.com/documentation/storekit/skpaymenttransaction/1411273-transactiondate?language=objc) +- [transactionId](https://developer.apple.com/documentation/storekit/skpaymenttransaction/1411288-transactionidentifier?language=objc) +- [receipt](https://developer.apple.com/documentation/foundation/nsbundle/1407276-appstorereceipturl) + ### Event and session callbacks You can register a delegate callback to be notified of successful and failed tracked events and/or sessions. The same optional protocol `AdjustDelegate` used for the [attribution callback](#attribution-callback) is used. From 6def8c3b5dcb97135f572032f23cb582fe1a8b28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uglje=C5=A1a=20Erceg?= Date: Tue, 12 May 2020 23:09:15 +0200 Subject: [PATCH 20/35] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f3678992b..1ae7eb18f 100644 --- a/README.md +++ b/README.md @@ -519,7 +519,7 @@ Currently we support the below `source` parameter values: - `ADJAdRevenueSourceMopub` - representing MoPub mediation platform (for more information, check [integration guide][sdk2sdk-mopub]) -### Subscriptions tracking +### Subscriptions tracking **Note**: This feature is available only in the native SDK v4.22.0 and above. @@ -534,6 +534,9 @@ ADJSubscription *subscription = [[ADJSubscription alloc] initWithPrice:price [Adjust trackSubscription:subscription]; ``` + +Make sure to do this before making a call to `finishTransaction` in `paymentQueue:updatedTransaction` only if the state changed to `SKPaymentTransactionStatePurchased` or `SKPaymentTransactionStateRestored`. + Subscription parameters you need to pass to the method are: - [price](https://developer.apple.com/documentation/storekit/skproduct/1506094-price?language=objc) From 1c2caaf03348d313f1ee0070d4cbf21bff66cc50 Mon Sep 17 00:00:00 2001 From: uerceg Date: Thu, 14 May 2020 02:00:26 +0200 Subject: [PATCH 21/35] Add sales_region parameter and make transaction_date optional --- Adjust/ADJPackageBuilder.m | 3 +- Adjust/ADJSubscription.h | 23 ++++++----- Adjust/ADJSubscription.m | 40 +++++++++++++------ .../AdjustTestApp/ATAAdjustCommandExecutor.m | 15 ++++--- 4 files changed, 54 insertions(+), 27 deletions(-) diff --git a/Adjust/ADJPackageBuilder.m b/Adjust/ADJPackageBuilder.m index b3e04a6ee..e66e83753 100644 --- a/Adjust/ADJPackageBuilder.m +++ b/Adjust/ADJPackageBuilder.m @@ -808,10 +808,11 @@ - (NSMutableDictionary *)getSubscriptionParameters:(BOOL)isInDelay forSubscripti [ADJPackageBuilder parameters:parameters setNumber:subscription.price forKey:@"revenue"]; [ADJPackageBuilder parameters:parameters setString:subscription.currency forKey:@"currency"]; - [ADJPackageBuilder parameters:parameters setDate:subscription.transactionDate forKey:@"transaction_date"]; [ADJPackageBuilder parameters:parameters setString:subscription.transactionId forKey:@"transaction_id"]; [ADJPackageBuilder parameters:parameters setString:[subscription.receipt adjEncodeBase64] forKey:@"receipt"]; [ADJPackageBuilder parameters:parameters setString:subscription.billingStore forKey:@"billing_store"]; + [ADJPackageBuilder parameters:parameters setDate:subscription.transactionDate forKey:@"transaction_date"]; + [ADJPackageBuilder parameters:parameters setString:subscription.salesRegion forKey:@"sales_region"]; #if !TARGET_OS_TV && !TARGET_OS_MACCATALYST [ADJPackageBuilder parameters:parameters setString:[ADJUtil readMCC] forKey:@"mcc"]; diff --git a/Adjust/ADJSubscription.h b/Adjust/ADJSubscription.h index 0409cb508..92f5395ed 100644 --- a/Adjust/ADJSubscription.h +++ b/Adjust/ADJSubscription.h @@ -10,28 +10,33 @@ @interface ADJSubscription : NSObject -@property (nonatomic, copy, readonly, nonnull) NSDecimalNumber *price; +@property (nonatomic, copy, readonly, nonnull) NSDecimalNumber *price; // [M] revenue -@property (nonatomic, copy, readonly, nonnull) NSString *currency; +@property (nonatomic, copy, readonly, nonnull) NSString *currency; // [M] currency -@property (nonatomic, copy, readonly, nonnull) NSDate *transactionDate; +@property (nonatomic, copy, readonly, nonnull) NSString *transactionId; // [M] transaction_id -@property (nonatomic, copy, readonly, nonnull) NSString *transactionId; +@property (nonatomic, copy, readonly, nonnull) NSData *receipt; // [M] receipt -@property (nonatomic, copy, readonly, nonnull) NSData *receipt; +@property (nonatomic, copy, readonly, nonnull) NSString *billingStore; // [M] billing_store -@property (nonatomic, copy, readonly, nonnull) NSString *billingStore; +@property (nonatomic, copy, readonly, nonnull) NSDate *transactionDate; // [O] transaction_date -@property (nonatomic, copy, readonly, nonnull) NSDictionary *partnerParameters; +@property (nonatomic, copy, readonly, nonnull) NSString *salesRegion; // [O] sales_region -@property (nonatomic, copy, readonly, nonnull) NSDictionary *callbackParameters; +@property (nonatomic, copy, readonly, nonnull) NSDictionary *callbackParameters; // [O] callback_params + +@property (nonatomic, copy, readonly, nonnull) NSDictionary *partnerParameters; // [O] partner_params - (nullable id)initWithPrice:(nonnull NSDecimalNumber *)price currency:(nonnull NSString *)currency - transactionDate:(nonnull NSDate *)transactionDate transactionId:(nonnull NSString *)transactionId andReceipt:(nonnull NSData *)receipt; +- (void)setTransactionDate:(nonnull NSDate *)transactionDate; + +- (void)setSalesRegion:(nonnull NSString *)salesRegion; + - (void)addCallbackParameter:(nonnull NSString *)key value:(nonnull NSString *)value; - (void)addPartnerParameter:(nonnull NSString *)key value:(nonnull NSString *)value; diff --git a/Adjust/ADJSubscription.m b/Adjust/ADJSubscription.m index 86f4a8f03..304c37b6d 100644 --- a/Adjust/ADJSubscription.m +++ b/Adjust/ADJSubscription.m @@ -24,7 +24,6 @@ @implementation ADJSubscription - (nullable id)initWithPrice:(nonnull NSDecimalNumber *)price currency:(nonnull NSString *)currency - transactionDate:(nonnull NSDate *)transactionDate transactionId:(nonnull NSString *)transactionId andReceipt:(nonnull NSData *)receipt { self = [super init]; @@ -34,7 +33,6 @@ - (nullable id)initWithPrice:(nonnull NSDecimalNumber *)price _price = [price copy]; _currency = [currency copy]; - _transactionDate = [transactionDate copy]; _transactionId = [transactionId copy]; _receipt = [receipt copy]; _billingStore = @"iOS"; @@ -44,16 +42,31 @@ - (nullable id)initWithPrice:(nonnull NSDecimalNumber *)price return self; } +- (void)setTransactionDate:(NSDate *)transactionDate { + @synchronized (self) { + _transactionDate = [transactionDate copy]; + } +} + +- (void)setSalesRegion:(NSString *)salesRegion { + @synchronized (self) { + _salesRegion = [salesRegion copy]; + } +} + - (void)addCallbackParameter:(nonnull NSString *)key value:(nonnull NSString *)value { @synchronized (self) { - if (![ADJUtil isValidParameter:key + NSString *immutableKey = [key copy]; + NSString *immutableValue = [value copy]; + + if (![ADJUtil isValidParameter:immutableKey attributeType:@"key" parameterName:@"Callback"]) { return; } - if (![ADJUtil isValidParameter:value + if (![ADJUtil isValidParameter:immutableValue attributeType:@"value" parameterName:@"Callback"]) { return; @@ -63,11 +76,11 @@ - (void)addCallbackParameter:(nonnull NSString *)key self.mutableCallbackParameters = [[NSMutableDictionary alloc] init]; } - if ([self.mutableCallbackParameters objectForKey:key]) { - [self.logger warn:@"key %@ was overwritten", key]; + if ([self.mutableCallbackParameters objectForKey:immutableKey]) { + [self.logger warn:@"key %@ was overwritten", immutableKey]; } - [self.mutableCallbackParameters setObject:value forKey:key]; + [self.mutableCallbackParameters setObject:immutableValue forKey:immutableKey]; } } @@ -75,12 +88,15 @@ - (void)addPartnerParameter:(nonnull NSString *)key value:(nonnull NSString *)value { @synchronized (self) { - if (![ADJUtil isValidParameter:key + NSString *immutableKey = [key copy]; + NSString *immutableValue = [value copy]; + + if (![ADJUtil isValidParameter:immutableKey attributeType:@"key" parameterName:@"Partner"]) { return; } - if (![ADJUtil isValidParameter:value + if (![ADJUtil isValidParameter:immutableValue attributeType:@"value" parameterName:@"Partner"]) { return; @@ -90,11 +106,11 @@ - (void)addPartnerParameter:(nonnull NSString *)key self.mutablePartnerParameters = [[NSMutableDictionary alloc] init]; } - if ([self.mutablePartnerParameters objectForKey:key]) { - [self.logger warn:@"key %@ was overwritten", key]; + if ([self.mutablePartnerParameters objectForKey:immutableKey]) { + [self.logger warn:@"key %@ was overwritten", immutableKey]; } - [self.mutablePartnerParameters setObject:value forKey:key]; + [self.mutablePartnerParameters setObject:immutableValue forKey:immutableKey]; } } diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m index 7387a3155..f8a24d4cc 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m @@ -553,9 +553,10 @@ - (void)disableThirdPartySharing:(NSDictionary *)parameters { - (void)trackSubscription:(NSDictionary *)parameters { NSDecimalNumber *price; NSString *currency; - NSDate *transactionDate; NSString *transactionId; NSData *receipt; + NSDate *transactionDate; + NSString *salesRegion; if ([parameters objectForKey:@"revenue"]) { price = [[NSDecimalNumber alloc] initWithDouble:[[parameters objectForKey:@"revenue"][0] doubleValue]]; @@ -563,9 +564,6 @@ - (void)trackSubscription:(NSDictionary *)parameters { if ([parameters objectForKey:@"currency"]) { currency = [parameters objectForKey:@"currency"][0]; } - if ([parameters objectForKey:@"transactionDate"]) { - transactionDate = [NSDate dateWithTimeIntervalSince1970:[[parameters objectForKey:@"transactionDate"][0] doubleValue]]; - } if ([parameters objectForKey:@"transactionId"]) { transactionId = [parameters objectForKey:@"transactionId"][0]; } @@ -573,12 +571,19 @@ - (void)trackSubscription:(NSDictionary *)parameters { NSString *receiptString = [parameters objectForKey:@"receipt"][0]; receipt = [receiptString dataUsingEncoding:NSUTF8StringEncoding]; } + if ([parameters objectForKey:@"transactionDate"]) { + transactionDate = [NSDate dateWithTimeIntervalSince1970:[[parameters objectForKey:@"transactionDate"][0] doubleValue]]; + } + if ([parameters objectForKey:@"salesRegion"]) { + salesRegion = [parameters objectForKey:@"salesRegion"][0]; + } ADJSubscription *subscription = [[ADJSubscription alloc] initWithPrice:price currency:currency - transactionDate:transactionDate transactionId:transactionId andReceipt:receipt]; + [subscription setTransactionDate:transactionDate]; + [subscription setSalesRegion:salesRegion]; if ([parameters objectForKey:@"callbackParams"]) { NSArray *callbackParams = [parameters objectForKey:@"callbackParams"]; From 027f10115a13b91206a1b18815a37a789d8c4a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uglje=C5=A1a=20Erceg?= Date: Thu, 14 May 2020 02:04:45 +0200 Subject: [PATCH 22/35] Update README.md --- README.md | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1ae7eb18f..b65b65a3d 100644 --- a/README.md +++ b/README.md @@ -528,22 +528,46 @@ You can track App Store subscriptions and verify their validity with Adjust SDK. ```objc ADJSubscription *subscription = [[ADJSubscription alloc] initWithPrice:price currency:currency - transactionDate:transactionDate transactionId:transactionId andReceipt:receipt]; +[subscription setTransactionDate:transactionDate]; +[subscription setSalesRegion:salesRegion]; + [Adjust trackSubscription:subscription]; ``` Make sure to do this before making a call to `finishTransaction` in `paymentQueue:updatedTransaction` only if the state changed to `SKPaymentTransactionStatePurchased` or `SKPaymentTransactionStateRestored`. -Subscription parameters you need to pass to the method are: +Subscription tracking parameters: - [price](https://developer.apple.com/documentation/storekit/skproduct/1506094-price?language=objc) - currency (you need to pass [currencyCode](https://developer.apple.com/documentation/foundation/nslocale/1642836-currencycode?language=objc) of the [priceLocale](https://developer.apple.com/documentation/storekit/skproduct/1506145-pricelocale?language=objc) object) -- [transactionDate](https://developer.apple.com/documentation/storekit/skpaymenttransaction/1411273-transactiondate?language=objc) - [transactionId](https://developer.apple.com/documentation/storekit/skpaymenttransaction/1411288-transactionidentifier?language=objc) - [receipt](https://developer.apple.com/documentation/foundation/nsbundle/1407276-appstorereceipturl) +- [transactionDate](https://developer.apple.com/documentation/storekit/skpaymenttransaction/1411273-transactiondate?language=objc) +- salesRegion (you need to pass [countryCode](https://developer.apple.com/documentation/foundation/nslocale/1643060-countrycode?language=objc) of the [priceLocale](https://developer.apple.com/documentation/storekit/skproduct/1506145-pricelocale?language=objc) object) + +In same fashion like with event tracking, you can attach callback and partner parameters to subscription object as well: + +```objc +ADJSubscription *subscription = [[ADJSubscription alloc] initWithPrice:price + currency:currency + transactionId:transactionId + andReceipt:receipt]; +[subscription setTransactionDate:transactionDate]; +[subscription setSalesRegion:salesRegion]; + +// add callback parameters +[subscription addCallbackParameter:@"key" value:@"value"]; +[subscription addCallbackParameter:@"foo" value:@"bar"]; + +// add partner parameters +[subscription addPartnerParameter:@"key" value:@"value"]; +[subscription addPartnerParameter:@"foo" value:@"bar"]; + +[Adjust trackSubscription:subscription]; +``` ### Event and session callbacks From aeb32bf1f9195ff5dc737b5386b822090223571c Mon Sep 17 00:00:00 2001 From: nonelse Date: Tue, 19 May 2020 18:06:31 +0200 Subject: [PATCH 23/35] Extract networking into request handler --- Adjust/ADJActivityHandler.h | 11 +- Adjust/ADJActivityHandler.m | 59 +- Adjust/ADJAdjustFactory.h | 22 +- Adjust/ADJAdjustFactory.m | 98 +-- Adjust/ADJAttributionHandler.h | 14 +- Adjust/ADJAttributionHandler.m | 71 ++- Adjust/ADJPackageBuilder.h | 4 + Adjust/ADJPackageHandler.h | 19 +- Adjust/ADJPackageHandler.m | 109 ++-- Adjust/ADJRequestHandler.h | 29 +- Adjust/ADJRequestHandler.m | 558 +++++++++++++++--- Adjust/ADJResponseData.h | 9 +- Adjust/ADJResponseData.m | 47 +- Adjust/ADJSdkClickHandler.h | 14 +- Adjust/ADJSdkClickHandler.m | 88 +-- Adjust/ADJUtil.h | 20 +- Adjust/ADJUtil.m | 458 -------------- Adjust/Adjust.h | 4 +- Adjust/Adjust.m | 15 +- AdjustBridge/AdjustBridge.m | 10 +- .../AdjustTestApp/ATAAdjustCommandExecutor.m | 57 +- .../Delegates/ATAAdjustDelegateAttribution.h | 2 +- .../Delegates/ATAAdjustDelegateAttribution.m | 8 +- .../ATAAdjustDelegateDeferredDeeplink.h | 2 +- .../ATAAdjustDelegateDeferredDeeplink.m | 8 +- .../Delegates/ATAAdjustDelegateEventFailure.h | 2 +- .../Delegates/ATAAdjustDelegateEventFailure.m | 8 +- .../Delegates/ATAAdjustDelegateEventSuccess.h | 2 +- .../Delegates/ATAAdjustDelegateEventSuccess.m | 8 +- .../ATAAdjustDelegateSessionFailure.h | 2 +- .../ATAAdjustDelegateSessionFailure.m | 8 +- .../ATAAdjustDelegateSessionSuccess.h | 2 +- .../ATAAdjustDelegateSessionSuccess.m | 8 +- .../AdjustTestApp/ViewController.m | 4 +- 34 files changed, 796 insertions(+), 984 deletions(-) diff --git a/Adjust/ADJActivityHandler.h b/Adjust/ADJActivityHandler.h index 9a96dd4fa..360699ced 100644 --- a/Adjust/ADJActivityHandler.h +++ b/Adjust/ADJActivityHandler.h @@ -44,9 +44,7 @@ @property (nonatomic, copy) NSData *deviceTokenData; @property (nonatomic, copy) NSNumber *enabled; @property (nonatomic, assign) BOOL offline; -@property (nonatomic, copy) NSString *basePath; -@property (nonatomic, copy) NSString *gdprPath; -@property (nonatomic, copy) NSString *subscriptionPath; +@property (nonatomic, copy) NSString *extraPath; - (id)init; @@ -99,9 +97,6 @@ - (void)trackAdRevenue:(NSString *)soruce payload:(NSData *)payload; - (void)disableThirdPartySharing; - (void)trackSubscription:(ADJSubscription *)subscription; -- (NSString *)getBasePath; -- (NSString *)getGdprPath; -- (NSString *)getSubscriptionPath; - (ADJDeviceInfo *)deviceInfo; - (ADJActivityState *)activityState; @@ -114,8 +109,8 @@ @interface ADJActivityHandler : NSObject -+ (id)handlerWithConfig:(ADJConfig *)adjustConfig - savedPreLaunch:(ADJSavedPreLaunch *)savedPreLaunch; +- (id)initWithConfig:(ADJConfig *)adjustConfig + savedPreLaunch:(ADJSavedPreLaunch *)savedPreLaunch; - (void)addSessionCallbackParameterI:(ADJActivityHandler *)selfI key:(NSString *)key diff --git a/Adjust/ADJActivityHandler.m b/Adjust/ADJActivityHandler.m index 009e74916..d119c9d9f 100644 --- a/Adjust/ADJActivityHandler.m +++ b/Adjust/ADJActivityHandler.m @@ -80,9 +80,9 @@ - (id)init { @interface ADJActivityHandler() @property (nonatomic, strong) dispatch_queue_t internalQueue; -@property (nonatomic, strong) id packageHandler; -@property (nonatomic, strong) id attributionHandler; -@property (nonatomic, strong) id sdkClickHandler; +@property (nonatomic, strong) ADJPackageHandler *packageHandler; +@property (nonatomic, strong) ADJAttributionHandler *attributionHandler; +@property (nonatomic, strong) ADJSdkClickHandler *sdkClickHandler; @property (nonatomic, strong) ADJActivityState *activityState; @property (nonatomic, strong) ADJTimerCycle *foregroundTimer; @property (nonatomic, strong) ADJTimerOnce *backgroundTimer; @@ -116,15 +116,9 @@ @implementation ADJActivityHandler @synthesize attribution = _attribution; -+ (id)handlerWithConfig:(ADJConfig *)adjustConfig - savedPreLaunch:(ADJSavedPreLaunch *)savedPreLaunch -{ - return [[ADJActivityHandler alloc] initWithConfig:adjustConfig - savedPreLaunch:savedPreLaunch]; -} - - (id)initWithConfig:(ADJConfig *)adjustConfig - savedPreLaunch:(ADJSavedPreLaunch *)savedPreLaunch { + savedPreLaunch:(ADJSavedPreLaunch *)savedPreLaunch +{ self = [super init]; if (self == nil) return nil; @@ -196,16 +190,6 @@ - (id)initWithConfig:(ADJConfig *)adjustConfig // does not have the session response by default self.internalState.sessionResponseProcessed = NO; - if (savedPreLaunch.basePath != nil) { - self.basePath = savedPreLaunch.basePath; - } - if (savedPreLaunch.gdprPath != nil) { - self.gdprPath = savedPreLaunch.gdprPath; - } - if (savedPreLaunch.subscriptionPath != nil) { - self.subscriptionPath = savedPreLaunch.subscriptionPath; - } - self.iAdRetriesLeft = kiAdRetriesCount; self.internalQueue = dispatch_queue_create(kInternalQueueName, DISPATCH_QUEUE_SERIAL); @@ -213,7 +197,7 @@ - (id)initWithConfig:(ADJConfig *)adjustConfig selfInject:self block:^(ADJActivityHandler * selfI) { [selfI initI:selfI - preLaunchActionsArray:savedPreLaunch.preLaunchActionsArray]; + preLaunchActions:savedPreLaunch]; }]; /* Not needed, done already in initI:preLaunchActionsArray: method. @@ -709,7 +693,7 @@ + (void)deleteSessionPartnerParameter { #pragma mark - internal - (void)initI:(ADJActivityHandler *)selfI -preLaunchActionsArray:(NSArray*)preLaunchActionsArray +preLaunchActions:(ADJSavedPreLaunch*)preLaunchActions { // get session values kSessionInterval = ADJAdjustFactory.sessionInterval; @@ -782,28 +766,37 @@ - (void)initI:(ADJActivityHandler *)selfI [ADJUtil updateUrlSessionConfiguration:selfI.adjustConfig]; - selfI.packageHandler = [ADJAdjustFactory packageHandlerForActivityHandler:selfI - startsSending:[selfI toSendI:selfI - sdkClickHandlerOnly:NO]]; + selfI.packageHandler = [[ADJPackageHandler alloc] + initWithActivityHandler:selfI + startsSending: + [selfI toSendI:selfI sdkClickHandlerOnly:NO] + userAgent:selfI.adjustConfig.userAgent + extraPath:preLaunchActions.extraPath]; // update session parameters in package queue if ([selfI itHasToUpdatePackagesI:selfI]) { [selfI updatePackagesI:selfI]; } - selfI.attributionHandler = [ADJAdjustFactory attributionHandlerForActivityHandler:selfI - startsSending:[selfI toSendI:selfI - sdkClickHandlerOnly:NO]]; + selfI.attributionHandler = [[ADJAttributionHandler alloc] + initWithActivityHandler:selfI + startsSending: + [selfI toSendI:selfI sdkClickHandlerOnly:NO] + userAgent:selfI.adjustConfig.userAgent + extraPath:preLaunchActions.extraPath]; - selfI.sdkClickHandler = [ADJAdjustFactory sdkClickHandlerForActivityHandler:selfI - startsSending:[selfI toSendI:selfI - sdkClickHandlerOnly:YES]]; + selfI.sdkClickHandler = [[ADJSdkClickHandler alloc] + initWithActivityHandler:selfI + startsSending:[selfI toSendI:selfI sdkClickHandlerOnly:YES] + userAgent:selfI.adjustConfig.userAgent + extraPath:preLaunchActions.extraPath]; if (selfI.adjustConfig.allowiAdInfoReading == YES) { [selfI checkForiAdI:selfI]; } - [selfI preLaunchActionsI:selfI preLaunchActionsArray:preLaunchActionsArray]; + [selfI preLaunchActionsI:selfI + preLaunchActionsArray:preLaunchActions.preLaunchActionsArray]; [ADJUtil launchInMainThreadWithInactive:^(BOOL isInactive) { [ADJUtil launchInQueue:self.internalQueue selfInject:self block:^(ADJActivityHandler * selfI) { diff --git a/Adjust/ADJAdjustFactory.h b/Adjust/ADJAdjustFactory.h index fce9560b3..cef20d7e3 100644 --- a/Adjust/ADJAdjustFactory.h +++ b/Adjust/ADJAdjustFactory.h @@ -7,37 +7,23 @@ // #import -#import "ADJActivityHandler.h" -#import "ADJPackageHandler.h" -#import "ADJRequestHandler.h" #import "ADJLogger.h" -#import "ADJAttributionHandler.h" #import "ADJActivityPackage.h" #import "ADJBackoffStrategy.h" #import "ADJSdkClickHandler.h" @interface ADJAdjustFactory : NSObject -+ (id)packageHandlerForActivityHandler:(id)activityHandler - startsSending:(BOOL)startsSending; -+ (id)requestHandlerForPackageHandler:(id)packageHandler - andActivityHandler:(id)activityHandler; -+ (id)activityHandlerWithConfig:(ADJConfig *)adjustConfig - savedPreLaunch:(ADJSavedPreLaunch *)savedPreLaunch; -+ (id)sdkClickHandlerForActivityHandler:(id)activityHandler - startsSending:(BOOL)startsSending; - + (id)logger; + (double)sessionInterval; + (double)subsessionInterval; ++ (double)requestTimeout; + (NSTimeInterval)timerInterval; + (NSTimeInterval)timerStart; + (ADJBackoffStrategy *)packageHandlerBackoffStrategy; + (ADJBackoffStrategy *)sdkClickHandlerBackoffStrategy; + (ADJBackoffStrategy *)installSessionBackoffStrategy; -+ (id)attributionHandlerForActivityHandler:(id)activityHandler - startsSending:(BOOL)startsSending; + (BOOL)testing; + (NSTimeInterval)maxDelayStart; + (NSString *)baseUrl; @@ -45,16 +31,12 @@ + (NSString *)subscriptionUrl; + (BOOL)iAdFrameworkEnabled; -+ (void)setPackageHandler:(id)packageHandler; -+ (void)setRequestHandler:(id)requestHandler; -+ (void)setActivityHandler:(id)activityHandler; -+ (void)setSdkClickHandler:(id)sdkClickHandler; + (void)setLogger:(id)logger; + (void)setSessionInterval:(double)sessionInterval; + (void)setSubsessionInterval:(double)subsessionInterval; ++ (void)setRequestTimeout:(double)requestTimeout; + (void)setTimerInterval:(NSTimeInterval)timerInterval; + (void)setTimerStart:(NSTimeInterval)timerStart; -+ (void)setAttributionHandler:(id)attributionHandler; + (void)setPackageHandlerBackoffStrategy:(ADJBackoffStrategy *)backoffStrategy; + (void)setSdkClickHandlerBackoffStrategy:(ADJBackoffStrategy *)backoffStrategy; + (void)setTesting:(BOOL)testing; diff --git a/Adjust/ADJAdjustFactory.m b/Adjust/ADJAdjustFactory.m index 70ad0b4d2..5be3e469b 100644 --- a/Adjust/ADJAdjustFactory.m +++ b/Adjust/ADJAdjustFactory.m @@ -7,16 +7,14 @@ // #import "ADJAdjustFactory.h" +#import "ADJActivityHandler.h" +#import "ADJPackageHandler.h" -static id internalPackageHandler = nil; -static id internalRequestHandler = nil; -static id internalActivityHandler = nil; static id internalLogger = nil; -static id internalAttributionHandler = nil; -static id internalSdkClickHandler = nil; static double internalSessionInterval = -1; static double intervalSubsessionInterval = -1; +static double internalRequestTimeout = -1; static NSTimeInterval internalTimerInterval = -1; static NSTimeInterval intervalTimerStart = -1; static ADJBackoffStrategy * packageHandlerBackoffStrategy = nil; @@ -35,37 +33,6 @@ @implementation ADJAdjustFactory -+ (id)packageHandlerForActivityHandler:(id)activityHandler - startsSending:(BOOL)startsSending { - if (internalPackageHandler == nil) { - return [ADJPackageHandler handlerWithActivityHandler:activityHandler startsSending:startsSending]; - } - - return [internalPackageHandler initWithActivityHandler:activityHandler startsSending:startsSending]; -} - -+ (id)requestHandlerForPackageHandler:(id)packageHandler - andActivityHandler:(id)activityHandler { - if (internalRequestHandler == nil) { - return [ADJRequestHandler handlerWithPackageHandler:packageHandler - andActivityHandler:activityHandler]; - } - return [internalRequestHandler initWithPackageHandler:packageHandler - andActivityHandler:activityHandler]; -} - -+ (id)activityHandlerWithConfig:(ADJConfig *)adjustConfig - savedPreLaunch:(ADJSavedPreLaunch *)savedPreLaunch -{ - if (internalActivityHandler == nil) { - return [ADJActivityHandler handlerWithConfig:adjustConfig - savedPreLaunch:savedPreLaunch - ]; - } - return [internalActivityHandler initWithConfig:adjustConfig - savedPreLaunch:savedPreLaunch]; -} - + (id)logger { if (internalLogger == nil) { // same instance of logger @@ -88,6 +55,13 @@ + (double)subsessionInterval { return intervalSubsessionInterval; } ++ (double)requestTimeout { + if (internalRequestTimeout == -1) { + return 60; // 60 second + } + return internalRequestTimeout; +} + + (NSTimeInterval)timerInterval { if (internalTimerInterval < 0) { return 60; // 1 minute @@ -123,28 +97,6 @@ + (ADJBackoffStrategy *)installSessionBackoffStrategy { return installSessionBackoffStrategy; } -+ (id)attributionHandlerForActivityHandler:(id)activityHandler - startsSending:(BOOL)startsSending -{ - if (internalAttributionHandler == nil) { - return [ADJAttributionHandler handlerWithActivityHandler:activityHandler - startsSending:startsSending]; - } - - return [internalAttributionHandler initWithActivityHandler:activityHandler - startsSending:startsSending]; -} - -+ (id)sdkClickHandlerForActivityHandler:(id)activityHandler - startsSending:(BOOL)startsSending -{ - if (internalSdkClickHandler == nil) { - return [ADJSdkClickHandler handlerWithActivityHandler:activityHandler startsSending:startsSending]; - } - - return [internalSdkClickHandler initWithActivityHandler:activityHandler startsSending:startsSending]; -} - + (BOOL)testing { return internalTesting; } @@ -172,18 +124,6 @@ + (NSString *)subscriptionUrl { return internalSubscriptionUrl; } -+ (void)setPackageHandler:(id)packageHandler { - internalPackageHandler = packageHandler; -} - -+ (void)setRequestHandler:(id)requestHandler { - internalRequestHandler = requestHandler; -} - -+ (void)setActivityHandler:(id)activityHandler { - internalActivityHandler = activityHandler; -} - + (void)setLogger:(id)logger { internalLogger = logger; } @@ -196,6 +136,10 @@ + (void)setSubsessionInterval:(double)subsessionInterval { intervalSubsessionInterval = subsessionInterval; } ++ (void)setRequestTimeout:(double)requestTimeout { + internalRequestTimeout = requestTimeout; +} + + (void)setTimerInterval:(NSTimeInterval)timerInterval { internalTimerInterval = timerInterval; } @@ -204,14 +148,6 @@ + (void)setTimerStart:(NSTimeInterval)timerStart { intervalTimerStart = timerStart; } -+ (void)setAttributionHandler:(id)attributionHandler { - internalAttributionHandler = attributionHandler; -} - -+ (void)setSdkClickHandler:(id)sdkClickHandler { - internalSdkClickHandler = sdkClickHandler; -} - + (void)setPackageHandlerBackoffStrategy:(ADJBackoffStrategy *)backoffStrategy { packageHandlerBackoffStrategy = backoffStrategy; } @@ -291,17 +227,13 @@ + (void)teardown:(BOOL)deleteState { [ADJActivityHandler deleteState]; [ADJPackageHandler deleteState]; } - internalPackageHandler = nil; - internalRequestHandler = nil; - internalActivityHandler = nil; internalLogger = nil; - internalAttributionHandler = nil; - internalSdkClickHandler = nil; internalSessionInterval = -1; intervalSubsessionInterval = -1; internalTimerInterval = -1; intervalTimerStart = -1; + internalRequestTimeout = -1; packageHandlerBackoffStrategy = nil; sdkClickHandlerBackoffStrategy = nil; internalTesting = NO; diff --git a/Adjust/ADJAttributionHandler.h b/Adjust/ADJAttributionHandler.h index 783e6f079..f7a5ff372 100644 --- a/Adjust/ADJAttributionHandler.h +++ b/Adjust/ADJAttributionHandler.h @@ -9,11 +9,14 @@ #import #import "ADJActivityHandler.h" #import "ADJActivityPackage.h" +#import "ADJRequestHandler.h" -@protocol ADJAttributionHandler +@interface ADJAttributionHandler : NSObject - (id)initWithActivityHandler:(id) activityHandler - startsSending:(BOOL)startsSending; + startsSending:(BOOL)startsSending + userAgent:(NSString *)userAgent + extraPath:(NSString *)extraPath; - (void)checkSessionResponse:(ADJSessionResponseData *)sessionResponseData; @@ -30,10 +33,3 @@ - (void)teardown; @end - -@interface ADJAttributionHandler : NSObject - -+ (id)handlerWithActivityHandler:(id)activityHandler - startsSending:(BOOL)startsSending; - -@end diff --git a/Adjust/ADJAttributionHandler.m b/Adjust/ADJAttributionHandler.m index 22f2b77da..d46c8f027 100644 --- a/Adjust/ADJAttributionHandler.m +++ b/Adjust/ADJAttributionHandler.m @@ -13,6 +13,7 @@ #import "NSString+ADJAdditions.h" #import "ADJTimerOnce.h" #import "ADJPackageBuilder.h" +#import "ADJUtil.h" static const char * const kInternalQueueName = "com.adjust.AttributionQueue"; static NSString * const kAttributionTimerName = @"Attribution timer"; @@ -20,35 +21,36 @@ @interface ADJAttributionHandler() @property (nonatomic, strong) dispatch_queue_t internalQueue; +@property (nonatomic, strong) ADJRequestHandler *requestHandler; @property (nonatomic, weak) id activityHandler; @property (nonatomic, weak) id logger; @property (nonatomic, strong) ADJTimerOnce *attributionTimer; @property (atomic, assign) BOOL paused; -@property (nonatomic, copy) NSString *basePath; @property (nonatomic, copy) NSString *lastInitiatedBy; @end @implementation ADJAttributionHandler - -+ (id)handlerWithActivityHandler:(id)activityHandler - startsSending:(BOOL)startsSending; -{ - return [[ADJAttributionHandler alloc] initWithActivityHandler:activityHandler - startsSending:startsSending]; -} - - (id)initWithActivityHandler:(id) activityHandler - startsSending:(BOOL)startsSending; + startsSending:(BOOL)startsSending + userAgent:(NSString *)userAgent + extraPath:(NSString *)extraPath { self = [super init]; if (self == nil) return nil; self.internalQueue = dispatch_queue_create(kInternalQueueName, DISPATCH_QUEUE_SERIAL); + self.requestHandler = [[ADJRequestHandler alloc] + initWithResponseCallback:self + extraPath:extraPath + baseUrl:[ADJAdjustFactory baseUrl] + gdprUrl:[ADJAdjustFactory gdprUrl] + subscriptionUrl:[ADJAdjustFactory subscriptionUrl] + userAgent:userAgent + requestTimeout:[ADJAdjustFactory requestTimeout]]; self.activityHandler = activityHandler; self.logger = ADJAdjustFactory.logger; self.paused = !startsSending; - self.basePath = [activityHandler getBasePath]; __weak __typeof__(self) weakSelf = self; self.attributionTimer = [ADJTimerOnce timerWithBlock:^{ __typeof__(self) strongSelf = weakSelf; @@ -190,25 +192,33 @@ - (void)requestAttributionI:(ADJAttributionHandler*)selfI { [selfI.logger verbose:@"%@", attributionPackage.extendedString]; - NSURL * baseUrl = [NSURL URLWithString:[ADJAdjustFactory baseUrl]]; - - [ADJUtil sendGetRequest:baseUrl - basePath:selfI.basePath - prefixErrorMessage:@"Failed to get attribution" - activityPackage:attributionPackage - responseDataHandler:^(ADJResponseData * responseData) - { - // Check if any package response contains information that user has opted out. - // If yes, disable SDK and flush any potentially stored packages that happened afterwards. - if (responseData.trackingState == ADJTrackingStateOptedOut) { - [selfI.activityHandler setTrackingStateOptedOut]; - return; - } - - if ([responseData isKindOfClass:[ADJAttributionResponseData class]]) { - [selfI checkAttributionResponse:(ADJAttributionResponseData*)responseData]; - } - }]; + NSDictionary *sendingParameters = @{ + @"sent_at": [ADJUtil formatSeconds1970:[NSDate.date timeIntervalSince1970]] + }; + + [selfI.requestHandler sendPackageByGET:attributionPackage + sendingParameters:sendingParameters]; +} + +- (void)responseCallback:(ADJResponseData *)responseData { + if (responseData.jsonResponse) { + [self.logger debug: + @"Got attribution JSON response with message: %@", responseData.message]; + } else { + [self.logger error: + @"Could not get attribution JSON response with message: %@", responseData.message]; + } + + // Check if any package response contains information that user has opted out. + // If yes, disable SDK and flush any potentially stored packages that happened afterwards. + if (responseData.trackingState == ADJTrackingStateOptedOut) { + [self.activityHandler setTrackingStateOptedOut]; + return; + } + + if ([responseData isKindOfClass:[ADJAttributionResponseData class]]) { + [self checkAttributionResponse:(ADJAttributionResponseData*)responseData]; + } } - (void)waitRequestAttributionWithDelayI:(ADJAttributionHandler*)selfI @@ -256,6 +266,7 @@ - (void)teardown { self.activityHandler = nil; self.logger = nil; self.attributionTimer = nil; + self.requestHandler = nil; } @end diff --git a/Adjust/ADJPackageBuilder.h b/Adjust/ADJPackageBuilder.h index 3b1349dd1..7d2723b67 100644 --- a/Adjust/ADJPackageBuilder.h +++ b/Adjust/ADJPackageBuilder.h @@ -62,4 +62,8 @@ setString:(NSString *)value forKey:(NSString *)key; ++ (void)parameters:(NSMutableDictionary *)parameters + setInt:(int)value + forKey:(NSString *)key; + @end diff --git a/Adjust/ADJPackageHandler.h b/Adjust/ADJPackageHandler.h index 12d4f3a01..06dc9d488 100644 --- a/Adjust/ADJPackageHandler.h +++ b/Adjust/ADJPackageHandler.h @@ -12,32 +12,23 @@ #import "ADJActivityHandler.h" #import "ADJResponseData.h" #import "ADJSessionParameters.h" +#import "ADJRequestHandler.h" -@protocol ADJPackageHandler +@interface ADJPackageHandler : NSObject - (id)initWithActivityHandler:(id)activityHandler - startsSending:(BOOL)startsSending; + startsSending:(BOOL)startsSending + userAgent:(NSString *)userAgent + extraPath:(NSString *)extraPath; - (void)addPackage:(ADJActivityPackage *)package; - (void)sendFirstPackage; -- (void)sendNextPackage:(ADJResponseData *)responseData; -- (void)closeFirstPackage:(ADJResponseData *)responseData - activityPackage:(ADJActivityPackage *)activityPackage; - (void)pauseSending; - (void)resumeSending; - (void)updatePackages:(ADJSessionParameters *)sessionParameters; - (void)flush; -- (NSString *)getBasePath; -- (NSString *)getGdprPath; -- (NSString *)getSubscriptionPath; - (void)teardown; + (void)deleteState; -@end - -@interface ADJPackageHandler : NSObject - -+ (id)handlerWithActivityHandler:(id)activityHandler - startsSending:(BOOL)startsSending; @end diff --git a/Adjust/ADJPackageHandler.m b/Adjust/ADJPackageHandler.m index c918f4dce..29942b1b7 100644 --- a/Adjust/ADJPackageHandler.m +++ b/Adjust/ADJPackageHandler.m @@ -6,7 +6,7 @@ // Copyright (c) 2013 adjust GmbH. All rights reserved. // -#import "ADJRequestHandler.h" +#import "ADJPackageHandler.h" #import "ADJActivityPackage.h" #import "ADJLogger.h" #import "ADJUtil.h" @@ -24,16 +24,13 @@ @interface ADJPackageHandler() @property (nonatomic, strong) dispatch_queue_t internalQueue; @property (nonatomic, strong) dispatch_semaphore_t sendingSemaphore; -@property (nonatomic, strong) id requestHandler; +@property (nonatomic, strong) ADJRequestHandler *requestHandler; @property (nonatomic, strong) NSMutableArray *packageQueue; @property (nonatomic, strong) ADJBackoffStrategy *backoffStrategy; @property (nonatomic, strong) ADJBackoffStrategy *backoffStrategyForInstallSession; @property (nonatomic, assign) BOOL paused; @property (nonatomic, weak) id activityHandler; @property (nonatomic, weak) id logger; -@property (nonatomic, copy) NSString *basePath; -@property (nonatomic, copy) NSString *gdprPath; -@property (nonatomic, copy) NSString *subscriptionPath; @property (nonatomic, assign) NSInteger lastPackageRetriesCount; @end @@ -41,14 +38,10 @@ @interface ADJPackageHandler() #pragma mark - @implementation ADJPackageHandler -+ (id)handlerWithActivityHandler:(id)activityHandler - startsSending:(BOOL)startsSending -{ - return [[ADJPackageHandler alloc] initWithActivityHandler:activityHandler startsSending:startsSending]; -} - - (id)initWithActivityHandler:(id)activityHandler startsSending:(BOOL)startsSending + userAgent:(NSString *)userAgent + extraPath:(NSString *)extraPath { self = [super init]; if (self == nil) return nil; @@ -56,9 +49,6 @@ - (id)initWithActivityHandler:(id)activityHandler self.internalQueue = dispatch_queue_create(kInternalQueueName, DISPATCH_QUEUE_SERIAL); self.backoffStrategy = [ADJAdjustFactory packageHandlerBackoffStrategy]; self.backoffStrategyForInstallSession = [ADJAdjustFactory installSessionBackoffStrategy]; - self.basePath = [activityHandler getBasePath]; - self.gdprPath = [activityHandler getGdprPath]; - self.subscriptionPath = [activityHandler getSubscriptionPath]; self.lastPackageRetriesCount = 0; [ADJUtil launchInQueue:self.internalQueue @@ -66,7 +56,9 @@ - (id)initWithActivityHandler:(id)activityHandler block:^(ADJPackageHandler * selfI) { [selfI initI:selfI activityHandler:activityHandler - startsSending:startsSending]; + startsSending:startsSending + userAgent:userAgent + extraPath:extraPath]; }]; return self; @@ -88,6 +80,25 @@ - (void)sendFirstPackage { }]; } +- (void)responseCallback:(ADJResponseData *)responseData { + if (responseData.jsonResponse) { + [self.logger debug:@"Got JSON response with message: %@", responseData.message]; + } else { + [self.logger error:@"Could not get JSON response with message: %@", responseData.message]; + } + // Check if any package response contains information that user has opted out. + // If yes, disable SDK and flush any potentially stored packages that happened afterwards. + if (responseData.trackingState == ADJTrackingStateOptedOut) { + [self.activityHandler setTrackingStateOptedOut]; + return; + } + if (responseData.jsonResponse == nil) { + [self closeFirstPackage:responseData]; + } else { + [self sendNextPackage:responseData]; + } +} + - (void)sendNextPackage:(ADJResponseData *)responseData { self.lastPackageRetriesCount = 0; @@ -101,28 +112,14 @@ - (void)sendNextPackage:(ADJResponseData *)responseData { } - (void)closeFirstPackage:(ADJResponseData *)responseData - activityPackage:(ADJActivityPackage *)activityPackage { responseData.willRetry = YES; [self.activityHandler finishedTracking:responseData]; - dispatch_block_t work = ^{ - [self.logger verbose:@"Package handler can send"]; - dispatch_semaphore_signal(self.sendingSemaphore); - - [self sendFirstPackage]; - }; - - if (activityPackage == nil) { - self.lastPackageRetriesCount = 0; - work(); - return; - } - self.lastPackageRetriesCount++; NSTimeInterval waitTime; - if ([activityPackage activityKind] == ADJActivityKindSession && [ADJUserDefaults getInstallTracked] == NO) { + if (responseData.activityKind == ADJActivityKindSession && [ADJUserDefaults getInstallTracked] == NO) { waitTime = [ADJUtil waitingTime:self.lastPackageRetriesCount backoffStrategy:self.backoffStrategyForInstallSession]; } else { waitTime = [ADJUtil waitingTime:self.lastPackageRetriesCount backoffStrategy:self.backoffStrategy]; @@ -130,7 +127,16 @@ - (void)closeFirstPackage:(ADJResponseData *)responseData NSString *waitTimeFormatted = [ADJUtil secondsNumberFormat:waitTime]; [self.logger verbose:@"Waiting for %@ seconds before retrying the %d time", waitTimeFormatted, self.lastPackageRetriesCount]; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(waitTime * NSEC_PER_SEC)), self.internalQueue, work); + dispatch_after + (dispatch_time(DISPATCH_TIME_NOW, (int64_t)(waitTime * NSEC_PER_SEC)), + self.internalQueue, + ^{ + [self.logger verbose:@"Package handler finished waiting"]; + + dispatch_semaphore_signal(self.sendingSemaphore); + + [self sendFirstPackage]; + }); } - (void)pauseSending { @@ -159,26 +165,11 @@ - (void)flush { }]; } -- (NSString *)getBasePath { - return _basePath; -} - -- (NSString *)getGdprPath { - return _gdprPath; -} - -- (NSString *)getSubscriptionPath { - return _subscriptionPath; -} - - (void)teardown { [ADJAdjustFactory.logger verbose:@"ADJPackageHandler teardown"]; if (self.sendingSemaphore != nil) { dispatch_semaphore_signal(self.sendingSemaphore); } - if (self.requestHandler != nil) { - [self.requestHandler teardown]; - } [self teardownPackageQueueS]; self.internalQueue = nil; self.sendingSemaphore = nil; @@ -200,11 +191,19 @@ + (void)deletePackageQueue { - (void)initI:(ADJPackageHandler *)selfI activityHandler:(id)activityHandler startsSending:(BOOL)startsSending + userAgent:(NSString *)userAgent + extraPath:(NSString *)extraPath { selfI.activityHandler = activityHandler; selfI.paused = !startsSending; - selfI.requestHandler = [ADJAdjustFactory requestHandlerForPackageHandler:selfI - andActivityHandler:selfI.activityHandler]; + selfI.requestHandler = [[ADJRequestHandler alloc] + initWithResponseCallback:self + extraPath:extraPath + baseUrl:[ADJAdjustFactory baseUrl] + gdprUrl:[ADJAdjustFactory gdprUrl] + subscriptionUrl:[ADJAdjustFactory subscriptionUrl] + userAgent:userAgent + requestTimeout:[ADJAdjustFactory requestTimeout]]; selfI.logger = ADJAdjustFactory.logger; selfI.sendingSemaphore = dispatch_semaphore_create(1); [selfI readPackageQueueI:selfI]; @@ -242,8 +241,18 @@ - (void)sendFirstI:(ADJPackageHandler *)selfI return; } - [selfI.requestHandler sendPackage:activityPackage - queueSize:queueSize - 1]; + NSMutableDictionary *sendingParameters = [NSMutableDictionary dictionaryWithCapacity:2]; + if (queueSize - 1 > 0) { + [ADJPackageBuilder parameters:sendingParameters + setInt:(int)queueSize - 1 + forKey:@"queue_size"]; + } + [ADJPackageBuilder parameters:sendingParameters + setString:[ADJUtil formatSeconds1970:[NSDate.date timeIntervalSince1970]] + forKey:@"sent_at"]; + + [selfI.requestHandler sendPackageByPOST:activityPackage + sendingParameters:[sendingParameters copy]]; } - (void)sendNextI:(ADJPackageHandler *)selfI { diff --git a/Adjust/ADJRequestHandler.h b/Adjust/ADJRequestHandler.h index 5dc8d1772..816ad331e 100644 --- a/Adjust/ADJRequestHandler.h +++ b/Adjust/ADJRequestHandler.h @@ -7,23 +7,26 @@ // #import -#import "ADJPackageHandler.h" +#import "ADJActivityPackage.h" -@protocol ADJRequestHandler - -- (id)initWithPackageHandler:(id)packageHandler - andActivityHandler:(id)activityHandler; - -- (void)sendPackage:(ADJActivityPackage *)activityPackage - queueSize:(NSUInteger)queueSize; +@protocol ADJResponseCallback +- (void)responseCallback:(ADJResponseData *)responseData; +@end -- (void)teardown; +@interface ADJRequestHandler : NSObject -@end +- (id)initWithResponseCallback:(id)responseCallback + extraPath:(NSString *)extraPath + baseUrl:(NSString *)baseUrl + gdprUrl:(NSString *)gdprUrl + subscriptionUrl:(NSString *)subscriptionUrl + userAgent:(NSString *)userAgent + requestTimeout:(double)requestTimeout; -@interface ADJRequestHandler : NSObject +- (void)sendPackageByPOST:(ADJActivityPackage *)activityPackage + sendingParameters:(NSDictionary *)sendingParameters; -+ (id)handlerWithPackageHandler:(id)packageHandler - andActivityHandler:(id)activityHandler; +- (void)sendPackageByGET:(ADJActivityPackage *)activityPackage + sendingParameters:(NSDictionary *)sendingParameters; @end diff --git a/Adjust/ADJRequestHandler.m b/Adjust/ADJRequestHandler.m index ec2fb6eb1..de2232918 100644 --- a/Adjust/ADJRequestHandler.m +++ b/Adjust/ADJRequestHandler.m @@ -14,23 +14,21 @@ #import "ADJActivityPackage.h" #import "NSString+ADJAdditions.h" -static const char * const kInternalQueueName = "io.adjust.RequestQueue"; - @interface ADJRequestHandler() -@property (nonatomic, strong) dispatch_queue_t internalQueue; +@property (nonatomic, copy) NSString *baseUrlString; +@property (nonatomic, copy) NSString *gdrpUrlString; +@property (nonatomic, copy) NSString *subscriptionUrlString; +@property (nonatomic, copy) NSString *extraPath; +@property (nonatomic, copy) NSString *userAgent; +@property (nonatomic, assign) double requestTimeout; +@property (nonatomic, weak) id responseCallback; @property (nonatomic, weak) id logger; -@property (nonatomic, weak) id packageHandler; - -@property (nonatomic, weak) id activityHandler; - -@property (nonatomic, copy) NSString *basePath; - -@property (nonatomic, copy) NSString *gdprPath; +@property (nonatomic, copy) NSURLSessionConfiguration *defaultSessionConfiguration; -@property (nonatomic, copy) NSString *subscriptionPath; +@property (nonatomic, strong) NSHashTable *exceptionKeys; @end @@ -38,95 +36,497 @@ @implementation ADJRequestHandler #pragma mark - Public methods -+ (ADJRequestHandler *)handlerWithPackageHandler:(id)packageHandler - andActivityHandler:(id)activityHandler { - return [[ADJRequestHandler alloc] initWithPackageHandler:packageHandler - andActivityHandler:activityHandler]; -} - -- (id)initWithPackageHandler:(id)packageHandler - andActivityHandler:(id)activityHandler { +- (id)initWithResponseCallback:(id)responseCallback + extraPath:(NSString *)extraPath + baseUrl:(NSString *)baseUrl + gdprUrl:(NSString *)gdprUrl + subscriptionUrl:(NSString *)subscriptionUrl + userAgent:(NSString *)userAgent + requestTimeout:(double)requestTimeout +{ self = [super init]; if (self == nil) { return nil; } - - self.internalQueue = dispatch_queue_create(kInternalQueueName, DISPATCH_QUEUE_SERIAL); - self.packageHandler = packageHandler; - self.activityHandler = activityHandler; + self.baseUrlString = baseUrl; + self.gdrpUrlString = gdprUrl; + self.subscriptionUrlString = subscriptionUrl; + self.extraPath = extraPath ?: @""; + self.userAgent = userAgent; + self.requestTimeout = requestTimeout; + self.responseCallback = responseCallback; + self.logger = ADJAdjustFactory.logger; - self.basePath = [packageHandler getBasePath]; - self.gdprPath = [packageHandler getGdprPath]; - self.subscriptionPath = [packageHandler getSubscriptionPath]; + self.defaultSessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; + + self.exceptionKeys = + [NSHashTable hashTableWithOptions:NSHashTableStrongMemory]; + [self.exceptionKeys addObject:@"event_callback_id"]; + [self.exceptionKeys addObject:@"secret_id"]; + [self.exceptionKeys addObject:@"signature"]; + [self.exceptionKeys addObject:@"headers_id"]; + [self.exceptionKeys addObject:@"native_version"]; + [self.exceptionKeys addObject:@"algorithm"]; + [self.exceptionKeys addObject:@"app_secret"]; return self; } -- (void)sendPackage:(ADJActivityPackage *)activityPackage queueSize:(NSUInteger)queueSize { - [ADJUtil launchInQueue:self.internalQueue - selfInject:self - block:^(ADJRequestHandler* selfI) { - [selfI sendI:selfI activityPackage:activityPackage queueSize:queueSize]; - }]; +- (void)sendPackageByPOST:(ADJActivityPackage *)activityPackage + sendingParameters:(NSDictionary *)sendingParameters +{ + NSDictionary *parameters = [[NSDictionary alloc] + initWithDictionary:activityPackage.parameters + copyItems:YES]; + NSString *path = [activityPackage.path copy]; + NSString *clientSdk = [activityPackage.clientSdk copy]; + ADJActivityKind activityKind = activityPackage.activityKind; + + NSString *urlHostString; + if (activityKind == ADJActivityKindGdpr) { + urlHostString = self.gdrpUrlString; + } else if (activityKind == ADJActivityKindSubscription) { + urlHostString = self.subscriptionUrlString; + } else { + urlHostString = self.baseUrlString; + } + + ADJResponseData *responseData = + [ADJResponseData buildResponseData:activityPackage]; + + NSString * authorizationHeader = [self buildAuthorizationHeader:parameters activityKind:activityKind]; + + NSMutableURLRequest *urlRequest = + [self requestForPostPackage:path + clientSdk:clientSdk + parameters:parameters + urlHostString:urlHostString + sendingParameters:sendingParameters]; + + [self sendRequest:urlRequest + authorizationHeader:authorizationHeader + responseData:responseData]; } -- (void)teardown { - [ADJAdjustFactory.logger verbose:@"ADJRequestHandler teardown"]; - - self.logger = nil; - self.internalQueue = nil; - self.packageHandler = nil; - self.activityHandler = nil; +- (void)sendPackageByGET:(ADJActivityPackage *)activityPackage + sendingParameters:(NSDictionary *)sendingParameters +{ + NSDictionary *parameters = [[NSDictionary alloc] + initWithDictionary:activityPackage.parameters + copyItems:YES]; + NSString *path = [activityPackage.path copy]; + NSString *clientSdk = [activityPackage.clientSdk copy]; + ADJActivityKind activityKind = activityPackage.activityKind; + + ADJResponseData *responseData = + [ADJResponseData buildResponseData:activityPackage]; + + NSString * authorizationHeader = [self buildAuthorizationHeader:parameters activityKind:activityKind]; + + NSMutableURLRequest *urlRequest = + [self requestForGetPackage:path + clientSdk:clientSdk + parameters:parameters + urlHostString:self.baseUrlString + sendingParameters:sendingParameters]; + + [self sendRequest:urlRequest + authorizationHeader:authorizationHeader + responseData:responseData]; } -#pragma mark - Private & helper methods +#pragma mark Internal methods +- (void)sendRequest:(NSMutableURLRequest *)request +authorizationHeader:(NSString *)authorizationHeader + responseData:(ADJResponseData *)responseData +{ + if (authorizationHeader != nil) { + [ADJAdjustFactory.logger debug:@"authorizationHeader %@", authorizationHeader]; + [request setValue:authorizationHeader forHTTPHeaderField:@"Authorization"]; + } + if (self.userAgent != nil) { + [request setValue:self.userAgent forHTTPHeaderField:@"User-Agent"]; + } -- (void)sendI:(ADJRequestHandler *)selfI activityPackage:(ADJActivityPackage *)activityPackage queueSize:(NSUInteger)queueSize { - NSURL *url; + Class NSURLSessionClass = NSClassFromString(@"NSURLSession"); + if (NSURLSessionClass != nil) { + [self sendNSURLSessionRequest:request + responseData:responseData]; + } else { + [self sendNSURLConnectionRequest:request + responseData:responseData]; + } +} + +- (void)sendNSURLSessionRequest:(NSMutableURLRequest *)request + responseData:(ADJResponseData *)responseData +{ + NSURLSession *session = [NSURLSession sessionWithConfiguration:self.defaultSessionConfiguration]; + NSURLSessionDataTask *task = + [session dataTaskWithRequest:request + completionHandler: + ^(NSData *data, NSURLResponse *response, NSError *error) + { + [self handleResponseWithData:data + response:(NSHTTPURLResponse *)response + error:error + responseData:responseData]; + }]; + [task resume]; + [session finishTasksAndInvalidate]; +} - if (activityPackage.activityKind == ADJActivityKindGdpr) { - NSString *gdprUrl = [ADJAdjustFactory gdprUrl]; - if (selfI.gdprPath != nil) { - url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", gdprUrl, selfI.gdprPath]]; - } else { - url = [NSURL URLWithString:gdprUrl]; +- (void)sendNSURLConnectionRequest:(NSMutableURLRequest *)request + responseData:(ADJResponseData *)responseData +{ + dispatch_async + (dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), + ^{ + NSError *error = nil; + NSURLResponse *response = nil; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSData *data = [NSURLConnection sendSynchronousRequest:request + returningResponse:&response + error:&error]; + #pragma clang diagnostic pop + [self handleResponseWithData:data + response:(NSHTTPURLResponse *)response + error:error + responseData:responseData]; + }); +} + +- (void)handleResponseWithData:(NSData *)data + response:(NSHTTPURLResponse *)urlResponse + error:(NSError *)responseError + responseData:(ADJResponseData *)responseData +{ + // Connection error + if (responseError != nil) { + responseData.message = responseError.description; + [self.responseCallback responseCallback:responseData]; + return; + } + if ([ADJUtil isNull:data]) { + responseData.message = @"nil response data"; + [self.responseCallback responseCallback:responseData]; + return; + } + + NSString *responseString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] adjTrim]; + NSInteger statusCode = urlResponse.statusCode; + [self.logger verbose:@"Response: %@", responseString]; + + if (statusCode == 429) { + responseData.message = @"Too frequent requests to the endpoint (429)"; + [self.responseCallback responseCallback:responseData]; + return; + } + + [self saveJsonResponse:data responseData:responseData]; + if (responseData.jsonResponse == nil) { + [self.responseCallback responseCallback:responseData]; + return; + } + + NSString *messageResponse = [responseData.jsonResponse objectForKey:@"message"]; + responseData.message = messageResponse; + responseData.timeStamp = [responseData.jsonResponse objectForKey:@"timestamp"]; + responseData.adid = [responseData.jsonResponse objectForKey:@"adid"]; + + NSString *trackingState = [responseData.jsonResponse objectForKey:@"tracking_state"]; + if (trackingState != nil) { + if ([trackingState isEqualToString:@"opted_out"]) { + responseData.trackingState = ADJTrackingStateOptedOut; } - } else if (activityPackage.activityKind == ADJActivityKindSubscription) { - NSString *subscriptionUrl = [ADJAdjustFactory subscriptionUrl]; - if (selfI.subscriptionPath != nil) { - url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", subscriptionUrl, selfI.subscriptionPath]]; - } else { - url = [NSURL URLWithString:subscriptionUrl]; + } + + if (statusCode == 200) { + responseData.success = YES; + } + + [self.responseCallback responseCallback:responseData]; +} +#pragma mark - URL Request +- (NSMutableURLRequest *) + requestForPostPackage:(NSString *)path + clientSdk:(NSString *)clientSdk + parameters:(NSDictionary *)parameters + urlHostString:(NSString *)urlHostString + sendingParameters: + (NSDictionary *)sendingParameters +{ + NSString *urlString = [NSString stringWithFormat:@"%@%@%@", + urlHostString, self.extraPath, path]; + + [self.logger debug:@"TORMV Post final url: %@", urlString]; + + NSURL *url = [NSURL URLWithString:urlString]; + //NSURL *url = [baseUrl URLByAppendingPathComponent:path]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + request.timeoutInterval = self.requestTimeout; + request.HTTPMethod = @"POST"; + [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; + [request setValue:clientSdk forHTTPHeaderField:@"Client-Sdk"]; + + NSUInteger sendingParametersCount = sendingParameters? sendingParameters.count : 0; + NSMutableArray *kvParameters = + [NSMutableArray arrayWithCapacity: + parameters.count + sendingParametersCount]; + + [self injectParameters:parameters + kvArray:kvParameters]; + [self injectParameters:sendingParameters + kvArray:kvParameters]; + + NSString *bodyString = [kvParameters componentsJoinedByString:@"&"]; + NSData *body = [NSData dataWithBytes:bodyString.UTF8String length:bodyString.length]; + [request setHTTPBody:body]; + return request; +} + +- (NSMutableURLRequest *) + requestForGetPackage:(NSString *)path + clientSdk:(NSString *)clientSdk + parameters:(NSDictionary *)parameters + urlHostString:(NSString *)urlHostString + sendingParameters:(NSDictionary *)sendingParameters +{ + NSUInteger sendingParametersCount = sendingParameters? sendingParameters.count : 0; + NSMutableArray *kvParameters = + [NSMutableArray arrayWithCapacity: + parameters.count + sendingParametersCount]; + + [self injectParameters:parameters + kvArray:kvParameters]; + [self injectParameters:sendingParameters + kvArray:kvParameters]; + + NSString *queryStringParameters = [kvParameters componentsJoinedByString:@"&"]; + + NSString *urlString = + [NSString stringWithFormat:@"%@%@%@?%@", + urlHostString, self.extraPath, path, queryStringParameters]; + + [self.logger debug:@"TORMV Get final url: %@", urlString]; + + NSURL *url = [NSURL URLWithString:urlString]; + + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + request.timeoutInterval = self.requestTimeout; + request.HTTPMethod = @"GET"; + [request setValue:clientSdk forHTTPHeaderField:@"Client-Sdk"]; + return request; +} + +- (void) + injectParameters:(NSDictionary *)parameters + kvArray:(NSMutableArray *)kvArray +{ + if (parameters == nil || parameters.count == 0) { + return; + } + + for (NSString *key in parameters) { + if ([self.exceptionKeys containsObject:key]) { + continue; } + NSString *value = [parameters objectForKey:key]; + NSString *escapedValue = [value adjUrlEncode]; + NSString *escapedKey = [key adjUrlEncode]; + NSString *pair = [NSString stringWithFormat:@"%@=%@", escapedKey, escapedValue]; + [kvArray addObject:pair]; + } +} + +#pragma mark - Authorization Header +- (NSString *)buildAuthorizationHeader:(NSDictionary *)parameters + activityKind:(ADJActivityKind)activityKind +{ + NSString *secretId = [parameters objectForKey:@"secret_id"]; + NSString *signature = [parameters objectForKey:@"signature"]; + NSString *headersId = [parameters objectForKey:@"headers_id"]; + NSString *nativeVersion = [parameters objectForKey:@"native_version"]; + NSString *algorithm = [parameters objectForKey:@"algorithm"]; + NSString *authorizationHeader = [self buildAuthorizationHeaderV2:signature + secretId:secretId + headersId:headersId + nativeVersion:nativeVersion + algorithm:algorithm]; + if (authorizationHeader != nil) { + return authorizationHeader; + } + + NSString * appSecret = [parameters objectForKey:@"app_secret"]; + return [self buildAuthorizationHeaderV1:appSecret + secretId:secretId + parameters:parameters + activityKind:activityKind]; +} + +- (NSString *)buildAuthorizationHeaderV2:(NSString *)signature + secretId:(NSString *)secretId + headersId:(NSString *)headersId + nativeVersion:(NSString *)nativeVersion + algorithm:(NSString *)algorithm +{ + if (secretId == nil || signature == nil || headersId == nil) { + return nil; + } + + NSString * signatureHeader = [NSString stringWithFormat:@"signature=\"%@\"", signature]; + NSString * secretIdHeader = [NSString stringWithFormat:@"secret_id=\"%@\"", secretId]; + NSString * idHeader = [NSString stringWithFormat:@"headers_id=\"%@\"", headersId]; + NSString * algorithmHeader = [NSString stringWithFormat:@"algorithm=\"%@\"", algorithm != nil ? algorithm : @"adj1"]; + + NSString * authorizationHeader = [NSString stringWithFormat:@"Signature %@,%@,%@,%@", + signatureHeader, secretIdHeader, algorithmHeader, idHeader]; + + if (nativeVersion == nil) { + return [authorizationHeader stringByAppendingFormat:@",native_version=\"\""]; + } + return [authorizationHeader stringByAppendingFormat:@",native_version=\"%@\"", nativeVersion]; +} + +- (NSString *)buildAuthorizationHeaderV1:(NSString *)appSecret + secretId:(NSString *)secretId + parameters:(NSDictionary *)parameters + activityKind:(ADJActivityKind)activityKind +{ + if (appSecret == nil) { + return nil; + } + + NSString *activityKindS = [ADJActivityKindUtil activityKindToString:activityKind]; + NSDictionary *signatureParameters = [self buildSignatureParameters:parameters + appSecret:appSecret + activityKindS:activityKindS]; + NSMutableString *fields = [[NSMutableString alloc] initWithCapacity:5]; + NSMutableString *clearSignature = [[NSMutableString alloc] initWithCapacity:5]; + + // signature part of header + for (NSDictionary *key in signatureParameters) { + [fields appendFormat:@"%@ ", key]; + NSString *value = [signatureParameters objectForKey:key]; + [clearSignature appendString:value]; + } + + NSString *secretIdHeader = [NSString stringWithFormat:@"secret_id=\"%@\"", secretId]; + // algorithm part of header + NSString *algorithm = @"sha256"; + NSString *signature = [clearSignature adjSha256]; + NSString *signatureHeader = [NSString stringWithFormat:@"signature=\"%@\"", signature]; + NSString *algorithmHeader = [NSString stringWithFormat:@"algorithm=\"%@\"", algorithm]; + // fields part of header + // Remove last empty space. + if (fields.length > 0) { + [fields deleteCharactersInRange:NSMakeRange(fields.length - 1, 1)]; + } + + NSString *fieldsHeader = [NSString stringWithFormat:@"headers=\"%@\"", fields]; + // putting it all together + NSString *authorizationHeader = [NSString stringWithFormat:@"Signature %@,%@,%@,%@", + secretIdHeader, + signatureHeader, + algorithmHeader, + fieldsHeader]; + return authorizationHeader; +} + +- (NSDictionary *)buildSignatureParameters:(NSDictionary *)parameters + appSecret:(NSString *)appSecret + activityKindS:(NSString *)activityKindS { + NSString *appSecretName = @"app_secret"; + NSString *sourceName = @"source"; + NSString *payloadName = @"payload"; + NSString *activityKindName = @"activity_kind"; + NSString *activityKindValue = activityKindS; + NSString *createdAtName = @"created_at"; + NSString *createdAtValue = [parameters objectForKey:createdAtName]; + NSString *deviceIdentifierName = [self getValidIdentifier:parameters]; + NSString *deviceIdentifierValue = [parameters objectForKey:deviceIdentifierName]; + NSMutableDictionary *signatureParameters = [[NSMutableDictionary alloc] initWithCapacity:6]; + + [self checkAndAddEntry:signatureParameters key:appSecretName value:appSecret]; + [self checkAndAddEntry:signatureParameters key:createdAtName value:createdAtValue]; + [self checkAndAddEntry:signatureParameters key:activityKindName value:activityKindValue]; + [self checkAndAddEntry:signatureParameters key:deviceIdentifierName value:deviceIdentifierValue]; + [self checkAndAddEntry:signatureParameters key:sourceName value:parameters[sourceName]]; + [self checkAndAddEntry:signatureParameters key:payloadName value:parameters[payloadName]]; + + return signatureParameters; +} + +- (void)checkAndAddEntry:(NSMutableDictionary *)parameters + key:(NSString *)key + value:(NSString *)value { + if (key == nil) { + return; + } + + if (value == nil) { + return; + } + + [parameters setObject:value forKey:key]; +} + +- (NSString *)getValidIdentifier:(NSDictionary *)parameters { + NSString *idfaName = @"idfa"; + NSString *persistentUUIDName = @"persistent_ios_uuid"; + NSString *uuidName = @"ios_uuid"; + + if ([parameters objectForKey:idfaName] != nil) { + return idfaName; + } + if ([parameters objectForKey:persistentUUIDName] != nil) { + return persistentUUIDName; + } + if ([parameters objectForKey:uuidName] != nil) { + return uuidName; + } + return nil; +} + +#pragma mark - JSON +- (void)saveJsonResponse:(NSData *)jsonData responseData:(ADJResponseData *)responseData { + NSError *error = nil; + NSException *exception = nil; + NSDictionary *jsonDict = + [self buildJsonDict:jsonData exceptionPtr:&exception errorPtr:&error]; + + if (exception != nil) { + responseData.message = + [NSString stringWithFormat: + @"Failed to parse json response. (%@)", exception.description]; + } else if (error != nil) { + responseData.message = + [NSString stringWithFormat: + @"Failed to parse json response. (%@)", error.localizedDescription]; + } else if ([ADJUtil isNull:jsonDict]) { + responseData.message = [NSString stringWithFormat:@"Failed to parse json response "]; } else { - NSString *baseUrl = [ADJAdjustFactory baseUrl]; - if (selfI.basePath != nil) { - url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", baseUrl, selfI.basePath]]; - } else { - url = [NSURL URLWithString:baseUrl]; - } + responseData.jsonResponse = jsonDict; + } +} + +- (NSDictionary *)buildJsonDict:(NSData *)jsonData + exceptionPtr:(NSException **)exceptionPtr + errorPtr:(NSError **)error { + if (jsonData == nil) { + return nil; } - [ADJUtil sendPostRequest:url - queueSize:queueSize - prefixErrorMessage:activityPackage.failureMessage - suffixErrorMessage:@"Will retry later" - activityPackage:activityPackage - responseDataHandler:^(ADJResponseData *responseData) { - // Check if any package response contains information that user has opted out. - // If yes, disable SDK and flush any potentially stored packages that happened afterwards. - if (responseData.trackingState == ADJTrackingStateOptedOut) { - [selfI.activityHandler setTrackingStateOptedOut]; - return; - } - if (responseData.jsonResponse == nil) { - [selfI.packageHandler closeFirstPackage:responseData activityPackage:activityPackage]; - return; - } - - [selfI.packageHandler sendNextPackage:responseData]; - }]; + NSDictionary *jsonDict = nil; + @try { + jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:error]; + } @catch (NSException *ex) { + *exceptionPtr = ex; + return nil; + } + return jsonDict; } @end diff --git a/Adjust/ADJResponseData.h b/Adjust/ADJResponseData.h index 57b209398..d1b7c4fa0 100644 --- a/Adjust/ADJResponseData.h +++ b/Adjust/ADJResponseData.h @@ -39,9 +39,9 @@ typedef NS_ENUM(int, ADJTrackingState) { @property (nonatomic, copy) ADJAttribution *attribution; -- (id)init; +@property (nonatomic, copy) NSDictionary *sendingParameters; -+ (ADJResponseData *)responseData; +@property (nonatomic, strong) ADJActivityPackage *sdkClickPackage; + (id)buildResponseData:(ADJActivityPackage *)activityPackage; @@ -68,9 +68,8 @@ typedef NS_ENUM(int, ADJTrackingState) { - (ADJEventFailure *)failureResponseData; -- (id)initWithActivityPackage:(ADJActivityPackage *)activityPackage; - -+ (ADJResponseData *)responseDataWithActivityPackage:(ADJActivityPackage *)activityPackage; +- (id)initWithEventToken:(NSString *)eventToken + callbackId:(NSString *)callbackId; @end diff --git a/Adjust/ADJResponseData.m b/Adjust/ADJResponseData.m index 986043723..16f81a63e 100644 --- a/Adjust/ADJResponseData.m +++ b/Adjust/ADJResponseData.m @@ -11,13 +11,14 @@ @implementation ADJResponseData -- (id)init { +- (id)init +{ self = [super init]; if (self == nil) { return nil; } - + return self; } @@ -42,9 +43,16 @@ + (id)buildResponseData:(ADJActivityPackage *)activityPackage { break; case ADJActivityKindClick: responseData = [[ADJSdkClickResponseData alloc] init]; + responseData.sdkClickPackage = activityPackage; break; case ADJActivityKindEvent: - responseData = [[ADJEventResponseData alloc] initWithActivityPackage:activityPackage]; + responseData = [[ADJEventResponseData alloc] + initWithEventToken: + [activityPackage.parameters + objectForKey:@"event_token"] + callbackId: + [activityPackage.parameters + objectForKey:@"event_callback_id"]]; break; case ADJActivityKindAttribution: responseData = [[ADJAttributionResponseData alloc] init]; @@ -73,7 +81,6 @@ - (id)copyWithZone:(NSZone *)zone { copy.message = [self.message copyWithZone:zone]; copy.timeStamp = [self.timeStamp copyWithZone:zone]; copy.adid = [self.adid copyWithZone:zone]; - copy.success = self.success; copy.willRetry = self.willRetry; copy.trackingState = self.trackingState; copy.jsonResponse = [self.jsonResponse copyWithZone:zone]; @@ -87,16 +94,6 @@ - (id)copyWithZone:(NSZone *)zone { @implementation ADJSessionResponseData -- (id)initWithActivityPackage:(ADJActivityPackage *)activityPackage { - self = [super init]; - - if (self == nil) { - return nil; - } - - return self; -} - - (ADJSessionSuccess *)successResponseData { ADJSessionSuccess *successResponseData = [ADJSessionSuccess sessionSuccessResponseData]; @@ -133,19 +130,17 @@ @implementation ADJSdkClickResponseData @implementation ADJEventResponseData -+ (ADJEventResponseData *)responseDataWithActivityPackage:(ADJActivityPackage *)activityPackage { - return [[ADJEventResponseData alloc] initWithActivityPackage:activityPackage]; -} - -- (id)initWithActivityPackage:(ADJActivityPackage *)activityPackage { +- (id)initWithEventToken:(NSString *)eventToken + callbackId:(NSString *)callbackId +{ self = [super init]; if (self == nil) { return nil; } - self.eventToken = [activityPackage.parameters objectForKey:@"event_token"]; - self.callbackId = [activityPackage.parameters objectForKey:@"event_callback_id"]; + self.eventToken = eventToken; + self.callbackId = callbackId; return self; } @@ -196,16 +191,6 @@ - (id)copyWithZone:(NSZone *)zone { @implementation ADJAttributionResponseData -- (id)initWithActivityPackage:(ADJActivityPackage *)activityPackage { - self = [super init]; - - if (self == nil) { - return nil; - } - - return self; -} - - (id)copyWithZone:(NSZone *)zone { ADJAttributionResponseData *copy = [super copyWithZone:zone]; diff --git a/Adjust/ADJSdkClickHandler.h b/Adjust/ADJSdkClickHandler.h index b74ddfda7..dbd49720d 100644 --- a/Adjust/ADJSdkClickHandler.h +++ b/Adjust/ADJSdkClickHandler.h @@ -9,21 +9,17 @@ #import #import "ADJActivityPackage.h" #import "ADJActivityHandler.h" +#import "ADJRequestHandler.h" -@protocol ADJSdkClickHandler +@interface ADJSdkClickHandler : NSObject - (id)initWithActivityHandler:(id)activityHandler - startsSending:(BOOL)startsSending; + startsSending:(BOOL)startsSending + userAgent:(NSString *)userAgent + extraPath:(NSString *)extraPath; - (void)pauseSending; - (void)resumeSending; - (void)sendSdkClick:(ADJActivityPackage *)sdkClickPackage; - (void)teardown; @end - -@interface ADJSdkClickHandler : NSObject - -+ (id)handlerWithActivityHandler:(id)activityHandler - startsSending:(BOOL)startsSending; - -@end diff --git a/Adjust/ADJSdkClickHandler.m b/Adjust/ADJSdkClickHandler.m index 73ff01e7e..830e97b0f 100644 --- a/Adjust/ADJSdkClickHandler.m +++ b/Adjust/ADJSdkClickHandler.m @@ -16,9 +16,9 @@ @interface ADJSdkClickHandler() -@property (nonatomic, copy) NSString *basePath; @property (nonatomic, strong) NSMutableArray *packageQueue; @property (nonatomic, strong) dispatch_queue_t internalQueue; +@property (nonatomic, strong) ADJRequestHandler *requestHandler; @property (nonatomic, assign) BOOL paused; @property (nonatomic, strong) ADJBackoffStrategy *backoffStrategy; @@ -32,18 +32,13 @@ @interface ADJSdkClickHandler() @implementation ADJSdkClickHandler -#pragma mark - Public class methods - -+ (id)handlerWithActivityHandler:(id)activityHandler - startsSending:(BOOL)startsSending { - return [[ADJSdkClickHandler alloc] initWithActivityHandler:activityHandler - startsSending:startsSending]; -} - #pragma mark - Public instance methods - (id)initWithActivityHandler:(id)activityHandler - startsSending:(BOOL)startsSending { + startsSending:(BOOL)startsSending + userAgent:(NSString *)userAgent + extraPath:(NSString *)extraPath +{ self = [super init]; if (self == nil) { return nil; @@ -51,9 +46,17 @@ - (id)initWithActivityHandler:(id)activityHandler self.internalQueue = dispatch_queue_create(kInternalQueueName, DISPATCH_QUEUE_SERIAL); self.logger = ADJAdjustFactory.logger; - self.basePath = [activityHandler getBasePath]; self.lastPackageRetriesCount = 0; + self.requestHandler = [[ADJRequestHandler alloc] + initWithResponseCallback:self + extraPath:extraPath + baseUrl:[ADJAdjustFactory baseUrl] + gdprUrl:[ADJAdjustFactory gdprUrl] + subscriptionUrl:[ADJAdjustFactory subscriptionUrl] + userAgent:userAgent + requestTimeout:[ADJAdjustFactory requestTimeout]]; + [ADJUtil launchInQueue:self.internalQueue selfInject:self block:^(ADJSdkClickHandler *selfI) { @@ -144,38 +147,13 @@ - (void)sendNextSdkClickI:(ADJSdkClickHandler *)selfI { return; } - NSURL *url; - NSString *baseUrl = [ADJAdjustFactory baseUrl]; - if (selfI.basePath != nil) { - url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", baseUrl, selfI.basePath]]; - } else { - url = [NSURL URLWithString:baseUrl]; - } - dispatch_block_t work = ^{ - [ADJUtil sendPostRequest:url - queueSize:queueSize - 1 - prefixErrorMessage:sdkClickPackage.failureMessage - suffixErrorMessage:@"Will retry later" - activityPackage:sdkClickPackage - responseDataHandler:^(ADJResponseData *responseData) { - // Check if any package response contains information that user has opted out. - // If yes, disable SDK and flush any potentially stored packages that happened afterwards. - if (responseData.trackingState == ADJTrackingStateOptedOut) { - selfI.lastPackageRetriesCount = 0; - [selfI.activityHandler setTrackingStateOptedOut]; - return; - } - if (responseData.jsonResponse == nil) { - selfI.lastPackageRetriesCount++; - [selfI.logger error:@"Retrying sdk_click package for the %d time", selfI.lastPackageRetriesCount]; - [selfI sendSdkClick:sdkClickPackage]; - return; - } - selfI.lastPackageRetriesCount = 0; - - [selfI.activityHandler finishedTracking:responseData]; - }]; + NSDictionary *sendingParameters = @{ + @"sent_at": [ADJUtil formatSeconds1970:[NSDate.date timeIntervalSince1970]] + }; + + [selfI.requestHandler sendPackageByPOST:sdkClickPackage + sendingParameters:sendingParameters]; [selfI sendNextSdkClick]; }; @@ -192,4 +170,30 @@ - (void)sendNextSdkClickI:(ADJSdkClickHandler *)selfI { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(waitTime * NSEC_PER_SEC)), self.internalQueue, work); } +- (void)responseCallback:(ADJResponseData *)responseData { + if (responseData.jsonResponse) { + [self.logger debug: + @"Got click JSON response with message: %@", responseData.message]; + } else { + [self.logger error: + @"Could not get click JSON response with message: %@", responseData.message]; + } + // Check if any package response contains information that user has opted out. + // If yes, disable SDK and flush any potentially stored packages that happened afterwards. + if (responseData.trackingState == ADJTrackingStateOptedOut) { + self.lastPackageRetriesCount = 0; + [self.activityHandler setTrackingStateOptedOut]; + return; + } + if (responseData.jsonResponse == nil) { + self.lastPackageRetriesCount++; + [self.logger error:@"Retrying sdk_click package for the %d time", self.lastPackageRetriesCount]; + [self sendSdkClick:responseData.sdkClickPackage]; + return; + } + self.lastPackageRetriesCount = 0; + + [self.activityHandler finishedTracking:responseData]; +} + @end diff --git a/Adjust/ADJUtil.h b/Adjust/ADJUtil.h index dff12afca..758d1dea9 100644 --- a/Adjust/ADJUtil.h +++ b/Adjust/ADJUtil.h @@ -52,19 +52,6 @@ typedef void (^isInactiveInjected)(BOOL); selfInject:(id)selfInject block:(selfInjectedBlock)block; -+ (void)sendGetRequest:(NSURL *)baseUrl - basePath:(NSString *)basePath - prefixErrorMessage:(NSString *)prefixErrorMessage - activityPackage:(ADJActivityPackage *)activityPackage - responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler; - -+ (void)sendPostRequest:(NSURL *)baseUrl - queueSize:(NSUInteger)queueSize - prefixErrorMessage:(NSString *)prefixErrorMessage - suffixErrorMessage:(NSString *)suffixErrorMessage - activityPackage:(ADJActivityPackage *)activityPackage - responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler; - + (NSString *)idfa; + (NSString *)clientSdk; @@ -81,6 +68,9 @@ typedef void (^isInactiveInjected)(BOOL); + (NSString *)queryString:(NSDictionary *)parameters; ++ (NSString *)queryString:(NSDictionary *)parameters + queueSize:(NSUInteger)queueSize; + + (NSString *)convertDeviceToken:(NSData *)deviceToken; + (BOOL)isNull:(id)value; @@ -97,10 +87,6 @@ typedef void (^isInactiveInjected)(BOOL); + (NSDictionary *)convertDictionaryValues:(NSDictionary *)dictionary; -+ (NSDictionary *)buildJsonDict:(NSData *)jsonData - exceptionPtr:(NSException **)exceptionPtr - errorPtr:(NSError **)error; - + (NSDictionary *)mergeParameters:(NSDictionary *)target source:(NSDictionary *)source parameterName:(NSString *)parameterName; diff --git a/Adjust/ADJUtil.m b/Adjust/ADJUtil.m index ef867f2ed..347f05a96 100644 --- a/Adjust/ADJUtil.m +++ b/Adjust/ADJUtil.m @@ -36,7 +36,6 @@ static NSRegularExpression *optionalRedirectRegex = nil; static NSRegularExpression *shortUniversalLinkRegex = nil; static NSRegularExpression *excludedDeeplinkRegex = nil; -static NSURLSessionConfiguration *urlSessionConfiguration = nil; #if !TARGET_OS_TV && !TARGET_OS_MACCATALYST static CTCarrier *carrier = nil; @@ -65,7 +64,6 @@ + (void)initialize { [self initializeShortUniversalLinkRegex]; [self initializeOptionalRedirectRegex]; [self initializeExcludedDeeplinkRegex]; - [self initializeUrlSessionConfiguration]; [self initializeReachability]; #if !TARGET_OS_TV && !TARGET_OS_MACCATALYST [self initializeNetworkInfoAndCarrier]; @@ -78,7 +76,6 @@ + (void)teardown { secondsNumberFormatter = nil; optionalRedirectRegex = nil; shortUniversalLinkRegex = nil; - urlSessionConfiguration = nil; #if !TARGET_OS_TV && !TARGET_OS_MACCATALYST networkInfo = nil; carrier = nil; @@ -139,18 +136,6 @@ + (void)initializeSecondsNumberFormatter { [secondsNumberFormatter setPositiveFormat:@"0.0"]; } -+ (NSURLSessionConfiguration *)getUrlSessionConfiguration { - if (urlSessionConfiguration != nil) { - return urlSessionConfiguration; - } else { - return [NSURLSessionConfiguration defaultSessionConfiguration]; - } -} - -+ (void)initializeUrlSessionConfiguration { - urlSessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; -} - #if !TARGET_OS_TV && !TARGET_OS_MACCATALYST + (void)initializeNetworkInfoAndCarrier { networkInfo = [[CTTelephonyNetworkInfo alloc] init]; @@ -248,44 +233,6 @@ + (NSString *)formatDate:(NSDate *)value { return [dateFormatter stringFromDate:value]; } -+ (void)saveJsonResponse:(NSData *)jsonData responseData:(ADJResponseData *)responseData { - NSError *error = nil; - NSException *exception = nil; - NSDictionary *jsonDict = [ADJUtil buildJsonDict:jsonData exceptionPtr:&exception errorPtr:&error]; - - if (exception != nil) { - NSString *message = [NSString stringWithFormat:@"Failed to parse json response. (%@)", exception.description]; - [ADJAdjustFactory.logger error:message]; - responseData.message = message; - return; - } - if (error != nil) { - NSString *message = [NSString stringWithFormat:@"Failed to parse json response. (%@)", error.localizedDescription]; - [ADJAdjustFactory.logger error:message]; - responseData.message = message; - return; - } - - responseData.jsonResponse = jsonDict; -} - -+ (NSDictionary *)buildJsonDict:(NSData *)jsonData - exceptionPtr:(NSException **)exceptionPtr - errorPtr:(NSError **)error { - if (jsonData == nil) { - return nil; - } - - NSDictionary *jsonDict = nil; - @try { - jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:error]; - } @catch (NSException *ex) { - *exceptionPtr = ex; - return nil; - } - return jsonDict; -} - + (id)readObject:(NSString *)fileName objectName:(NSString *)objectName class:(Class)classToRead @@ -506,425 +453,20 @@ + (BOOL)isNotNull:(id)value { return value != nil && value != (id)[NSNull null]; } -+ (NSString *)formatErrorMessage:(NSString *)prefixErrorMessage - systemErrorMessage:(NSString *)systemErrorMessage - suffixErrorMessage:(NSString *)suffixErrorMessage { - NSString *errorMessage = [NSString stringWithFormat:@"%@ (%@)", prefixErrorMessage, systemErrorMessage]; - if (suffixErrorMessage == nil) { - return errorMessage; - } else { - return [errorMessage stringByAppendingFormat:@" %@", suffixErrorMessage]; - } -} - -+ (void)sendGetRequest:(NSURL *)baseUrl - basePath:(NSString *)basePath - prefixErrorMessage:(NSString *)prefixErrorMessage - activityPackage:(ADJActivityPackage *)activityPackage - responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler { - NSMutableDictionary *parametersCopy = [[NSMutableDictionary alloc] initWithCapacity:[activityPackage.parameters count]]; - [parametersCopy addEntriesFromDictionary:activityPackage.parameters]; - - [ADJUtil extractEventCallbackId:parametersCopy]; - - NSString * authorizationHeader = [ADJUtil buildAuthorizationHeader:parametersCopy activityKind:activityPackage.activityKind]; - - NSMutableURLRequest *request = [ADJUtil requestForGetPackage:activityPackage.path - clientSdk:activityPackage.clientSdk - parameters:parametersCopy - baseUrl:baseUrl - basePath:basePath]; - [ADJUtil sendRequest:request - prefixErrorMessage:prefixErrorMessage - activityPackage:activityPackage - authorizationHeader:authorizationHeader - responseDataHandler:responseDataHandler]; -} - -+ (void)sendRequest:(NSMutableURLRequest *)request - prefixErrorMessage:(NSString *)prefixErrorMessage - activityPackage:(ADJActivityPackage *)activityPackage -authorizationHeader:(NSString *)authorizationHeader -responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler { - [ADJUtil sendRequest:request - prefixErrorMessage:prefixErrorMessage - suffixErrorMessage:nil - authorizationHeader:authorizationHeader - activityPackage:activityPackage - responseDataHandler:responseDataHandler]; -} - -+ (void)sendPostRequest:(NSURL *)baseUrl - queueSize:(NSUInteger)queueSize - prefixErrorMessage:(NSString *)prefixErrorMessage - suffixErrorMessage:(NSString *)suffixErrorMessage - activityPackage:(ADJActivityPackage *)activityPackage - responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler -{ - NSMutableDictionary *parametersCopy = [[NSMutableDictionary alloc] initWithCapacity:[activityPackage.parameters count]]; - [parametersCopy addEntriesFromDictionary:activityPackage.parameters]; - - [ADJUtil extractEventCallbackId:parametersCopy]; - - NSString * authorizationHeader = [ADJUtil buildAuthorizationHeader:parametersCopy activityKind:activityPackage.activityKind]; - - NSMutableURLRequest *request = [ADJUtil requestForPostPackage:activityPackage.path - clientSdk:activityPackage.clientSdk - parameters:parametersCopy - baseUrl:baseUrl queueSize:queueSize]; - [ADJUtil sendRequest:request - prefixErrorMessage:prefixErrorMessage - suffixErrorMessage:suffixErrorMessage - authorizationHeader:authorizationHeader - activityPackage:activityPackage - responseDataHandler:responseDataHandler]; -} - -+ (void)sendRequest:(NSMutableURLRequest *)request - prefixErrorMessage:(NSString *)prefixErrorMessage - suffixErrorMessage:(NSString *)suffixErrorMessage -authorizationHeader:(NSString *)authorizationHeader - activityPackage:(ADJActivityPackage *)activityPackage -responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler -{ - if (authorizationHeader != nil) { - [ADJAdjustFactory.logger debug:@"authorizationHeader %@", authorizationHeader]; - [request setValue:authorizationHeader forHTTPHeaderField:@"Authorization"]; - } - if (userAgent != nil) { - [request setValue:userAgent forHTTPHeaderField:@"User-Agent"]; - } - - Class NSURLSessionClass = NSClassFromString(@"NSURLSession"); - if (NSURLSessionClass != nil) { - [ADJUtil sendNSURLSessionRequest:request - prefixErrorMessage:prefixErrorMessage - suffixErrorMessage:suffixErrorMessage - activityPackage:activityPackage - responseDataHandler:responseDataHandler]; - } else { - [ADJUtil sendNSURLConnectionRequest:request - prefixErrorMessage:prefixErrorMessage - suffixErrorMessage:suffixErrorMessage - activityPackage:activityPackage - responseDataHandler:responseDataHandler]; - } -} - -+ (NSString *)buildAuthorizationHeader:(NSMutableDictionary *)parameters - activityKind:(ADJActivityKind)activityKind -{ - NSString *secretId = [ADJUtil extractEntry:parameters - key:@"secret_id"]; - NSString *signature = [ADJUtil extractEntry:parameters - key:@"signature"]; - NSString *headersId = [ADJUtil extractEntry:parameters - key:@"headers_id"]; - NSString *nativeVersion = [ADJUtil extractEntry:parameters - key:@"native_version"]; - NSString *algorithm = [ADJUtil extractEntry:parameters - key:@"algorithm"]; - NSString *authorizationHeader = [ADJUtil buildAuthorizationHeaderV2:signature - secretId:secretId - headersId:headersId - nativeVersion:nativeVersion - algorithm:algorithm]; - if (authorizationHeader != nil) { - return authorizationHeader; - } - - NSString * appSecret = [ADJUtil extractEntry:parameters key:@"app_secret"]; - return [ADJUtil buildAuthorizationHeaderV1:appSecret - secretId:secretId - parameters:parameters - activityKind:activityKind]; -} - -+ (NSString *)extractEntry:(NSMutableDictionary *)parameters - key:(NSString *)key -{ - NSString *stringValue = [parameters objectForKey:key]; - if (stringValue == nil) { - return nil; - } - [parameters removeObjectForKey:key]; - return stringValue; -} - -+ (NSString *)buildAuthorizationHeaderV2:(NSString *)signature - secretId:(NSString *)secretId - headersId:(NSString *)headersId - nativeVersion:(NSString *)nativeVersion - algorithm:(NSString *)algorithm -{ - if (secretId == nil || signature == nil || headersId == nil) { - return nil; - } - NSString * signatureHeader = [NSString stringWithFormat:@"signature=\"%@\"", signature]; - NSString * secretIdHeader = [NSString stringWithFormat:@"secret_id=\"%@\"", secretId]; - NSString * idHeader = [NSString stringWithFormat:@"headers_id=\"%@\"", headersId]; - NSString * algorithmHeader = [NSString stringWithFormat:@"algorithm=\"%@\"", algorithm != nil ? algorithm : @"adj1"]; - NSString * authorizationHeader = [NSString stringWithFormat:@"Signature %@,%@,%@,%@", - signatureHeader, secretIdHeader, algorithmHeader, idHeader]; - if (nativeVersion == nil) { - return [authorizationHeader stringByAppendingFormat:@",native_version=\"\""]; - } - return [authorizationHeader stringByAppendingFormat:@",native_version=\"%@\"", nativeVersion]; -} -+ (void)extractEventCallbackId:(NSMutableDictionary *)parameters { - NSString *eventCallbackId = [parameters objectForKey:@"event_callback_id"]; - if (eventCallbackId == nil) { - return; - } - [parameters removeObjectForKey:@"event_callback_id"]; -} -+ (NSMutableURLRequest *)requestForGetPackage:(NSString *)path - clientSdk:(NSString *)clientSdk - parameters:(NSDictionary *)parameters - baseUrl:(NSURL *)baseUrl - basePath:(NSString *)basePath { - NSString *queryStringParameters = [ADJUtil queryString:parameters]; - NSString *relativePath; - if (basePath != nil) { - relativePath = [NSString stringWithFormat:@"%@%@?%@", basePath, path, queryStringParameters]; - } else { - relativePath = [NSString stringWithFormat:@"%@?%@", path, queryStringParameters]; - } - NSURL *url = [NSURL URLWithString:relativePath relativeToURL:baseUrl]; - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; - request.timeoutInterval = kRequestTimeout; - request.HTTPMethod = @"GET"; - [request setValue:clientSdk forHTTPHeaderField:@"Client-Sdk"]; - return request; -} -+ (NSMutableURLRequest *)requestForPostPackage:(NSString *)path - clientSdk:(NSString *)clientSdk - parameters:(NSDictionary *)parameters - baseUrl:(NSURL *)baseUrl - queueSize:(NSUInteger)queueSize { - NSURL *url = [baseUrl URLByAppendingPathComponent:path]; - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; - request.timeoutInterval = kRequestTimeout; - request.HTTPMethod = @"POST"; - [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; - [request setValue:clientSdk forHTTPHeaderField:@"Client-Sdk"]; - - NSString *bodyString = [ADJUtil queryString:parameters queueSize:queueSize]; - NSData *body = [NSData dataWithBytes:bodyString.UTF8String length:bodyString.length]; - [request setHTTPBody:body]; - return request; -} -+ (NSString *)buildAuthorizationHeaderV1:(NSString *)appSecret - secretId:(NSString *)secretId - parameters:(NSMutableDictionary *)parameters - activityKind:(ADJActivityKind)activityKind -{ - if (appSecret == nil) { - return nil; - } - NSString *activityKindS = [ADJActivityKindUtil activityKindToString:activityKind]; - NSDictionary *signatureParameters = [ADJUtil buildSignatureParameters:parameters - appSecret:appSecret - activityKindS:activityKindS]; - NSMutableString *fields = [[NSMutableString alloc] initWithCapacity:5]; - NSMutableString *clearSignature = [[NSMutableString alloc] initWithCapacity:5]; - - // signature part of header - for (NSDictionary *key in signatureParameters) { - [fields appendFormat:@"%@ ", key]; - NSString *value = [signatureParameters objectForKey:key]; - [clearSignature appendString:value]; - } - - NSString *secretIdHeader = [NSString stringWithFormat:@"secret_id=\"%@\"", secretId]; - // algorithm part of header - NSString *algorithm = @"sha256"; - NSString *signature = [clearSignature adjSha256]; - NSString *signatureHeader = [NSString stringWithFormat:@"signature=\"%@\"", signature]; - NSString *algorithmHeader = [NSString stringWithFormat:@"algorithm=\"%@\"", algorithm]; - // fields part of header - // Remove last empty space. - if (fields.length > 0) { - [fields deleteCharactersInRange:NSMakeRange(fields.length - 1, 1)]; - } - - NSString *fieldsHeader = [NSString stringWithFormat:@"headers=\"%@\"", fields]; - // putting it all together - NSString *authorizationHeader = [NSString stringWithFormat:@"Signature %@,%@,%@,%@", - secretIdHeader, - signatureHeader, - algorithmHeader, - fieldsHeader]; - return authorizationHeader; -} -+ (NSDictionary *)buildSignatureParameters:(NSMutableDictionary *)parameters - appSecret:(NSString *)appSecret - activityKindS:(NSString *)activityKindS { - NSString *appSecretName = @"app_secret"; - NSString *sourceName = @"source"; - NSString *payloadName = @"payload"; - NSString *activityKindName = @"activity_kind"; - NSString *activityKindValue = activityKindS; - NSString *createdAtName = @"created_at"; - NSString *createdAtValue = [parameters objectForKey:createdAtName]; - NSString *deviceIdentifierName = [ADJUtil getValidIdentifier:parameters]; - NSString *deviceIdentifierValue = [parameters objectForKey:deviceIdentifierName]; - NSMutableDictionary *signatureParameters = [[NSMutableDictionary alloc] initWithCapacity:6]; - - [ADJUtil checkAndAddEntry:signatureParameters key:appSecretName value:appSecret]; - [ADJUtil checkAndAddEntry:signatureParameters key:createdAtName value:createdAtValue]; - [ADJUtil checkAndAddEntry:signatureParameters key:activityKindName value:activityKindValue]; - [ADJUtil checkAndAddEntry:signatureParameters key:deviceIdentifierName value:deviceIdentifierValue]; - [ADJUtil checkAndAddEntry:signatureParameters key:sourceName value:parameters[sourceName]]; - [ADJUtil checkAndAddEntry:signatureParameters key:payloadName value:parameters[payloadName]]; - - return signatureParameters; -} -+ (void)checkAndAddEntry:(NSMutableDictionary *)parameters - key:(NSString *)key - value:(NSString *)value { - if (key == nil) { - return; - } - if (value == nil) { - return; - } - - [parameters setObject:value forKey:key]; -} - -+ (NSString *)getValidIdentifier:(NSMutableDictionary *)parameters { - NSString *idfaName = @"idfa"; - NSString *persistentUUIDName = @"persistent_ios_uuid"; - NSString *uuidName = @"ios_uuid"; - - if ([parameters objectForKey:idfaName] != nil) { - return idfaName; - } - if ([parameters objectForKey:persistentUUIDName] != nil) { - return persistentUUIDName; - } - if ([parameters objectForKey:uuidName] != nil) { - return uuidName; - } - return nil; -} - -+ (void)sendNSURLSessionRequest:(NSMutableURLRequest *)request - prefixErrorMessage:(NSString *)prefixErrorMessage - suffixErrorMessage:(NSString *)suffixErrorMessage - activityPackage:(ADJActivityPackage *)activityPackage - responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler { - NSURLSession *session = [NSURLSession sessionWithConfiguration:[ADJUtil getUrlSessionConfiguration]]; - NSURLSessionDataTask *task = [session dataTaskWithRequest:request - completionHandler: - ^(NSData *data, NSURLResponse *response, NSError *error) { - ADJResponseData *responseData = [ADJUtil completionHandler:data - response:(NSHTTPURLResponse *)response - error:error - prefixErrorMessage:prefixErrorMessage - suffixErrorMessage:suffixErrorMessage - activityPackage:activityPackage]; - responseDataHandler(responseData); - }]; - [task resume]; - [session finishTasksAndInvalidate]; -} -+ (void)sendNSURLConnectionRequest:(NSMutableURLRequest *)request - prefixErrorMessage:(NSString *)prefixErrorMessage - suffixErrorMessage:(NSString *)suffixErrorMessage - activityPackage:(ADJActivityPackage *)activityPackage - responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler { - NSError *responseError = nil; - NSHTTPURLResponse *urlResponse = nil; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - NSData *data = [NSURLConnection sendSynchronousRequest:request - returningResponse:&urlResponse - error:&responseError]; -#pragma clang diagnostic pop - ADJResponseData *responseData = [ADJUtil completionHandler:data - response:(NSHTTPURLResponse *)urlResponse - error:responseError - prefixErrorMessage:prefixErrorMessage - suffixErrorMessage:suffixErrorMessage - activityPackage:activityPackage]; - responseDataHandler(responseData); -} -+ (ADJResponseData *)completionHandler:(NSData *)data - response:(NSHTTPURLResponse *)urlResponse - error:(NSError *)responseError - prefixErrorMessage:(NSString *)prefixErrorMessage - suffixErrorMessage:(NSString *)suffixErrorMessage - activityPackage:(ADJActivityPackage *)activityPackage { - ADJResponseData *responseData = [ADJResponseData buildResponseData:activityPackage]; - // Connection error - if (responseError != nil) { - NSString *errorMessage = [ADJUtil formatErrorMessage:prefixErrorMessage - systemErrorMessage:responseError.localizedDescription - suffixErrorMessage:suffixErrorMessage]; - [ADJAdjustFactory.logger error:errorMessage]; - responseData.message = errorMessage; - return responseData; - } - if ([ADJUtil isNull:data]) { - NSString *errorMessage = [ADJUtil formatErrorMessage:prefixErrorMessage - systemErrorMessage:@"empty error" - suffixErrorMessage:suffixErrorMessage]; - [ADJAdjustFactory.logger error:errorMessage]; - responseData.message = errorMessage; - return responseData; - } - - NSString *responseString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] adjTrim]; - NSInteger statusCode = urlResponse.statusCode; - [ADJAdjustFactory.logger verbose:@"Response: %@", responseString]; - - if (statusCode == 429) { - [ADJAdjustFactory.logger error:@"Too frequent requests to the endpoint (429)"]; - return responseData; - } - [ADJUtil saveJsonResponse:data responseData:responseData]; - if ([ADJUtil isNull:responseData.jsonResponse]) { - return responseData; - } - - NSString *messageResponse = [responseData.jsonResponse objectForKey:@"message"]; - responseData.message = messageResponse; - responseData.timeStamp = [responseData.jsonResponse objectForKey:@"timestamp"]; - responseData.adid = [responseData.jsonResponse objectForKey:@"adid"]; - - NSString *trackingState = [responseData.jsonResponse objectForKey:@"tracking_state"]; - if (trackingState != nil) { - if ([trackingState isEqualToString:@"opted_out"]) { - responseData.trackingState = ADJTrackingStateOptedOut; - } - } - if (messageResponse == nil) { - messageResponse = @"No message found"; - } - if (statusCode == 200) { - [ADJAdjustFactory.logger info:@"%@", messageResponse]; - responseData.success = YES; - } else { - [ADJAdjustFactory.logger error:@"%@", messageResponse]; - } - return responseData; -} // Convert all values to strings, if value is dictionary -> recursive call + (NSDictionary *)convertDictionaryValues:(NSDictionary *)dictionary { diff --git a/Adjust/Adjust.h b/Adjust/Adjust.h index c6c55a5f6..d980579e6 100644 --- a/Adjust/Adjust.h +++ b/Adjust/Adjust.h @@ -17,9 +17,7 @@ @property (nonatomic, copy, nullable) NSString *baseUrl; @property (nonatomic, copy, nullable) NSString *gdprUrl; @property (nonatomic, copy, nullable) NSString *subscriptionUrl; -@property (nonatomic, copy, nullable) NSString *basePath; -@property (nonatomic, copy, nullable) NSString *gdprPath; -@property (nonatomic, copy, nullable) NSString *subscriptionPath; +@property (nonatomic, copy, nullable) NSString *extraPath; @property (nonatomic, copy, nullable) NSNumber *timerIntervalInMilliseconds; @property (nonatomic, copy, nullable) NSNumber *timerStartInMilliseconds; @property (nonatomic, copy, nullable) NSNumber *sessionIntervalInMilliseconds; diff --git a/Adjust/Adjust.m b/Adjust/Adjust.m index 873afa13d..201769dd6 100644 --- a/Adjust/Adjust.m +++ b/Adjust/Adjust.m @@ -267,8 +267,9 @@ - (void)appDidLaunch:(ADJConfig *)adjustConfig { return; } - self.activityHandler = [ADJAdjustFactory activityHandlerWithConfig:adjustConfig - savedPreLaunch:self.savedPreLaunch]; + self.activityHandler = [[ADJActivityHandler alloc] + initWithConfig:adjustConfig + savedPreLaunch:self.savedPreLaunch]; } - (void)trackEvent:(ADJEvent *)event { @@ -525,14 +526,8 @@ - (void)teardown { } - (void)setTestOptions:(AdjustTestOptions *)testOptions { - if (testOptions.basePath != nil) { - self.savedPreLaunch.basePath = testOptions.basePath; - } - if (testOptions.gdprPath != nil) { - self.savedPreLaunch.gdprPath = testOptions.gdprPath; - } - if (testOptions.subscriptionPath != nil) { - self.savedPreLaunch.subscriptionPath = testOptions.subscriptionPath; + if (testOptions.extraPath != nil) { + self.savedPreLaunch.extraPath = testOptions.extraPath; } if (testOptions.baseUrl != nil) { [ADJAdjustFactory setBaseUrl:testOptions.baseUrl]; diff --git a/AdjustBridge/AdjustBridge.m b/AdjustBridge/AdjustBridge.m index 29d79d6b6..f8ee8edc5 100644 --- a/AdjustBridge/AdjustBridge.m +++ b/AdjustBridge/AdjustBridge.m @@ -486,8 +486,7 @@ - (void)loadWKWebViewBridge:(WKWebView *)wkWebView [self.bridgeRegister registerHandler:@"adjust_setTestOptions" handler:^(id data, WVJBResponseCallback responseCallback) { NSString *baseUrl = [data objectForKey:@"baseUrl"]; NSString *gdprUrl = [data objectForKey:@"gdprUrl"]; - NSString *basePath = [data objectForKey:@"basePath"]; - NSString *gdprPath = [data objectForKey:@"gdprPath"]; + NSString *extraPath = [data objectForKey:@"extraPath"]; NSNumber *timerIntervalInMilliseconds = [data objectForKey:@"timerIntervalInMilliseconds"]; NSNumber *timerStartInMilliseconds = [data objectForKey:@"timerStartInMilliseconds"]; NSNumber *sessionIntervalInMilliseconds = [data objectForKey:@"sessionIntervalInMilliseconds"]; @@ -505,11 +504,8 @@ - (void)loadWKWebViewBridge:(WKWebView *)wkWebView if ([self isFieldValid:gdprUrl]) { testOptions.gdprUrl = gdprUrl; } - if ([self isFieldValid:basePath]) { - testOptions.basePath = basePath; - } - if ([self isFieldValid:gdprPath]) { - testOptions.gdprPath = gdprPath; + if ([self isFieldValid:extraPath]) { + testOptions.extraPath = extraPath; } if ([self isFieldValid:timerIntervalInMilliseconds]) { testOptions.timerIntervalInMilliseconds = timerIntervalInMilliseconds; diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m index f8a24d4cc..bbacbef8a 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m @@ -20,9 +20,7 @@ @interface ATAAdjustCommandExecutor () -@property (nonatomic, copy) NSString *basePath; -@property (nonatomic, copy) NSString *gdprPath; -@property (nonatomic, copy) NSString *subscriptionPath; +@property (nonatomic, copy) NSString *extraPath; @property (nonatomic, strong) NSMutableDictionary *savedConfigs; @property (nonatomic, strong) NSMutableDictionary *savedEvents; @property (nonatomic, strong) NSObject *adjustDelegate; @@ -41,9 +39,7 @@ - (id)init { self.savedConfigs = [NSMutableDictionary dictionary]; self.savedEvents = [NSMutableDictionary dictionary]; self.adjustDelegate = nil; - self.basePath = nil; - self.gdprPath = nil; - self.subscriptionPath = nil; + self.extraPath = nil; return self; } @@ -107,9 +103,7 @@ - (void)testOptions:(NSDictionary *)parameters { testOptions.subscriptionUrl = subscriptionUrl; if ([parameters objectForKey:@"basePath"]) { - self.basePath = [parameters objectForKey:@"basePath"][0]; - self.gdprPath = [parameters objectForKey:@"basePath"][0]; - self.subscriptionPath = [parameters objectForKey:@"basePath"][0]; + self.extraPath = [parameters objectForKey:@"basePath"][0]; } if ([parameters objectForKey:@"timerInterval"]) { NSString *timerIntervalMilliS = [parameters objectForKey:@"timerInterval"][0]; @@ -161,9 +155,7 @@ - (void)testOptions:(NSDictionary *)parameters { NSString *teardownOption = teardownOptions[i]; if ([teardownOption isEqualToString:@"resetSdk"]) { testOptions.teardown = YES; - testOptions.basePath = self.basePath; - testOptions.gdprPath = self.gdprPath; - testOptions.subscriptionPath = self.subscriptionPath; + testOptions.extraPath = self.extraPath; } if ([teardownOption isEqualToString:@"deleteState"]) { testOptions.deleteState = YES; @@ -179,17 +171,13 @@ - (void)testOptions:(NSDictionary *)parameters { } if ([teardownOption isEqualToString:@"sdk"]) { testOptions.teardown = YES; - testOptions.basePath = nil; - testOptions.gdprPath = nil; - testOptions.subscriptionPath = nil; + testOptions.extraPath = nil; } if ([teardownOption isEqualToString:@"test"]) { self.savedConfigs = nil; self.savedEvents = nil; self.adjustDelegate = nil; - self.basePath = nil; - self.gdprPath = nil; - self.subscriptionPath = nil; + self.extraPath = nil; testOptions.timerIntervalInMilliseconds = [NSNumber numberWithInt:-1000]; testOptions.timerStartInMilliseconds = [NSNumber numberWithInt:-1000]; testOptions.sessionIntervalInMilliseconds = [NSNumber numberWithInt:-1000]; @@ -320,40 +308,47 @@ - (void)config:(NSDictionary *)parameters { if ([parameters objectForKey:@"attributionCallbackSendAll"]) { NSLog(@"attributionCallbackSendAll detected"); - self.adjustDelegate = [[ATAAdjustDelegateAttribution alloc] initWithTestLibrary:self.testLibrary - andBasePath:self.basePath]; + self.adjustDelegate = + [[ATAAdjustDelegateAttribution alloc] initWithTestLibrary:self.testLibrary + andExtraPath:self.extraPath]; } if ([parameters objectForKey:@"sessionCallbackSendSuccess"]) { NSLog(@"sessionCallbackSendSuccess detected"); - self.adjustDelegate = [[ATAAdjustDelegateSessionSuccess alloc] initWithTestLibrary:self.testLibrary - andBasePath:self.basePath]; + self.adjustDelegate = + [[ATAAdjustDelegateSessionSuccess alloc] initWithTestLibrary:self.testLibrary + andExtraPath:self.extraPath]; } if ([parameters objectForKey:@"sessionCallbackSendFailure"]) { NSLog(@"sessionCallbackSendFailure detected"); - self.adjustDelegate = [[ATAAdjustDelegateSessionFailure alloc] initWithTestLibrary:self.testLibrary - andBasePath:self.basePath]; + self.adjustDelegate = + [[ATAAdjustDelegateSessionFailure alloc] initWithTestLibrary:self.testLibrary + andExtraPath:self.extraPath]; } if ([parameters objectForKey:@"eventCallbackSendSuccess"]) { NSLog(@"eventCallbackSendSuccess detected"); - self.adjustDelegate = [[ATAAdjustDelegateEventSuccess alloc] initWithTestLibrary:self.testLibrary - andBasePath:self.basePath]; + self.adjustDelegate = + [[ATAAdjustDelegateEventSuccess alloc] initWithTestLibrary:self.testLibrary + andExtraPath:self.extraPath]; } if ([parameters objectForKey:@"eventCallbackSendFailure"]) { NSLog(@"eventCallbackSendFailure detected"); - self.adjustDelegate = [[ATAAdjustDelegateEventFailure alloc] initWithTestLibrary:self.testLibrary - andBasePath:self.basePath]; + self.adjustDelegate = + [[ATAAdjustDelegateEventFailure alloc] initWithTestLibrary:self.testLibrary + andExtraPath:self.extraPath]; } if ([parameters objectForKey:@"deferredDeeplinkCallback"]) { NSLog(@"deferredDeeplinkCallback detected"); NSString *shouldOpenDeeplinkS = [parameters objectForKey:@"deferredDeeplinkCallback"][0]; - self.adjustDelegate = [[ATAAdjustDelegateDeferredDeeplink alloc] initWithTestLibrary:self.testLibrary - basePath:self.basePath - andReturnValue:[shouldOpenDeeplinkS boolValue]]; + self.adjustDelegate = + [[ATAAdjustDelegateDeferredDeeplink alloc] + initWithTestLibrary:self.testLibrary + extraPath:self.extraPath + andReturnValue:[shouldOpenDeeplinkS boolValue]]; } [adjustConfig setDelegate:self.adjustDelegate]; diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateAttribution.h b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateAttribution.h index 0aaf1f8bd..9512b5247 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateAttribution.h +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateAttribution.h @@ -12,6 +12,6 @@ @interface ATAAdjustDelegateAttribution : NSObject -- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andBasePath:(NSString *)basePath; +- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andExtraPath:(NSString *)extraPath; @end diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateAttribution.m b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateAttribution.m index 745a528bb..2a4a24cde 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateAttribution.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateAttribution.m @@ -11,13 +11,13 @@ @interface ATAAdjustDelegateAttribution () @property (nonatomic, strong) ATLTestLibrary *testLibrary; -@property (nonatomic, copy) NSString *basePath; +@property (nonatomic, copy) NSString *extraPath; @end @implementation ATAAdjustDelegateAttribution -- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andBasePath:(NSString *)basePath { +- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andExtraPath:(NSString *)extraPath { self = [super init]; if (nil == self) { @@ -25,7 +25,7 @@ - (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andBasePath:(NSString *) } self.testLibrary = testLibrary; - self.basePath = basePath; + self.extraPath = extraPath; return self; } @@ -43,7 +43,7 @@ - (void)adjustAttributionChanged:(ADJAttribution *)attribution { [self.testLibrary addInfoToSend:@"clickLabel" value:attribution.clickLabel]; [self.testLibrary addInfoToSend:@"adid" value:attribution.adid]; - [self.testLibrary sendInfoToServer:self.basePath]; + [self.testLibrary sendInfoToServer:self.extraPath]; } @end diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateDeferredDeeplink.h b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateDeferredDeeplink.h index 89e3683de..0316700dc 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateDeferredDeeplink.h +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateDeferredDeeplink.h @@ -12,6 +12,6 @@ @interface ATAAdjustDelegateDeferredDeeplink : NSObject -- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary basePath:(NSString *)basePath andReturnValue:(BOOL)returnValue; +- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary extraPath:(NSString *)extraPath andReturnValue:(BOOL)returnValue; @end diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateDeferredDeeplink.m b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateDeferredDeeplink.m index 6e30364d5..43fc29e5a 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateDeferredDeeplink.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateDeferredDeeplink.m @@ -11,14 +11,14 @@ @interface ATAAdjustDelegateDeferredDeeplink () @property (nonatomic, strong) ATLTestLibrary *testLibrary; -@property (nonatomic, copy) NSString *basePath; +@property (nonatomic, copy) NSString *extraPath; @property (nonatomic, assign) BOOL returnValue; @end @implementation ATAAdjustDelegateDeferredDeeplink -- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary basePath:(NSString *)basePath andReturnValue:(BOOL)returnValue { +- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary extraPath:(NSString *)extraPath andReturnValue:(BOOL)returnValue { self = [super init]; if (nil == self) { @@ -26,7 +26,7 @@ - (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary basePath:(NSString *)bas } self.testLibrary = testLibrary; - self.basePath = basePath; + self.extraPath = extraPath; self.returnValue = returnValue; return self; @@ -37,7 +37,7 @@ - (BOOL)adjustDeeplinkResponse:(nullable NSURL *)deeplink { NSLog(@"Deep link: %@", deeplink); [self.testLibrary addInfoToSend:@"deeplink" value:[deeplink absoluteString]]; - [self.testLibrary sendInfoToServer:self.basePath]; + [self.testLibrary sendInfoToServer:self.extraPath]; return self.returnValue; } diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventFailure.h b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventFailure.h index 072a88c1a..5e5ee05b5 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventFailure.h +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventFailure.h @@ -12,6 +12,6 @@ @interface ATAAdjustDelegateEventFailure : NSObject -- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andBasePath:(NSString *)basePath; +- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andExtraPath:(NSString *)extraPath; @end diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventFailure.m b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventFailure.m index 17ba3479f..313442736 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventFailure.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventFailure.m @@ -11,13 +11,13 @@ @interface ATAAdjustDelegateEventFailure () @property (nonatomic, strong) ATLTestLibrary *testLibrary; -@property (nonatomic, copy) NSString *basePath; +@property (nonatomic, copy) NSString *extraPath; @end @implementation ATAAdjustDelegateEventFailure -- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andBasePath:(NSString *)basePath { +- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andExtraPath:(NSString *)extraPath { self = [super init]; if (nil == self) { @@ -25,7 +25,7 @@ - (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andBasePath:(NSString *) } self.testLibrary = testLibrary; - self.basePath = basePath; + self.extraPath = extraPath; return self; } @@ -53,7 +53,7 @@ - (void)adjustEventTrackingFailed:(ADJEventFailure *)eventFailureResponseData { [self.testLibrary addInfoToSend:@"jsonResponse" value:jsonString]; } - [self.testLibrary sendInfoToServer:self.basePath]; + [self.testLibrary sendInfoToServer:self.extraPath]; } @end diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventSuccess.h b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventSuccess.h index 129bbece5..19ab41717 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventSuccess.h +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventSuccess.h @@ -12,6 +12,6 @@ @interface ATAAdjustDelegateEventSuccess : NSObject -- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andBasePath:(NSString *)basePath; +- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andExtraPath:(NSString *)extraPath; @end diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventSuccess.m b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventSuccess.m index 573eafce7..d71fadad2 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventSuccess.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateEventSuccess.m @@ -11,13 +11,13 @@ @interface ATAAdjustDelegateEventSuccess () @property (nonatomic, strong) ATLTestLibrary *testLibrary; -@property (nonatomic, copy) NSString *basePath; +@property (nonatomic, copy) NSString *extraPath; @end @implementation ATAAdjustDelegateEventSuccess -- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andBasePath:(NSString *)basePath { +- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andExtraPath:(NSString *)extraPath { self = [super init]; if (nil == self) { @@ -25,7 +25,7 @@ - (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andBasePath:(NSString *) } self.testLibrary = testLibrary; - self.basePath = basePath; + self.extraPath = extraPath; return self; } @@ -52,7 +52,7 @@ - (void)adjustEventTrackingSucceeded:(ADJEventSuccess *)eventSuccessResponseData [self.testLibrary addInfoToSend:@"jsonResponse" value:jsonString]; } - [self.testLibrary sendInfoToServer:self.basePath]; + [self.testLibrary sendInfoToServer:self.extraPath]; } @end diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionFailure.h b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionFailure.h index 70f1e939b..a680fd3b2 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionFailure.h +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionFailure.h @@ -12,6 +12,6 @@ @interface ATAAdjustDelegateSessionFailure : NSObject -- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andBasePath:(NSString *)basePath; +- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andExtraPath:(NSString *)extraPath; @end diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionFailure.m b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionFailure.m index e1008cc7e..3b59a2619 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionFailure.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionFailure.m @@ -11,13 +11,13 @@ @interface ATAAdjustDelegateSessionFailure () @property (nonatomic, strong) ATLTestLibrary *testLibrary; -@property (nonatomic, copy) NSString *basePath; +@property (nonatomic, copy) NSString *extraPath; @end @implementation ATAAdjustDelegateSessionFailure -- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andBasePath:(NSString *)basePath { +- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andExtraPath:(NSString *)extraPath { self = [super init]; if (nil == self) { @@ -25,7 +25,7 @@ - (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andBasePath:(NSString *) } self.testLibrary = testLibrary; - self.basePath = basePath; + self.extraPath = extraPath; return self; } @@ -51,7 +51,7 @@ - (void)adjustSessionTrackingFailed:(ADJSessionFailure *)sessionFailureResponseD [self.testLibrary addInfoToSend:@"jsonResponse" value:jsonString]; } - [self.testLibrary sendInfoToServer:self.basePath]; + [self.testLibrary sendInfoToServer:self.extraPath]; } @end diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionSuccess.h b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionSuccess.h index 134d419b4..437650ac8 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionSuccess.h +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionSuccess.h @@ -12,6 +12,6 @@ @interface ATAAdjustDelegateSessionSuccess : NSObject -- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andBasePath:(NSString *)basePath; +- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andExtraPath:(NSString *)extraPath; @end diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionSuccess.m b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionSuccess.m index ef7c717a4..7015a95fb 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionSuccess.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/Delegates/ATAAdjustDelegateSessionSuccess.m @@ -11,13 +11,13 @@ @interface ATAAdjustDelegateSessionSuccess () @property (nonatomic, strong) ATLTestLibrary *testLibrary; -@property (nonatomic, copy) NSString *basePath; +@property (nonatomic, copy) NSString *extraPath; @end @implementation ATAAdjustDelegateSessionSuccess -- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andBasePath:(NSString *)basePath { +- (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andExtraPath:(NSString *)extraPath { self = [super init]; if (nil == self) { @@ -25,7 +25,7 @@ - (id)initWithTestLibrary:(ATLTestLibrary *)testLibrary andBasePath:(NSString *) } self.testLibrary = testLibrary; - self.basePath = basePath; + self.extraPath = extraPath; return self; } @@ -50,7 +50,7 @@ - (void)adjustSessionTrackingSucceeded:(ADJSessionSuccess *)sessionSuccessRespon [self.testLibrary addInfoToSend:@"jsonResponse" value:jsonString]; } - [self.testLibrary sendInfoToServer:self.basePath]; + [self.testLibrary sendInfoToServer:self.extraPath]; } @end diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.m b/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.m index 9eb837814..6b62c40cb 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/ViewController.m @@ -30,8 +30,8 @@ - (void)viewDidLoad { andCommandDelegate:self.adjustCommandExecutor]; [self.adjustCommandExecutor setTestLibrary:self.testLibrary]; - // [self.testLibrary addTestDirectory:@"current/third-party-sharing"]; - [self.testLibrary addTest:@"Test_iOs_Subscription_subscription"]; + //[self.testLibrary addTestDirectory:@"event-callbacks"]; + //[self.testLibrary addTest:@"Test_AdRevenue_ad_revenue"]; // [self.testLibrary doNotExitAfterEnd]; [self startTestSession]; From c227e647af30a35a34a0e0c2a66512c2f6077ac9 Mon Sep 17 00:00:00 2001 From: uerceg Date: Mon, 25 May 2020 13:37:38 +0200 Subject: [PATCH 24/35] New version 4.22.0 --- Adjust.podspec | 4 ++-- Adjust/ADJUtil.m | 2 +- Adjust/Adjust.h | 2 +- AdjustBridge/AdjustBridgeRegister.m | 2 +- AdjustTests/AdjustUnitTests/ADJPackageFields.m | 2 +- README.md | 4 ++-- VERSION | 2 +- doc/chinese/README.md | 4 ++-- doc/english/migrate.md | 2 +- doc/english/web_views.md | 2 +- doc/japanese/README.md | 4 ++-- doc/korean/README.md | 4 ++-- doc/korean/web_views.md | 2 +- doc/migrate.md | 2 +- 14 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Adjust.podspec b/Adjust.podspec index 316a436b0..d26e45e01 100644 --- a/Adjust.podspec +++ b/Adjust.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = "Adjust" - s.version = "4.21.3" + s.version = "4.22.0" s.summary = "This is the iOS SDK of adjust. You can read more about it at http://adjust.com." s.homepage = "https://github.com/adjust/ios_sdk" s.license = { :type => 'MIT', :file => 'MIT-LICENSE' } s.author = { "Christian Wellenbrock" => "welle@adjust.com" } - s.source = { :git => "https://github.com/adjust/ios_sdk.git", :tag => "v4.21.3" } + s.source = { :git => "https://github.com/adjust/ios_sdk.git", :tag => "v4.22.0" } s.ios.deployment_target = '6.0' s.tvos.deployment_target = '9.0' s.framework = 'SystemConfiguration' diff --git a/Adjust/ADJUtil.m b/Adjust/ADJUtil.m index 347f05a96..03ee102a8 100644 --- a/Adjust/ADJUtil.m +++ b/Adjust/ADJUtil.m @@ -42,7 +42,7 @@ static CTTelephonyNetworkInfo *networkInfo = nil; #endif -static NSString * const kClientSdk = @"ios4.21.3"; +static NSString * const kClientSdk = @"ios4.22.0"; static NSString * const kDeeplinkParam = @"deep_link="; static NSString * const kSchemeDelimiter = @"://"; static NSString * const kDefaultScheme = @"AdjustUniversalScheme"; diff --git a/Adjust/Adjust.h b/Adjust/Adjust.h index d980579e6..6e6acda59 100644 --- a/Adjust/Adjust.h +++ b/Adjust/Adjust.h @@ -2,7 +2,7 @@ // Adjust.h // Adjust // -// V4.21.3 +// V4.22.0 // Created by Christian Wellenbrock (wellle) on 23rd July 2013. // Copyright © 2012-2017 Adjust GmbH. All rights reserved. // diff --git a/AdjustBridge/AdjustBridgeRegister.m b/AdjustBridge/AdjustBridgeRegister.m index b87799a2d..62b58c204 100644 --- a/AdjustBridge/AdjustBridgeRegister.m +++ b/AdjustBridge/AdjustBridgeRegister.m @@ -221,7 +221,7 @@ + (NSString *)adjust_js { if (this.sdkPrefix) { return this.sdkPrefix; } else { - return 'web-bridge4.21.3'; + return 'web-bridge4.22.0'; } }, setTestOptions: function(testOptions) { diff --git a/AdjustTests/AdjustUnitTests/ADJPackageFields.m b/AdjustTests/AdjustUnitTests/ADJPackageFields.m index ab7a0b56e..d41d85980 100644 --- a/AdjustTests/AdjustUnitTests/ADJPackageFields.m +++ b/AdjustTests/AdjustUnitTests/ADJPackageFields.m @@ -16,7 +16,7 @@ - (id) init { // default values self.appToken = @"qwerty123456"; - self.clientSdk = @"ios4.21.3"; + self.clientSdk = @"ios4.22.0"; self.suffix = @""; self.environment = @"sandbox"; diff --git a/README.md b/README.md index b65b65a3d..8faa04cbb 100644 --- a/README.md +++ b/README.md @@ -75,13 +75,13 @@ We will describe the steps to integrate the Adjust SDK into your iOS project. We If you're using [CocoaPods][cocoapods], you can add the following line to your `Podfile` and continue from [this step](#sdk-integrate): ```ruby -pod 'Adjust', '~> 4.21.3' +pod 'Adjust', '~> 4.22.0' ``` or: ```ruby -pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.21.3' +pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.22.0' ``` --- diff --git a/VERSION b/VERSION index fedb11348..d7638f377 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.21.3 +4.22.0 diff --git a/doc/chinese/README.md b/doc/chinese/README.md index 4d497188b..07e41ebe5 100644 --- a/doc/chinese/README.md +++ b/doc/chinese/README.md @@ -73,13 +73,13 @@ Read this in other languages: [English][en-readme], [中文][zh-readme], [日本 如果您正在使用[CocoaPods][cocoapods],您可以将以下代码行添加至 `Podfile`,然后继续进行[此步骤](#sdk-integrate): ```ruby -pod 'Adjust', '~> 4.21.3' +pod 'Adjust', '~> 4.22.0' ``` 或: ```ruby -pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.21.3' +pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.22.0' ``` --- diff --git a/doc/english/migrate.md b/doc/english/migrate.md index 754f75536..1b4b98dc5 100644 --- a/doc/english/migrate.md +++ b/doc/english/migrate.md @@ -1,4 +1,4 @@ -## Migrate your Adjust SDK for iOS to v4.21.3 from v3.4.0 +## Migrate your Adjust SDK for iOS to v4.22.0 from v3.4.0 ### Initial setup diff --git a/doc/english/web_views.md b/doc/english/web_views.md index 3758dc7f3..3e1b83d49 100644 --- a/doc/english/web_views.md +++ b/doc/english/web_views.md @@ -64,7 +64,7 @@ We will describe the steps to integrate the Adjust SDK into your iOS project. We If you're using [CocoaPods][cocoapods], you can add the following line to your `Podfile` and continue from [this step](#sdk-integrate): ```ruby -pod 'Adjust/WebBridge', '~> 4.21.3' +pod 'Adjust/WebBridge', '~> 4.22.0' ``` --- diff --git a/doc/japanese/README.md b/doc/japanese/README.md index 068d4cc50..e6ffc2957 100644 --- a/doc/japanese/README.md +++ b/doc/japanese/README.md @@ -25,13 +25,13 @@ adjust SDKをiOSプロジェクトに連携する手順を説明します。 [こちらの手順](#sdk-integrate)に進んでください。 ```ruby -pod 'Adjust', '~> 4.21.3' +pod 'Adjust', '~> 4.22.0' ``` または ```ruby -pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.21.3' +pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.22.0' ``` --- diff --git a/doc/korean/README.md b/doc/korean/README.md index 98586b073..16d6727cd 100644 --- a/doc/korean/README.md +++ b/doc/korean/README.md @@ -73,13 +73,13 @@ iOS 개발용 Xcode를 사용한다는 가정하에 iOS 프로젝트에 Adjust S [CocoaPods][cocoapods]를 사용하는 경우, 다음 내용을 `Podfile`에 추가한 후 [해당 단계](#sdk-integrate)를 완료하세요. ```ruby -pod 'Adjust', '~> 4.21.3' +pod 'Adjust', '~> 4.22.0' ``` 또는: ```ruby -pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.21.3' +pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.22.0' ``` --- diff --git a/doc/korean/web_views.md b/doc/korean/web_views.md index e191eb289..2775d6800 100644 --- a/doc/korean/web_views.md +++ b/doc/korean/web_views.md @@ -64,7 +64,7 @@ iOS 개발용 Xcode를 사용한다는 가정하에 iOS 프로젝트에 Adjust S [CocoaPods][cocoapods]를 사용하는 경우, 다음 내용을 'Podfile'에 추가한 후 [해당 단계](#sdk-integrate)를 완료하세요. ```ruby -pod 'Adjust/WebBridge', '~> 4.21.3' +pod 'Adjust/WebBridge', '~> 4.22.0' ``` --- diff --git a/doc/migrate.md b/doc/migrate.md index 754f75536..1b4b98dc5 100644 --- a/doc/migrate.md +++ b/doc/migrate.md @@ -1,4 +1,4 @@ -## Migrate your Adjust SDK for iOS to v4.21.3 from v3.4.0 +## Migrate your Adjust SDK for iOS to v4.22.0 from v3.4.0 ### Initial setup From 201c5403af16d9166c2f466da790ebb6316aeaac Mon Sep 17 00:00:00 2001 From: uerceg Date: Mon, 25 May 2020 13:39:33 +0200 Subject: [PATCH 25/35] CHANGELOG.md update --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3251a15ce..b996d6f8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +### Version 4.22.0 (xxth May 2020) +#### Added +- Added subscription tracking feature (`trackSubscription:` method added to `Adjust` API). + +--- + ### Version 4.21.3 (22nd April 2020) #### Changed - Added copying of each injected mutable property of `ADJEvent` class. From a8061c5b1c16145da4e16399c918b31f8cfeb097 Mon Sep 17 00:00:00 2001 From: mcoombs <52657116+mcoombs@users.noreply.github.com> Date: Tue, 26 May 2020 19:23:33 +0200 Subject: [PATCH 26/35] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 8faa04cbb..20254df7a 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Read this in other languages: [English][en-readme], [中文][zh-readme], [日本 * [Delay start](#delay-start) * [Attribution callback](#attribution-callback) * [Ad revenue tracking](#ad-revenue) - * [Subscriptions tracking](#subscriptions) + * [Subscription tracking](#subscriptions) * [Event and session callbacks](#event-session-callbacks) * [Disable tracking](#disable-tracking) * [Offline mode](#offline-mode) @@ -519,11 +519,11 @@ Currently we support the below `source` parameter values: - `ADJAdRevenueSourceMopub` - representing MoPub mediation platform (for more information, check [integration guide][sdk2sdk-mopub]) -### Subscriptions tracking +### Subscription tracking -**Note**: This feature is available only in the native SDK v4.22.0 and above. +**Note**: This feature is only available in the native SDK v4.22.0 and above. -You can track App Store subscriptions and verify their validity with Adjust SDK. After subscription has been successfully purchased, you need to make following call to Adjust SDK: +You can track App Store subscriptions and verify their validity with the Adjust SDK. After a subscription has been successfully purchased, make the following call to the Adjust SDK: ```objc ADJSubscription *subscription = [[ADJSubscription alloc] initWithPrice:price @@ -548,7 +548,7 @@ Subscription tracking parameters: - [transactionDate](https://developer.apple.com/documentation/storekit/skpaymenttransaction/1411273-transactiondate?language=objc) - salesRegion (you need to pass [countryCode](https://developer.apple.com/documentation/foundation/nslocale/1643060-countrycode?language=objc) of the [priceLocale](https://developer.apple.com/documentation/storekit/skproduct/1506145-pricelocale?language=objc) object) -In same fashion like with event tracking, you can attach callback and partner parameters to subscription object as well: +Just like with event tracking, you can attach callback and partner parameters to the subscription object as well: ```objc ADJSubscription *subscription = [[ADJSubscription alloc] initWithPrice:price From 2c439697857a4f4b1b83711eaac9503ab0c776f4 Mon Sep 17 00:00:00 2001 From: mcoombs <52657116+mcoombs@users.noreply.github.com> Date: Tue, 26 May 2020 19:45:17 +0200 Subject: [PATCH 27/35] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 20254df7a..6116015a9 100644 --- a/README.md +++ b/README.md @@ -536,8 +536,7 @@ ADJSubscription *subscription = [[ADJSubscription alloc] initWithPrice:price [Adjust trackSubscription:subscription]; ``` - -Make sure to do this before making a call to `finishTransaction` in `paymentQueue:updatedTransaction` only if the state changed to `SKPaymentTransactionStatePurchased` or `SKPaymentTransactionStateRestored`. +Only do this when the state has changed to `SKPaymentTransactionStatePurchased` or `SKPaymentTransactionStateRestored`. Then make a call to `finishTransaction` in `paymentQueue:updatedTransaction` . Subscription tracking parameters: From 505d0837765cede3c7f68c92332f19db2fb56a82 Mon Sep 17 00:00:00 2001 From: uerceg Date: Tue, 26 May 2020 23:05:13 +0200 Subject: [PATCH 28/35] Remove some log messages --- Adjust/ADJRequestHandler.m | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Adjust/ADJRequestHandler.m b/Adjust/ADJRequestHandler.m index de2232918..b34e25506 100644 --- a/Adjust/ADJRequestHandler.m +++ b/Adjust/ADJRequestHandler.m @@ -261,8 +261,6 @@ - (void)handleResponseWithData:(NSData *)data NSString *urlString = [NSString stringWithFormat:@"%@%@%@", urlHostString, self.extraPath, path]; - [self.logger debug:@"TORMV Post final url: %@", urlString]; - NSURL *url = [NSURL URLWithString:urlString]; //NSURL *url = [baseUrl URLByAppendingPathComponent:path]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; @@ -310,8 +308,6 @@ - (void)handleResponseWithData:(NSData *)data [NSString stringWithFormat:@"%@%@%@?%@", urlHostString, self.extraPath, path, queryStringParameters]; - [self.logger debug:@"TORMV Get final url: %@", urlString]; - NSURL *url = [NSURL URLWithString:urlString]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; From 6e6afffdbba65d0c897e628ce09d2a303af196cc Mon Sep 17 00:00:00 2001 From: uerceg Date: Wed, 27 May 2020 10:30:07 +0200 Subject: [PATCH 29/35] Remove unused timeout constant --- Adjust/ADJUtil.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/Adjust/ADJUtil.m b/Adjust/ADJUtil.m index 03ee102a8..b3c1b1e29 100644 --- a/Adjust/ADJUtil.m +++ b/Adjust/ADJUtil.m @@ -27,8 +27,6 @@ // https://stackoverflow.com/a/5337804/1498352 #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) -static const double kRequestTimeout = 60; // 60 seconds - static NSString *userAgent = nil; static ADJReachability *reachability = nil; static NSRegularExpression *universalLinkRegex = nil; From 7f65052cfd02110bb936433db23aac39f9648320 Mon Sep 17 00:00:00 2001 From: uerceg Date: Wed, 27 May 2020 15:54:27 +0200 Subject: [PATCH 30/35] Activity state synchronisation --- Adjust/ADJActivityHandler.m | 168 +++++++++++++++++++++++++++--------- Adjust/ADJPackageHandler.m | 5 +- Adjust/ADJUtil.h | 7 +- Adjust/ADJUtil.m | 12 ++- 4 files changed, 146 insertions(+), 46 deletions(-) diff --git a/Adjust/ADJActivityHandler.m b/Adjust/ADJActivityHandler.m index d119c9d9f..c47acd00d 100644 --- a/Adjust/ADJActivityHandler.m +++ b/Adjust/ADJActivityHandler.m @@ -149,7 +149,10 @@ - (id)initWithConfig:(ADJConfig *)adjustConfig [self.logger lockLogLevel]; // inject app token be available in activity state - [ADJActivityState saveAppToken:adjustConfig.appToken]; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + [ADJActivityState saveAppToken:adjustConfig.appToken]; + }]; // read files to have sync values available [self readAttribution]; @@ -480,8 +483,11 @@ - (void)sendIad3ClickPackage:(ADJActivityHandler *)selfI double now = [NSDate.date timeIntervalSince1970]; if (selfI.activityState != nil) { - double lastInterval = now - selfI.activityState.lastActivity; - selfI.activityState.lastInterval = lastInterval; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + double lastInterval = now - selfI.activityState.lastActivity; + selfI.activityState.lastInterval = lastInterval; + }]; } ADJPackageBuilder *clickBuilder = [[ADJPackageBuilder alloc] initWithDeviceInfo:selfI.deviceInfo @@ -500,7 +506,10 @@ - (void)saveAttributionDetailsI:(ADJActivityHandler *)selfI attributionDetails:(NSDictionary *)attributionDetails { // save new iAd details - selfI.activityState.attributionDetails = attributionDetails; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.attributionDetails = attributionDetails; + }]; [selfI writeAttributionI:selfI]; } @@ -838,7 +847,10 @@ - (void)processSessionI:(ADJActivityHandler *)selfI { NSData *deviceToken = [ADJUserDefaults getPushTokenData]; NSString *deviceTokenString = [ADJUtil convertDeviceToken:deviceToken]; NSString *pushToken = [ADJUserDefaults getPushTokenString]; - selfI.activityState.deviceToken = deviceTokenString != nil ? deviceTokenString : pushToken; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.deviceToken = deviceTokenString != nil ? deviceTokenString : pushToken; + }]; // track the first session package only if it's enabled if ([selfI.internalState isEnabled]) { @@ -850,14 +862,20 @@ - (void)processSessionI:(ADJActivityHandler *)selfI { if ([ADJUserDefaults getDisableThirdPartySharing]) { [selfI disableThirdPartySharingI:selfI]; } - selfI.activityState.sessionCount = 1; // this is the first session + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.sessionCount = 1; // this is the first session + }]; [selfI transferSessionPackageI:selfI now:now]; } } - [selfI.activityState resetSessionAttributes:now]; - selfI.activityState.enabled = [selfI.internalState isEnabled]; - selfI.activityState.updatePackages = [selfI.internalState itHasToUpdatePackages]; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + [selfI.activityState resetSessionAttributes:now]; + selfI.activityState.enabled = [selfI.internalState isEnabled]; + selfI.activityState.updatePackages = [selfI.internalState itHasToUpdatePackages]; + }]; [selfI writeActivityStateI:selfI]; [ADJUserDefaults removePushToken]; @@ -869,7 +887,10 @@ - (void)processSessionI:(ADJActivityHandler *)selfI { double lastInterval = now - selfI.activityState.lastActivity; if (lastInterval < 0) { [selfI.logger error:@"Time travel!"]; - selfI.activityState.lastActivity = now; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.lastActivity = now; + }]; [selfI writeActivityStateI:selfI]; return; } @@ -882,9 +903,12 @@ - (void)processSessionI:(ADJActivityHandler *)selfI { // new subsession if (lastInterval > kSubSessionInterval) { - selfI.activityState.subsessionCount++; - selfI.activityState.sessionLength += lastInterval; - selfI.activityState.lastActivity = now; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.subsessionCount++; + selfI.activityState.sessionLength += lastInterval; + selfI.activityState.lastActivity = now; + }]; [selfI.logger verbose:@"Started subsession %d of session %d", selfI.activityState.subsessionCount, selfI.activityState.sessionCount]; @@ -901,10 +925,16 @@ - (void)trackNewSessionI:(double)now withActivityHandler:(ADJActivityHandler *)s } double lastInterval = now - selfI.activityState.lastActivity; - selfI.activityState.sessionCount++; - selfI.activityState.lastInterval = lastInterval; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.sessionCount++; + selfI.activityState.lastInterval = lastInterval; + }]; [selfI transferSessionPackageI:selfI now:now]; - [selfI.activityState resetSessionAttributes:now]; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + [selfI.activityState resetSessionAttributes:now]; + }]; [selfI writeActivityStateI:selfI]; } @@ -977,7 +1007,10 @@ - (void)eventI:(ADJActivityHandler *)selfI double now = [NSDate.date timeIntervalSince1970]; - selfI.activityState.eventCount++; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.eventCount++; + }]; [selfI updateActivityStateI:selfI now:now]; // create and populate event package @@ -1075,7 +1108,10 @@ - (void)disableThirdPartySharingI:(ADJActivityHandler *)selfI { return; } - selfI.activityState.isThirdPartySharingDisabled = YES; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.isThirdPartySharingDisabled = YES; + }]; [selfI writeActivityStateI:selfI]; double now = [NSDate.date timeIntervalSince1970]; @@ -1241,7 +1277,10 @@ - (void)updateAdidI:(ADJActivityHandler *)selfI return; } - selfI.activityState.adid = adid; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.adid = adid; + }]; [selfI writeActivityStateI:selfI]; } @@ -1300,7 +1339,10 @@ - (void)setEnabledI:(ADJActivityHandler *)selfI enabled:(BOOL)enabled { } // Save new enabled state in activity state. - selfI.activityState.enabled = enabled; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.enabled = enabled; + }]; [selfI writeActivityStateI:selfI]; // Check if upon enabling install has been tracked. @@ -1448,8 +1490,11 @@ - (void)appWillOpenUrlI:(ADJActivityHandler *)selfI } double now = [NSDate.date timeIntervalSince1970]; - double lastInterval = now - selfI.activityState.lastActivity; - selfI.activityState.lastInterval = lastInterval; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + double lastInterval = now - selfI.activityState.lastActivity; + selfI.activityState.lastInterval = lastInterval; + }]; ADJPackageBuilder *clickBuilder = [[ADJPackageBuilder alloc] initWithDeviceInfo:selfI.deviceInfo activityState:selfI.activityState config:selfI.adjustConfig @@ -1543,7 +1588,10 @@ - (void)setDeviceTokenI:(ADJActivityHandler *)selfI } // save new push token - selfI.activityState.deviceToken = deviceTokenString; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.deviceToken = deviceTokenString; + }]; [selfI writeActivityStateI:selfI]; // send info package @@ -1587,7 +1635,10 @@ - (void)setPushTokenI:(ADJActivityHandler *)selfI } // save new push token - selfI.activityState.deviceToken = pushToken; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.deviceToken = pushToken; + }]; [selfI writeActivityStateI:selfI]; // send info package @@ -1622,7 +1673,10 @@ - (void)setGdprForgetMeI:(ADJActivityHandler *)selfI { return; } - selfI.activityState.isGdprForgotten = YES; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.isGdprForgotten = YES; + }]; [selfI writeActivityStateI:selfI]; // Send GDPR package @@ -1648,7 +1702,10 @@ - (void)setGdprForgetMeI:(ADJActivityHandler *)selfI { - (void)setTrackingStateOptedOutI:(ADJActivityHandler *)selfI { // In case of web opt out, once response from backend arrives isGdprForgotten field in this moment defaults to NO. // Set it to YES regardless of state, since at this moment it should be YES. - selfI.activityState.isGdprForgotten = YES; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.isGdprForgotten = YES; + }]; [selfI writeActivityStateI:selfI]; [selfI setEnabled:NO]; @@ -1691,14 +1748,20 @@ - (BOOL)updateActivityStateI:(ADJActivityHandler *)selfI // ignore late updates if (lastInterval > kSessionInterval) return NO; - selfI.activityState.lastActivity = now; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.lastActivity = now; + }]; if (lastInterval < 0) { [selfI.logger error:@"Time travel!"]; return YES; } else { - selfI.activityState.sessionLength += lastInterval; - selfI.activityState.timeSpent += lastInterval; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.sessionLength += lastInterval; + selfI.activityState.timeSpent += lastInterval; + }]; } return YES; @@ -1706,12 +1769,16 @@ - (BOOL)updateActivityStateI:(ADJActivityHandler *)selfI - (void)writeActivityStateI:(ADJActivityHandler *)selfI { - @synchronized ([ADJActivityState class]) { + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ if (selfI.activityState == nil) { return; } - [ADJUtil writeObject:selfI.activityState fileName:kActivityStateFilename objectName:@"Activity state"]; - } + [ADJUtil writeObject:selfI.activityState + fileName:kActivityStateFilename + objectName:@"Activity state" + syncObject:[ADJActivityState class]]; + }]; } - (void)teardownActivityStateS @@ -1729,7 +1796,10 @@ - (void)writeAttributionI:(ADJActivityHandler *)selfI { if (selfI.attribution == nil) { return; } - [ADJUtil writeObject:selfI.attribution fileName:kAttributionFilename objectName:@"Attribution"]; + [ADJUtil writeObject:selfI.attribution + fileName:kAttributionFilename + objectName:@"Attribution" + syncObject:[ADJAttribution class]]; } } @@ -1744,10 +1814,13 @@ - (void)teardownAttributionS } - (void)readActivityState { - [NSKeyedUnarchiver setClass:[ADJActivityState class] forClassName:@"AIActivityState"]; - self.activityState = [ADJUtil readObject:kActivityStateFilename - objectName:@"Activity state" - class:[ADJActivityState class]]; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + [NSKeyedUnarchiver setClass:[ADJActivityState class] forClassName:@"AIActivityState"]; + self.activityState = [ADJUtil readObject:kActivityStateFilename + objectName:@"Activity state" + class:[ADJActivityState class]]; + }]; } - (void)readAttribution { @@ -1763,7 +1836,8 @@ - (void)writeSessionCallbackParametersI:(ADJActivityHandler *)selfI { } [ADJUtil writeObject:selfI.sessionParameters.callbackParameters fileName:kSessionCallbackParametersFilename - objectName:@"Session Callback parameters"]; + objectName:@"Session Callback parameters" + syncObject:[ADJSessionParameters class]]; } } @@ -1774,7 +1848,8 @@ - (void)writeSessionPartnerParametersI:(ADJActivityHandler *)selfI { } [ADJUtil writeObject:selfI.sessionParameters.partnerParameters fileName:kSessionPartnerParametersFilename - objectName:@"Session Partner parameters"]; + objectName:@"Session Partner parameters" + syncObject:[ADJSessionParameters class]]; } } @@ -1885,7 +1960,10 @@ - (BOOL)toSendI:(ADJActivityHandler *)selfI - (void)setAskingAttributionI:(ADJActivityHandler *)selfI askingAttribution:(BOOL)askingAttribution { - selfI.activityState.askingAttribution = askingAttribution; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.askingAttribution = askingAttribution; + }]; [selfI writeActivityStateI:selfI]; } @@ -1984,7 +2062,10 @@ - (void)delayStartI:(ADJActivityHandler *)selfI { selfI.internalState.updatePackages = YES; if (selfI.activityState != nil) { - selfI.activityState.updatePackages = YES; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.updatePackages = YES; + }]; [selfI writeActivityStateI:selfI]; } } @@ -2012,7 +2093,10 @@ - (void)updatePackagesI:(ADJActivityHandler *)selfI { // no longer needs to update packages selfI.internalState.updatePackages = NO; if (selfI.activityState != nil) { - selfI.activityState.updatePackages = NO; + [ADJUtil launchSynchronisedWithObject:[ADJActivityState class] + block:^{ + selfI.activityState.updatePackages = NO; + }]; [selfI writeActivityStateI:selfI]; } } diff --git a/Adjust/ADJPackageHandler.m b/Adjust/ADJPackageHandler.m index 29942b1b7..9bd82a966 100644 --- a/Adjust/ADJPackageHandler.m +++ b/Adjust/ADJPackageHandler.m @@ -319,7 +319,10 @@ - (void)writePackageQueueS:(ADJPackageHandler *)selfS { return; } - [ADJUtil writeObject:selfS.packageQueue fileName:kPackageQueueFilename objectName:@"Package queue"]; + [ADJUtil writeObject:selfS.packageQueue + fileName:kPackageQueueFilename + objectName:@"Package queue" + syncObject:[ADJPackageHandler class]]; } } diff --git a/Adjust/ADJUtil.h b/Adjust/ADJUtil.h index 758d1dea9..c62606199 100644 --- a/Adjust/ADJUtil.h +++ b/Adjust/ADJUtil.h @@ -16,6 +16,7 @@ #import "ADJBackoffStrategy.h" typedef void (^selfInjectedBlock)(id); +typedef void (^synchronisedBlock)(void); typedef void (^isInactiveInjected)(BOOL); @interface ADJUtil : NSObject @@ -42,7 +43,8 @@ typedef void (^isInactiveInjected)(BOOL); + (void)writeObject:(id)object fileName:(NSString *)fileName - objectName:(NSString *)objectName; + objectName:(NSString *)objectName + syncObject:(id)syncObject; + (void)launchInMainThread:(NSObject *)receiver selector:(SEL)selector @@ -52,6 +54,9 @@ typedef void (^isInactiveInjected)(BOOL); selfInject:(id)selfInject block:(selfInjectedBlock)block; ++ (void)launchSynchronisedWithObject:(id)synchronisationObject + block:(synchronisedBlock)block; + + (NSString *)idfa; + (NSString *)clientSdk; diff --git a/Adjust/ADJUtil.m b/Adjust/ADJUtil.m index b3c1b1e29..4e94be28b 100644 --- a/Adjust/ADJUtil.m +++ b/Adjust/ADJUtil.m @@ -315,8 +315,9 @@ + (id)readObject:(NSString *)fileName + (void)writeObject:(id)object fileName:(NSString *)fileName - objectName:(NSString *)objectName { - @synchronized([ADJUtil class]) { + objectName:(NSString *)objectName + syncObject:(id)syncObject { + @synchronized(syncObject) { @try { BOOL result; NSString *filePath = [ADJUtil getFilePathInAppSupportDir:fileName]; @@ -781,6 +782,13 @@ + (void)launchInQueue:(dispatch_queue_t)queue }); } ++ (void)launchSynchronisedWithObject:(id)synchronisationObject + block:(synchronisedBlock)block { + @synchronized (synchronisationObject) { + block(); + } +} + + (BOOL)deleteFileWithName:(NSString *)fileName { NSString *documentsFilePath = [ADJUtil getFilePathInDocumentsDir:fileName]; NSString *appSupportFilePath = [ADJUtil getFilePathInAppSupportDir:fileName]; From 8fa2ea089f7152fd1eb3aa7b4a0e45c471376587 Mon Sep 17 00:00:00 2001 From: uerceg Date: Wed, 27 May 2020 16:19:02 +0200 Subject: [PATCH 31/35] Package queue synchronisation --- Adjust/ADJActivityHandler.m | 12 ++-- Adjust/ADJPackageHandler.m | 106 +++++++++++++++++++++--------------- Adjust/ADJUtil.h | 3 +- Adjust/ADJUtil.m | 3 +- 4 files changed, 75 insertions(+), 49 deletions(-) diff --git a/Adjust/ADJActivityHandler.m b/Adjust/ADJActivityHandler.m index c47acd00d..5d5be4629 100644 --- a/Adjust/ADJActivityHandler.m +++ b/Adjust/ADJActivityHandler.m @@ -1819,14 +1819,16 @@ - (void)readActivityState { [NSKeyedUnarchiver setClass:[ADJActivityState class] forClassName:@"AIActivityState"]; self.activityState = [ADJUtil readObject:kActivityStateFilename objectName:@"Activity state" - class:[ADJActivityState class]]; + class:[ADJActivityState class] + syncObject:[ADJActivityState class]]; }]; } - (void)readAttribution { self.attribution = [ADJUtil readObject:kAttributionFilename objectName:@"Attribution" - class:[ADJAttribution class]]; + class:[ADJAttribution class] + syncObject:[ADJAttribution class]]; } - (void)writeSessionCallbackParametersI:(ADJActivityHandler *)selfI { @@ -1867,13 +1869,15 @@ - (void)teardownAllSessionParametersS { - (void)readSessionCallbackParametersI:(ADJActivityHandler *)selfI { selfI.sessionParameters.callbackParameters = [ADJUtil readObject:kSessionCallbackParametersFilename objectName:@"Session Callback parameters" - class:[NSDictionary class]]; + class:[NSDictionary class] + syncObject:[ADJSessionParameters class]]; } - (void)readSessionPartnerParametersI:(ADJActivityHandler *)selfI { selfI.sessionParameters.partnerParameters = [ADJUtil readObject:kSessionPartnerParametersFilename objectName:@"Session Partner parameters" - class:[NSDictionary class]]; + class:[NSDictionary class] + syncObject:[ADJSessionParameters class]]; } # pragma mark - handlers status diff --git a/Adjust/ADJPackageHandler.m b/Adjust/ADJPackageHandler.m index 9bd82a966..e62d247a8 100644 --- a/Adjust/ADJPackageHandler.m +++ b/Adjust/ADJPackageHandler.m @@ -212,7 +212,10 @@ - (void)initI:(ADJPackageHandler *)selfI - (void)addI:(ADJPackageHandler *)selfI package:(ADJActivityPackage *)newPackage { - [selfI.packageQueue addObject:newPackage]; + [ADJUtil launchSynchronisedWithObject:[ADJPackageHandler class] + block:^{ + [selfI.packageQueue addObject:newPackage]; + }]; [selfI.logger debug:@"Added package %d (%@)", selfI.packageQueue.count, newPackage]; [selfI.logger verbose:@"%@", newPackage.extendedString]; @@ -257,7 +260,10 @@ - (void)sendFirstI:(ADJPackageHandler *)selfI - (void)sendNextI:(ADJPackageHandler *)selfI { if ([selfI.packageQueue count] > 0) { - [selfI.packageQueue removeObjectAtIndex:0]; + [ADJUtil launchSynchronisedWithObject:[ADJPackageHandler class] + block:^{ + [selfI.packageQueue removeObjectAtIndex:0]; + }]; [selfI writePackageQueueS:selfI]; } @@ -272,69 +278,83 @@ - (void)updatePackagesI:(ADJPackageHandler *)selfI [selfI.logger verbose:@"Session callback parameters: %@", sessionParameters.callbackParameters]; [selfI.logger verbose:@"Session partner parameters: %@", sessionParameters.partnerParameters]; - for (ADJActivityPackage * activityPackage in selfI.packageQueue) { - // callback parameters - NSDictionary * mergedCallbackParameters = [ADJUtil mergeParameters:sessionParameters.callbackParameters - source:activityPackage.callbackParameters - parameterName:@"Callback"]; - - [ADJPackageBuilder parameters:activityPackage.parameters - setDictionary:mergedCallbackParameters - forKey:@"callback_params"]; - - // partner parameters - NSDictionary * mergedPartnerParameters = [ADJUtil mergeParameters:sessionParameters.partnerParameters - source:activityPackage.partnerParameters - parameterName:@"Partner"]; - - [ADJPackageBuilder parameters:activityPackage.parameters - setDictionary:mergedPartnerParameters - forKey:@"partner_params"]; - } + [ADJUtil launchSynchronisedWithObject:[ADJPackageHandler class] + block:^{ + for (ADJActivityPackage * activityPackage in selfI.packageQueue) { + // callback parameters + NSDictionary * mergedCallbackParameters = [ADJUtil mergeParameters:sessionParameters.callbackParameters + source:activityPackage.callbackParameters + parameterName:@"Callback"]; + + [ADJPackageBuilder parameters:activityPackage.parameters + setDictionary:mergedCallbackParameters + forKey:@"callback_params"]; + + // partner parameters + NSDictionary * mergedPartnerParameters = [ADJUtil mergeParameters:sessionParameters.partnerParameters + source:activityPackage.partnerParameters + parameterName:@"Partner"]; + + [ADJPackageBuilder parameters:activityPackage.parameters + setDictionary:mergedPartnerParameters + forKey:@"partner_params"]; + } + }]; [selfI writePackageQueueS:selfI]; } - (void)flushI:(ADJPackageHandler *)selfI { - [selfI.packageQueue removeAllObjects]; + [ADJUtil launchSynchronisedWithObject:[ADJPackageHandler class] + block:^{ + [selfI.packageQueue removeAllObjects]; + }]; [selfI writePackageQueueS:selfI]; } #pragma mark - private - (void)readPackageQueueI:(ADJPackageHandler *)selfI { - [NSKeyedUnarchiver setClass:[ADJActivityPackage class] forClassName:@"AIActivityPackage"]; - - id object = [ADJUtil readObject:kPackageQueueFilename objectName:@"Package queue" class:[NSArray class]]; - - if (object != nil) { - selfI.packageQueue = object; - } else { - selfI.packageQueue = [NSMutableArray array]; - } + [ADJUtil launchSynchronisedWithObject:[ADJPackageHandler class] + block:^{ + [NSKeyedUnarchiver setClass:[ADJActivityPackage class] forClassName:@"AIActivityPackage"]; + + id object = [ADJUtil readObject:kPackageQueueFilename + objectName:@"Package queue" + class:[NSArray class] + syncObject:[ADJPackageHandler class]]; + + if (object != nil) { + selfI.packageQueue = object; + } else { + selfI.packageQueue = [NSMutableArray array]; + } + }]; } - (void)writePackageQueueS:(ADJPackageHandler *)selfS { - @synchronized ([ADJPackageHandler class]) { - if (selfS.packageQueue == nil) { - return; - } - + if (selfS.packageQueue == nil) { + return; + } + + [ADJUtil launchSynchronisedWithObject:[ADJPackageHandler class] + block:^{ [ADJUtil writeObject:selfS.packageQueue fileName:kPackageQueueFilename objectName:@"Package queue" syncObject:[ADJPackageHandler class]]; - } + }]; } - (void)teardownPackageQueueS { - @synchronized ([ADJPackageHandler class]) { - if (self.packageQueue == nil) { - return; - } - + if (self.packageQueue == nil) { + return; + } + + [ADJUtil launchSynchronisedWithObject:[ADJPackageHandler class] + block:^{ [self.packageQueue removeAllObjects]; self.packageQueue = nil; - } + }]; } - (void)dealloc { diff --git a/Adjust/ADJUtil.h b/Adjust/ADJUtil.h index c62606199..d63421745 100644 --- a/Adjust/ADJUtil.h +++ b/Adjust/ADJUtil.h @@ -25,7 +25,8 @@ typedef void (^isInactiveInjected)(BOOL); + (id)readObject:(NSString *)fileName objectName:(NSString *)objectName - class:(Class)classToRead; + class:(Class)classToRead + syncObject:(id)syncObject; + (void)excludeFromBackup:(NSString *)filename; diff --git a/Adjust/ADJUtil.m b/Adjust/ADJUtil.m index 4e94be28b..d380749c0 100644 --- a/Adjust/ADJUtil.m +++ b/Adjust/ADJUtil.m @@ -234,8 +234,9 @@ + (NSString *)formatDate:(NSDate *)value { + (id)readObject:(NSString *)fileName objectName:(NSString *)objectName class:(Class)classToRead + syncObject:(id)syncObject { - @synchronized([ADJUtil class]) { + @synchronized(syncObject) { NSString *documentsFilePath = [ADJUtil getFilePathInDocumentsDir:fileName]; NSString *appSupportFilePath = [ADJUtil getFilePathInAppSupportDir:fileName]; From 925e47e3d56d060d7dddd7e55c6abc019ddea826 Mon Sep 17 00:00:00 2001 From: uerceg Date: Wed, 27 May 2020 16:19:08 +0200 Subject: [PATCH 32/35] Xcode update --- Adjust.xcodeproj/project.pbxproj | 2 +- Adjust.xcodeproj/xcshareddata/xcschemes/AdjustSdk.xcscheme | 2 +- Adjust.xcodeproj/xcshareddata/xcschemes/AdjustSdkIm.xcscheme | 2 +- Adjust.xcodeproj/xcshareddata/xcschemes/AdjustSdkTv.xcscheme | 2 +- .../xcshareddata/xcschemes/AdjustSdkWebBridge.xcscheme | 2 +- .../xcshareddata/xcschemes/AdjustWebBridgeTestApp.xcscheme | 2 +- .../xcshareddata/xcschemes/PocketSocket-Mac.xcscheme | 2 +- .../xcshareddata/xcschemes/PocketSocket.xcscheme | 2 +- .../xcschemes/AdjustExample-iMessage MessagesExtension.xcscheme | 2 +- .../xcshareddata/xcschemes/AdjustExample-iMessage.xcscheme | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Adjust.xcodeproj/project.pbxproj b/Adjust.xcodeproj/project.pbxproj index 84695aeec..1aa7520a0 100644 --- a/Adjust.xcodeproj/project.pbxproj +++ b/Adjust.xcodeproj/project.pbxproj @@ -2232,7 +2232,7 @@ 9679920518BBAE2800394606 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1140; + LastUpgradeCheck = 1150; ORGANIZATIONNAME = "adjust GmbH"; TargetAttributes = { 9615158E1CD2CB2C0022D336 = { diff --git a/Adjust.xcodeproj/xcshareddata/xcschemes/AdjustSdk.xcscheme b/Adjust.xcodeproj/xcshareddata/xcschemes/AdjustSdk.xcscheme index 1f5e13c3a..fafe60d22 100644 --- a/Adjust.xcodeproj/xcshareddata/xcschemes/AdjustSdk.xcscheme +++ b/Adjust.xcodeproj/xcshareddata/xcschemes/AdjustSdk.xcscheme @@ -1,6 +1,6 @@ Date: Thu, 28 May 2020 14:27:11 +0200 Subject: [PATCH 33/35] CHANGELOG.md update --- CHANGELOG.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b996d6f8a..f5e366ac0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ -### Version 4.22.0 (xxth May 2020) +### Version 4.22.0 (28th May 2020) #### Added -- Added subscription tracking feature (`trackSubscription:` method added to `Adjust` API). +- Added subscription tracking feature. + +### Changed +- Refactored networking part and moved it to request handler. +- Added additional synchronisation in various cases of access to package queue and activity state. --- From a8a06a29351f9098a1f314b83b75fa9b80b0b245 Mon Sep 17 00:00:00 2001 From: uerceg Date: Thu, 28 May 2020 17:09:00 +0200 Subject: [PATCH 34/35] CHANGELOG.md update --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5e366ac0..abacf3aba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### Version 4.22.0 (28th May 2020) +### Version 4.22.0 (29th May 2020) #### Added - Added subscription tracking feature. From fa721bc8a0bdbeb370c01ba5253df35e52b9031a Mon Sep 17 00:00:00 2001 From: uerceg Date: Fri, 29 May 2020 00:11:18 +0200 Subject: [PATCH 35/35] Migrate web bridge test app to use extra path --- .../TestLibraryBridge.js | 44 ++++++++----------- .../TestLibraryBridge.m | 4 +- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/AdjustTests/AdjustWebBridgeTestApp/AdjustWebBridgeTestApp/TestLibraryBridge.js b/AdjustTests/AdjustWebBridgeTestApp/AdjustWebBridgeTestApp/TestLibraryBridge.js index e787699e8..bf0f7729d 100644 --- a/AdjustTests/AdjustWebBridgeTestApp/AdjustWebBridgeTestApp/TestLibraryBridge.js +++ b/AdjustTests/AdjustWebBridgeTestApp/AdjustWebBridgeTestApp/TestLibraryBridge.js @@ -35,8 +35,7 @@ var TestLibraryBridge = { var AdjustCommandExecutor = function(baseUrl, gdprUrl) { this.baseUrl = baseUrl; this.gdprUrl = gdprUrl; - this.basePath = null; - this.gdprPath = null; + this.extraPath = null; this.savedEvents = {}; this.savedConfigs = {}; this.savedCommands = []; @@ -50,8 +49,7 @@ AdjustCommandExecutor.prototype.testOptions = function(params) { var TestOptions = function() { this.baseUrl = null; this.gdprUrl = null; - this.basePath = null; - this.gdprPath = null; + this.extraPath = null; this.timerIntervalInMilliseconds = null; this.timerStartInMilliseconds = null; this.sessionIntervalInMilliseconds = null; @@ -67,10 +65,7 @@ AdjustCommandExecutor.prototype.testOptions = function(params) { testOptions.gdprUrl = this.gdprUrl; if ('basePath' in params) { - var basePath = getFirstValue(params, 'basePath'); - console.log('TestLibraryBridge hasOwnProperty basePath, first: ' + basePath); - this.basePath = basePath; - this.gdprPath = basePath; + this.extraPath = getFirstValue(params, 'basePath'); } if ('timerInterval' in params) { testOptions.timerIntervalInMilliseconds = getFirstValue(params, 'timerInterval'); @@ -106,8 +101,7 @@ AdjustCommandExecutor.prototype.testOptions = function(params) { switch(teardownOption) { case 'resetSdk': testOptions.teardown = true; - testOptions.basePath = this.basePath; - testOptions.gdprPath = this.gdprPath; + testOptions.extraPath = this.extraPath; break; case 'deleteState': testOptions.deleteState = true; @@ -122,15 +116,13 @@ AdjustCommandExecutor.prototype.testOptions = function(params) { break; case 'sdk': testOptions.teardown = true; - testOptions.basePath = null; - testOptions.gdprPath = null; + testOptions.extraPath = null; break; case 'test': // TODO: null configs // TODO: null events // TODO: null delegate - this.basePath = null; - this.gdprPath = null; + this.extraPath = null; testOptions.timerIntervalInMilliseconds = -1; testOptions.timerStartInMilliseconds = -1; testOptions.sessionIntervalInMilliseconds = -1; @@ -260,7 +252,7 @@ AdjustCommandExecutor.prototype.config = function(params) { if ('attributionCallbackSendAll' in params) { console.log('AdjustCommandExecutor.prototype.config attributionCallbackSendAll'); - var basePath = this.basePath; + var extraPath = this.extraPath; adjustConfig.setAttributionCallback( function(attribution) { console.log('attributionCallback: ' + JSON.stringify(attribution)); @@ -272,14 +264,14 @@ AdjustCommandExecutor.prototype.config = function(params) { addInfoToSend('creative', attribution.creative); addInfoToSend('clickLabel', attribution.click_label); addInfoToSend('adid', attribution.adid); - WebViewJavascriptBridge.callHandler('adjustTLB_sendInfoToServer', basePath, null); + WebViewJavascriptBridge.callHandler('adjustTLB_sendInfoToServer', extraPath, null); } ); } if ('sessionCallbackSendSuccess' in params) { console.log('AdjustCommandExecutor.prototype.config sessionCallbackSendSuccess'); - var basePath = this.basePath; + var extraPath = this.extraPath; adjustConfig.setSessionSuccessCallback( function(sessionSuccessResponseData) { console.log('sessionSuccessCallback: ' + JSON.stringify(sessionSuccessResponseData)); @@ -287,14 +279,14 @@ AdjustCommandExecutor.prototype.config = function(params) { addInfoToSend('timestamp', sessionSuccessResponseData.timestamp); addInfoToSend('adid', sessionSuccessResponseData.adid); addInfoToSend('jsonResponse', sessionSuccessResponseData.jsonResponse); - WebViewJavascriptBridge.callHandler('adjustTLB_sendInfoToServer', basePath, null); + WebViewJavascriptBridge.callHandler('adjustTLB_sendInfoToServer', extraPath, null); } ); } if ('sessionCallbackSendFailure' in params) { console.log('AdjustCommandExecutor.prototype.config sessionCallbackSendFailure'); - var basePath = this.basePath; + var extraPath = this.extraPath; adjustConfig.setSessionFailureCallback( function(sessionFailureResponseData) { console.log('sessionFailureCallback: ' + JSON.stringify(sessionFailureResponseData)); @@ -303,14 +295,14 @@ AdjustCommandExecutor.prototype.config = function(params) { addInfoToSend('adid', sessionFailureResponseData.adid); addInfoToSend('willRetry', sessionFailureResponseData.willRetry ? 'true' : 'false'); addInfoToSend('jsonResponse', sessionFailureResponseData.jsonResponse); - WebViewJavascriptBridge.callHandler('adjustTLB_sendInfoToServer', basePath, null); + WebViewJavascriptBridge.callHandler('adjustTLB_sendInfoToServer', extraPath, null); } ); } if ('eventCallbackSendSuccess' in params) { console.log('AdjustCommandExecutor.prototype.config eventCallbackSendSuccess'); - var basePath = this.basePath; + var extraPath = this.extraPath; adjustConfig.setEventSuccessCallback( function(eventSuccessResponseData) { console.log('eventSuccessCallback: ' + JSON.stringify(eventSuccessResponseData)); @@ -320,14 +312,14 @@ AdjustCommandExecutor.prototype.config = function(params) { addInfoToSend('eventToken', eventSuccessResponseData.eventToken); addInfoToSend('callbackId', eventSuccessResponseData.callbackId); addInfoToSend('jsonResponse', eventSuccessResponseData.jsonResponse); - WebViewJavascriptBridge.callHandler('adjustTLB_sendInfoToServer', basePath, null); + WebViewJavascriptBridge.callHandler('adjustTLB_sendInfoToServer', extraPath, null); } ); } if ('eventCallbackSendFailure' in params) { console.log('AdjustCommandExecutor.prototype.config eventCallbackSendFailure'); - var basePath = this.basePath; + var extraPath = this.extraPath; adjustConfig.setEventFailureCallback( function(eventFailureResponseData) { console.log('eventFailureCallback: ' + JSON.stringify(eventFailureResponseData)); @@ -338,7 +330,7 @@ AdjustCommandExecutor.prototype.config = function(params) { addInfoToSend('callbackId', eventFailureResponseData.callbackId); addInfoToSend('willRetry', eventFailureResponseData.willRetry ? 'true' : 'false'); addInfoToSend('jsonResponse', eventFailureResponseData.jsonResponse); - WebViewJavascriptBridge.callHandler('adjustTLB_sendInfoToServer', basePath, null); + WebViewJavascriptBridge.callHandler('adjustTLB_sendInfoToServer', extraPath, null); } ); } @@ -352,12 +344,12 @@ AdjustCommandExecutor.prototype.config = function(params) { if (shouldOpenDeeplinkS === 'false') { adjustConfig.setOpenDeferredDeeplink(false); } - var basePath = this.basePath; + var extraPath = this.extraPath; adjustConfig.setDeferredDeeplinkCallback( function(deeplink) { console.log('deferredDeeplinkCallback: ' + JSON.stringify(deeplink)); addInfoToSend('deeplink', deeplink); - WebViewJavascriptBridge.callHandler('adjustTLB_sendInfoToServer', basePath, null); + WebViewJavascriptBridge.callHandler('adjustTLB_sendInfoToServer', extraPath, null); } ); } diff --git a/AdjustTests/AdjustWebBridgeTestApp/AdjustWebBridgeTestApp/TestLibraryBridge.m b/AdjustTests/AdjustWebBridgeTestApp/AdjustWebBridgeTestApp/TestLibraryBridge.m index 6d3ab136f..dce90ea9b 100644 --- a/AdjustTests/AdjustWebBridgeTestApp/AdjustWebBridgeTestApp/TestLibraryBridge.m +++ b/AdjustTests/AdjustWebBridgeTestApp/AdjustWebBridgeTestApp/TestLibraryBridge.m @@ -49,8 +49,8 @@ - (id)initWithAdjustBridgeRegister:(AdjustBridgeRegister *)adjustBridgeRegister return; } - NSString *basePath = (NSString *)data; - [self.testLibrary sendInfoToServer:basePath]; + NSString *extraPath = (NSString *)data; + [self.testLibrary sendInfoToServer:extraPath]; }]; self.adjustBridgeRegister = adjustBridgeRegister;