Skip to content

Commit 5bbc4eb

Browse files
committed
Merge pull request #139 from adjust/iad_v3
Iad v3
2 parents 5550143 + 3bbcb9b commit 5bbc4eb

16 files changed

+211
-35
lines changed

Adjust.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
Pod::Spec.new do |s|
22
s.name = "Adjust"
3-
s.version = "4.4.4"
3+
s.version = "4.4.5"
44
s.summary = "This is the iOS SDK of adjust. You can read more about it at http://adjust.com."
55
s.homepage = "http://adjust.com"
66
s.license = { :type => 'MIT', :file => 'MIT-LICENSE' }
77
s.author = { "Christian Wellenbrock" => "[email protected]" }
8-
s.source = { :git => "https://github.com/adjust/ios_sdk.git", :tag => "v4.4.4" }
8+
s.source = { :git => "https://github.com/adjust/ios_sdk.git", :tag => "v4.4.5" }
99
s.ios.deployment_target = '5.0'
1010
s.tvos.deployment_target = '9.0'
1111
s.framework = 'SystemConfiguration'

Adjust.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@
479479
};
480480
};
481481
};
482-
buildConfigurationList = 9679920818BBAE2800394606 /* Build configuration list for PBXProject "Adjust" */;
482+
buildConfigurationList = 9679920818BBAE2800394606 /* Build configuration list for PBXProject "adjust" */;
483483
compatibilityVersion = "Xcode 3.2";
484484
developmentRegion = English;
485485
hasScannedForEncodings = 0;
@@ -816,7 +816,7 @@
816816
/* End XCBuildConfiguration section */
817817

818818
/* Begin XCConfigurationList section */
819-
9679920818BBAE2800394606 /* Build configuration list for PBXProject "Adjust" */ = {
819+
9679920818BBAE2800394606 /* Build configuration list for PBXProject "adjust" */ = {
820820
isa = XCConfigurationList;
821821
buildConfigurations = (
822822
9679922E18BBAE2800394606 /* Debug */,

Adjust/ADJActivityHandler.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030

3131
- (BOOL) updateAttribution:(ADJAttribution*) attribution;
3232
- (void) setIadDate:(NSDate*)iAdImpressionDate withPurchaseDate:(NSDate*)appPurchaseDate;
33+
- (void)setIadDetails:(NSDictionary *)attributionDetails
34+
error:(NSError *)error
35+
retriesLeft:(int)retriesLeft;
3336

3437
- (void) launchAttributionDelegate;
3538

Adjust/ADJActivityHandler.m

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
static NSString * const kAttributionFilename = @"AdjustIoAttribution";
2323
static NSString * const kAdjustPrefix = @"adjust_";
2424
static const char * const kInternalQueueName = "io.adjust.ActivityQueue";
25+
// number of tries
26+
static const int kTryIadV3 = 2;
27+
static const uint64_t kDelayRetryIad = 2 * NSEC_PER_SEC; // 1 second
2528

2629
#pragma mark -
2730
@interface ADJActivityHandler()
@@ -43,6 +46,12 @@ @interface ADJActivityHandler()
4346

4447
@end
4548

49+
// copy from ADClientError
50+
typedef NS_ENUM(NSInteger, AdjADClientError) {
51+
AdjADClientErrorUnknown = 0,
52+
AdjADClientErrorLimitAdTracking = 1,
53+
};
54+
4655
#pragma mark -
4756
@implementation ADJActivityHandler
4857

@@ -234,9 +243,53 @@ - (void)setIadDate:(NSDate *)iAdImpressionDate withPurchaseDate:(NSDate *)appPur
234243
config:self.adjustConfig
235244
createdAt:now];
236245

237-
[clickBuilder setPurchaseTime:appPurchaseDate];
246+
clickBuilder.purchaseTime = appPurchaseDate;
247+
clickBuilder.clickTime = iAdImpressionDate;
238248

239-
ADJActivityPackage *clickPackage = [clickBuilder buildClickPackage:@"iad" clickTime:iAdImpressionDate];
249+
ADJActivityPackage *clickPackage = [clickBuilder buildClickPackage:@"iad"];
250+
[self.packageHandler addPackage:clickPackage];
251+
}
252+
253+
- (void)setIadDetails:(NSDictionary *)attributionDetails
254+
error:(NSError *)error
255+
retriesLeft:(int)retriesLeft
256+
{
257+
if (![ADJUtil isNull:error]) {
258+
[self.logger error:@"iAd details error (%s)", [error description]];
259+
260+
if (retriesLeft < 0) {
261+
[self.logger error:@"Reached limit number of retry for iAd"];
262+
return;
263+
}
264+
265+
if (retriesLeft == 0) {
266+
[self.logger error:@"Reached limit number of retry for iAd, trying iAd v2"];
267+
}
268+
269+
if (error.code == AdjADClientErrorUnknown) {
270+
271+
dispatch_time_t retryTime = dispatch_time(DISPATCH_TIME_NOW, kDelayRetryIad);
272+
dispatch_after(retryTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
273+
[[UIDevice currentDevice] adjSetIad:self triesV3Left:retriesLeft];
274+
});
275+
}
276+
return;
277+
}
278+
279+
if ([ADJUtil isNull:attributionDetails]) {
280+
return;
281+
}
282+
283+
double now = [NSDate.date timeIntervalSince1970];
284+
ADJPackageBuilder *clickBuilder = [[ADJPackageBuilder alloc]
285+
initWithDeviceInfo:self.deviceInfo
286+
activityState:self.activityState
287+
config:self.adjustConfig
288+
createdAt:now];
289+
290+
clickBuilder.iadDetails = attributionDetails;
291+
292+
ADJActivityPackage *clickPackage = [clickBuilder buildClickPackage:@"iad3"];
240293
[self.packageHandler addPackage:clickPackage];
241294
}
242295

@@ -317,8 +370,7 @@ - (void)initInternal {
317370
queue:self.internalQueue
318371
startTime:ADJAdjustFactory.timerStart
319372
intervalTime:ADJAdjustFactory.timerInterval];
320-
321-
[[UIDevice currentDevice] adjSetIad:self];
373+
[[UIDevice currentDevice] adjSetIad:self triesV3Left:kTryIadV3];
322374

323375
[self startInternal];
324376
}
@@ -469,8 +521,9 @@ - (void) appWillOpenUrlInternal:(NSURL *)url {
469521
createdAt:now];
470522
clickBuilder.deeplinkParameters = adjustDeepLinks;
471523
clickBuilder.attribution = deeplinkAttribution;
524+
clickBuilder.clickTime = [NSDate date];
472525

473-
ADJActivityPackage *clickPackage = [clickBuilder buildClickPackage:@"deeplink" clickTime:[NSDate date]];
526+
ADJActivityPackage *clickPackage = [clickBuilder buildClickPackage:@"deeplink"];
474527
[self.packageHandler addPackage:clickPackage];
475528
}
476529

Adjust/ADJAdditions/UIDevice+ADJAdditions.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@
1818
- (NSString *)adjDeviceName;
1919
- (NSString *)adjCreateUuid;
2020
- (NSString *)adjVendorId;
21-
- (void)adjSetIad:(ADJActivityHandler *)activityHandler;
21+
- (void)adjSetIad:(ADJActivityHandler *)activityHandler
22+
triesV3Left:(int)triesV3Left;
2223
@end

Adjust/ADJAdditions/UIDevice+ADJAdditions.m

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,41 +140,89 @@ - (NSString *)adjVendorId {
140140
}
141141

142142
- (void) adjSetIad:(ADJActivityHandler *) activityHandler
143+
triesV3Left:(int)triesV3Left
143144
{
144145
id<ADJLogger> logger = [ADJAdjustFactory logger];
146+
[logger debug:@"iAd with %d tries to read v3", triesV3Left];
145147

146148
#if ADJUST_NO_IAD || TARGET_OS_TV
147149
[logger debug:@"ADJUST_NO_IAD or TARGET_OS_TV set"];
148150
return;
149151
#else
150152
[logger debug:@"ADJUST_NO_IAD or TARGET_OS_TV not set"];
151153

152-
// [[ADClient sharedClient] lookupAdConversionDetails:...]
154+
// [[ADClient sharedClient] ...]
153155
Class ADClientClass = NSClassFromString(@"ADClient");
154156
if (ADClientClass == nil) {
155157
return;
156158
}
157-
158159
#pragma clang diagnostic push
159160
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
160-
161161
SEL sharedClientSelector = NSSelectorFromString(@"sharedClient");
162162
if (![ADClientClass respondsToSelector:sharedClientSelector]) {
163163
return;
164164
}
165165
id ADClientSharedClientInstance = [ADClientClass performSelector:sharedClientSelector];
166166

167-
SEL iadDateSelector = NSSelectorFromString(@"lookupAdConversionDetails:");
168-
if (![ADClientSharedClientInstance respondsToSelector:iadDateSelector]) {
167+
if (ADClientSharedClientInstance == nil) {
169168
return;
170169
}
171170

171+
// if no tries for iad v3 left -> iad v2
172+
if (triesV3Left == 0) {
173+
[self adjSetIadWithDates:activityHandler ADClientSharedClientInstance:ADClientSharedClientInstance];
174+
return;
175+
}
176+
177+
BOOL isIadV3Avaliable = [self adjSetIadWithDetails:activityHandler
178+
ADClientSharedClientInstance:ADClientSharedClientInstance
179+
retriesLeft:(triesV3Left - 1)];
180+
181+
// if no tries for iad v3 left -> iad v2
182+
if (!isIadV3Avaliable) {
183+
[self adjSetIadWithDates:activityHandler ADClientSharedClientInstance:ADClientSharedClientInstance];
184+
}
185+
#pragma clang diagnostic pop
186+
#endif
187+
}
188+
189+
- (BOOL)adjSetIadWithDetails:(ADJActivityHandler *)activityHandler
190+
ADClientSharedClientInstance:(id)ADClientSharedClientInstance
191+
retriesLeft:(int)retriesLeft
192+
{
193+
SEL iadDetailsSelector = NSSelectorFromString(@"requestAttributionDetailsWithBlock:");
194+
195+
if (![ADClientSharedClientInstance respondsToSelector:iadDetailsSelector]) {
196+
return NO;
197+
}
198+
199+
#pragma clang diagnostic push
200+
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
201+
[ADClientSharedClientInstance performSelector:iadDetailsSelector
202+
withObject:^(NSDictionary *attributionDetails, NSError *error) {
203+
[activityHandler setIadDetails:attributionDetails error:error retriesLeft:retriesLeft];
204+
}];
205+
#pragma clang diagnostic pop
206+
207+
return YES;
208+
}
209+
210+
- (BOOL)adjSetIadWithDates:(ADJActivityHandler *)activityHandler
211+
ADClientSharedClientInstance:(id)ADClientSharedClientInstance
212+
{
213+
SEL iadDateSelector = NSSelectorFromString(@"lookupAdConversionDetails:");
214+
215+
if (![ADClientSharedClientInstance respondsToSelector:iadDateSelector]) {
216+
return NO;
217+
}
218+
#pragma clang diagnostic push
219+
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
172220
[ADClientSharedClientInstance performSelector:iadDateSelector
173221
withObject:^(NSDate *appPurchaseDate, NSDate *iAdImpressionDate) {
174222
[activityHandler setIadDate:iAdImpressionDate withPurchaseDate:appPurchaseDate];
175223
}];
176224

177225
#pragma clang diagnostic pop
178-
#endif
226+
return YES;
179227
}
180228
@end

Adjust/ADJPackageBuilder.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
@property (nonatomic, copy) ADJAttribution *attribution;
1818
@property (nonatomic, copy) NSDate *purchaseTime;
19+
@property (nonatomic, copy) NSDate *clickTime;
20+
@property (nonatomic, retain) NSDictionary *iadDetails;
1921
@property (nonatomic, retain) NSDictionary* deeplinkParameters;
2022

2123
- (id) initWithDeviceInfo:(ADJDeviceInfo *)deviceInfo
@@ -25,8 +27,7 @@
2527

2628
- (ADJActivityPackage *)buildSessionPackage;
2729
- (ADJActivityPackage *)buildEventPackage:(ADJEvent *)event;
28-
- (ADJActivityPackage *)buildClickPackage:(NSString *)clickSource
29-
clickTime:(NSDate *)clickTime;
30+
- (ADJActivityPackage *)buildClickPackage:(NSString *)clickSource;
3031
- (ADJActivityPackage *)buildAttributionPackage;
3132

3233
@end

Adjust/ADJPackageBuilder.m

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ - (ADJActivityPackage *)buildEventPackage:(ADJEvent *) event{
6161
[self parameters:parameters setString:event.currency forKey:@"currency"];
6262
[self parameters:parameters setString:event.eventToken forKey:@"event_token"];
6363

64-
[self parameters:parameters setDictionaryJson:event.callbackParameters forKey:@"callback_params"];
65-
[self parameters:parameters setDictionaryJson:event.partnerParameters forKey:@"partner_params"];
64+
[self parameters:parameters setDictionary:event.callbackParameters forKey:@"callback_params"];
65+
[self parameters:parameters setDictionary:event.partnerParameters forKey:@"partner_params"];
6666

6767
if (event.emptyReceipt) {
6868
NSString *emptyReceipt = @"empty";
@@ -85,13 +85,12 @@ - (ADJActivityPackage *)buildEventPackage:(ADJEvent *) event{
8585
}
8686

8787
- (ADJActivityPackage *)buildClickPackage:(NSString *)clickSource
88-
clickTime:(NSDate *)clickTime
8988
{
9089
NSMutableDictionary *parameters = [self idsParameters];
9190

9291
[self parameters:parameters setString:clickSource forKey:@"source"];
93-
[self parameters:parameters setDictionaryJson:self.deeplinkParameters forKey:@"params"];
94-
[self parameters:parameters setDate:clickTime forKey:@"click_time"];
92+
[self parameters:parameters setDictionary:self.deeplinkParameters forKey:@"params"];
93+
[self parameters:parameters setDate:self.clickTime forKey:@"click_time"];
9594
[self parameters:parameters setDate:self.purchaseTime forKey:@"purchase_time"];
9695

9796
if (self.attribution != nil) {
@@ -100,6 +99,7 @@ - (ADJActivityPackage *)buildClickPackage:(NSString *)clickSource
10099
[self parameters:parameters setString:self.attribution.adgroup forKey:@"adgroup"];
101100
[self parameters:parameters setString:self.attribution.creative forKey:@"creative"];
102101
}
102+
[self parameters:parameters setDictionary:self.iadDetails forKey:@"details"];
103103

104104
ADJActivityPackage *clickPackage = [self defaultActivityPackage];
105105
clickPackage.path = @"/sdk_click";
@@ -247,12 +247,22 @@ - (void)parameters:(NSMutableDictionary *)parameters setDuration:(double)value f
247247
- (void)parameters:(NSMutableDictionary *)parameters setDictionaryJson:(NSDictionary *)dictionary forKey:(NSString *)key {
248248
if (dictionary == nil) return;
249249
if (dictionary.count == 0) return;
250+
if (![NSJSONSerialization isValidJSONObject:dictionary]) return;
250251

251252
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil];
252253
NSString *dictionaryString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
253254
[self parameters:parameters setString:dictionaryString forKey:key];
254255
}
255256

257+
- (void)parameters:(NSMutableDictionary *)parameters setDictionary:(NSDictionary *)dictionary forKey:(NSString *)key {
258+
if (dictionary == nil) return;
259+
if (dictionary.count == 0) return;
260+
261+
NSDictionary * convertedDictionary = [ADJUtil convertDictionaryValues:dictionary];
262+
263+
[self parameters:parameters setDictionaryJson:convertedDictionary forKey:key];
264+
}
265+
256266
- (void)parameters:(NSMutableDictionary *)parameters setBool:(BOOL)value forKey:(NSString *)key {
257267
int valueInt = [[NSNumber numberWithBool:value] intValue];
258268

Adjust/ADJUtil.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@ jsonResponseHandler:(void (^) (NSDictionary * jsonDict))jsonResponseHandler;
3939
suffixErrorMessage:(NSString *)suffixErrorMessage
4040
jsonResponseHandler:(void (^) (NSDictionary * jsonDict))jsonResponseHandler;
4141

42+
+ (NSDictionary *)convertDictionaryValues:(NSDictionary *)dictionary;
4243
@end

Adjust/ADJUtil.m

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include <sys/xattr.h>
1717

1818
static NSString * const kBaseUrl = @"https://app.adjust.com";
19-
static NSString * const kClientSdk = @"ios4.4.4";
19+
static NSString * const kClientSdk = @"ios4.4.5";
2020

2121
static NSString * const kDateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'Z";
2222
static NSDateFormatter *dateFormat;
@@ -106,12 +106,10 @@ + (NSString *)formatSeconds1970:(double) value {
106106
return [self formatDate:date];
107107
}
108108

109-
110109
+ (NSString *)formatDate:(NSDate *) value {
111110
return [dateFormat stringFromDate:value];
112111
}
113112

114-
115113
+ (NSDictionary *)buildJsonDict:(NSData *)jsonData {
116114
if (jsonData == nil) {
117115
return nil;
@@ -329,4 +327,31 @@ + (NSDictionary *)completionHandler:(NSData *)responseData
329327

330328
return jsonDict;
331329
}
330+
331+
// convert all values to strings, if value is dictionary -> recursive call
332+
+ (NSDictionary *)convertDictionaryValues:(NSDictionary *)dictionary
333+
{
334+
NSMutableDictionary * convertedDictionary = [[NSMutableDictionary alloc] initWithCapacity:dictionary.count];
335+
336+
for (NSString * key in dictionary) {
337+
id value = [dictionary objectForKey:key];
338+
if ([value isKindOfClass:[NSDictionary class]]) {
339+
// dictionary value, recursive call
340+
NSDictionary * dictionaryValue = [ADJUtil convertDictionaryValues:(NSDictionary *)value];
341+
[convertedDictionary setObject:dictionaryValue forKey:key];
342+
343+
} else if ([value isKindOfClass:[NSDate class]]) {
344+
// format date to our custom format
345+
NSString * dateStingValue = [ADJUtil formatDate:value];
346+
[convertedDictionary setObject:dateStingValue forKey:key];
347+
348+
} else {
349+
// convert all other objects directly to string
350+
NSString * stringValue = [NSString stringWithFormat:@"%@", value];
351+
[convertedDictionary setObject:stringValue forKey:key];
352+
}
353+
}
354+
355+
return convertedDictionary;
356+
}
332357
@end

0 commit comments

Comments
 (0)