346 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
		
		
			
		
	
	
			346 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
|  | // | ||
|  | //  AdjustUnityDelegate.mm | ||
|  | //  Adjust SDK | ||
|  | // | ||
|  | //  Created by Uglješa Erceg (@uerceg) on 5th December 2016. | ||
|  | //  Copyright © 2012-2018 Adjust GmbH. All rights reserved. | ||
|  | // | ||
|  | 
 | ||
|  | #import <objc/runtime.h> | ||
|  | #import "AdjustUnityDelegate.h" | ||
|  | 
 | ||
|  | static dispatch_once_t onceToken; | ||
|  | static AdjustUnityDelegate *defaultInstance = nil; | ||
|  | 
 | ||
|  | @implementation AdjustUnityDelegate | ||
|  | 
 | ||
|  | #pragma mark - Object lifecycle methods | ||
|  | 
 | ||
|  | - (id)init { | ||
|  |     self = [super init]; | ||
|  |     if (nil == self) { | ||
|  |         return nil; | ||
|  |     } | ||
|  |     return self; | ||
|  | } | ||
|  | 
 | ||
|  | #pragma mark - Public methods | ||
|  | 
 | ||
|  | + (id)getInstanceWithAttributionCallback:(AdjustDelegateAttributionCallback)attributionCallback | ||
|  |                     eventSuccessCallback:(AdjustDelegateEventSuccessCallback)eventSuccessCallback | ||
|  |                     eventFailureCallback:(AdjustDelegateEventFailureCallback)eventFailureCallback | ||
|  |                   sessionSuccessCallback:(AdjustDelegateSessionSuccessCallback)sessionSuccessCallback | ||
|  |                   sessionFailureCallback:(AdjustDelegateSessionFailureCallback)sessionFailureCallback | ||
|  |                 deferredDeeplinkCallback:(AdjustDelegateDeferredDeeplinkCallback)deferredDeeplinkCallback | ||
|  |                      skanUpdatedCallback:(AdjustDelegateSkanUpdatedCallback)skanUpdatedCallback | ||
|  |             shouldLaunchDeferredDeeplink:(BOOL)shouldLaunchDeferredDeeplink { | ||
|  |     dispatch_once(&onceToken, ^{ | ||
|  |         defaultInstance = [[AdjustUnityDelegate alloc] init]; | ||
|  | 
 | ||
|  |         // Do the swizzling where and if needed. | ||
|  |         if (attributionCallback != nil) { | ||
|  |             [defaultInstance swizzleOriginalSelector:@selector(adjustAttributionChanged:) | ||
|  |                                         withSelector:@selector(adjustAttributionChangedWannabe:)]; | ||
|  |         } | ||
|  |         if (eventSuccessCallback != nil) { | ||
|  |             [defaultInstance swizzleOriginalSelector:@selector(adjustEventTrackingSucceeded:) | ||
|  |                                         withSelector:@selector(adjustEventTrackingSucceededWannabe:)]; | ||
|  |         } | ||
|  |         if (eventFailureCallback != nil) { | ||
|  |             [defaultInstance swizzleOriginalSelector:@selector(adjustEventTrackingFailed:) | ||
|  |                                         withSelector:@selector(adjustEventTrackingFailedWannabe:)]; | ||
|  |         } | ||
|  |         if (sessionSuccessCallback != nil) { | ||
|  |             [defaultInstance swizzleOriginalSelector:@selector(adjustSessionTrackingSucceeded:) | ||
|  |                                         withSelector:@selector(adjustSessionTrackingSucceededWannabe:)]; | ||
|  |         } | ||
|  |         if (sessionFailureCallback != nil) { | ||
|  |             [defaultInstance swizzleOriginalSelector:@selector(adjustSessionTrackingFailed:) | ||
|  |                                         withSelector:@selector(adjustSessionTrackingFailedWannabe:)]; | ||
|  |         } | ||
|  |         if (deferredDeeplinkCallback != nil) { | ||
|  |             [defaultInstance swizzleOriginalSelector:@selector(adjustDeferredDeeplinkReceived:) | ||
|  |                                         withSelector:@selector(adjustDeferredDeeplinkReceivedWannabe:)]; | ||
|  |         } | ||
|  |         if (skanUpdatedCallback != nil) { | ||
|  |             [defaultInstance swizzleOriginalSelector:@selector(adjustSkanUpdatedWithConversionData:) | ||
|  |                                         withSelector:@selector(adjustSkanUpdatedWithConversionDataWannabe:)]; | ||
|  |         } | ||
|  | 
 | ||
|  |         [defaultInstance setAttributionCallback:attributionCallback]; | ||
|  |         [defaultInstance setEventSuccessCallback:eventSuccessCallback]; | ||
|  |         [defaultInstance setEventFailureCallback:eventFailureCallback]; | ||
|  |         [defaultInstance setSessionSuccessCallback:sessionSuccessCallback]; | ||
|  |         [defaultInstance setSessionFailureCallback:sessionFailureCallback]; | ||
|  |         [defaultInstance setDeferredDeeplinkCallback:deferredDeeplinkCallback]; | ||
|  |         [defaultInstance setSkanUpdatedCallback:skanUpdatedCallback]; | ||
|  |         [defaultInstance setShouldLaunchDeferredDeeplink:shouldLaunchDeferredDeeplink]; | ||
|  |     }); | ||
|  |      | ||
|  |     return defaultInstance; | ||
|  | } | ||
|  | 
 | ||
|  | + (void)teardown { | ||
|  |     defaultInstance = nil; | ||
|  |     onceToken = 0; | ||
|  | } | ||
|  | 
 | ||
|  | #pragma mark - Private & helper methods | ||
|  | 
 | ||
|  | - (void)adjustAttributionChangedWannabe:(ADJAttribution *)attribution { | ||
|  |     if (attribution == nil || _attributionCallback == nil) { | ||
|  |         return; | ||
|  |     } | ||
|  |      | ||
|  |     NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; | ||
|  |     [self addValueOrEmpty:attribution.trackerToken | ||
|  |                    forKey:@"trackerToken" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:attribution.trackerName | ||
|  |                    forKey:@"trackerName" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:attribution.network | ||
|  |                    forKey:@"network" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:attribution.campaign | ||
|  |                    forKey:@"campaign" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:attribution.creative | ||
|  |                    forKey:@"creative" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:attribution.adgroup | ||
|  |                    forKey:@"adgroup" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:attribution.clickLabel | ||
|  |                    forKey:@"clickLabel" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:attribution.costType | ||
|  |                    forKey:@"costType" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:attribution.costAmount | ||
|  |                    forKey:@"costAmount" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:attribution.costCurrency | ||
|  |                    forKey:@"costCurrency" | ||
|  |              toDictionary:dictionary]; | ||
|  | 
 | ||
|  |     if (attribution.jsonResponse != nil) { | ||
|  |         NSData *jsonData = [NSJSONSerialization dataWithJSONObject:attribution.jsonResponse  | ||
|  |                                                            options:0 | ||
|  |                                                              error:nil]; | ||
|  |         NSString *strJsonResponse = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; | ||
|  |         [self addValueOrEmpty:strJsonResponse | ||
|  |                        forKey:@"jsonResponse" | ||
|  |                  toDictionary:dictionary]; | ||
|  |     } | ||
|  | 
 | ||
|  |     NSData *dataAttribution = [NSJSONSerialization dataWithJSONObject:dictionary | ||
|  |                                                               options:0 | ||
|  |                                                                 error:nil]; | ||
|  |     NSString *stringAttribution = [[NSString alloc] initWithBytes:[dataAttribution bytes] | ||
|  |                                                            length:[dataAttribution length] | ||
|  |                                                          encoding:NSUTF8StringEncoding]; | ||
|  |     const char* charArrayAttribution = [stringAttribution UTF8String]; | ||
|  |     _attributionCallback(charArrayAttribution); | ||
|  | } | ||
|  | 
 | ||
|  | - (void)adjustEventTrackingSucceededWannabe:(ADJEventSuccess *)eventSuccessResponseData { | ||
|  |     if (nil == eventSuccessResponseData || _eventSuccessCallback == nil) { | ||
|  |         return; | ||
|  |     } | ||
|  | 
 | ||
|  |     NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; | ||
|  |     [self addValueOrEmpty:eventSuccessResponseData.message | ||
|  |                    forKey:@"message" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:eventSuccessResponseData.timestamp | ||
|  |                    forKey:@"timestamp" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:eventSuccessResponseData.adid | ||
|  |                    forKey:@"adid" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:eventSuccessResponseData.eventToken | ||
|  |                    forKey:@"eventToken" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:eventSuccessResponseData.callbackId | ||
|  |                    forKey:@"callbackId" | ||
|  |              toDictionary:dictionary]; | ||
|  |     if (eventSuccessResponseData.jsonResponse != nil) { | ||
|  |         [dictionary setObject:eventSuccessResponseData.jsonResponse | ||
|  |                        forKey:@"jsonResponse"]; | ||
|  |     } | ||
|  | 
 | ||
|  |     NSData *dataEventSuccess = [NSJSONSerialization dataWithJSONObject:dictionary | ||
|  |                                                                options:0 | ||
|  |                                                                  error:nil]; | ||
|  |     NSString *stringEventSuccess = [[NSString alloc] initWithBytes:[dataEventSuccess bytes] | ||
|  |                                                             length:[dataEventSuccess length] | ||
|  |                                                           encoding:NSUTF8StringEncoding]; | ||
|  |     const char* charArrayEventSuccess = [stringEventSuccess UTF8String]; | ||
|  |     _eventSuccessCallback(charArrayEventSuccess); | ||
|  | } | ||
|  | 
 | ||
|  | - (void)adjustEventTrackingFailedWannabe:(ADJEventFailure *)eventFailureResponseData { | ||
|  |     if (nil == eventFailureResponseData || _eventFailureCallback == nil) { | ||
|  |         return; | ||
|  |     } | ||
|  | 
 | ||
|  |     NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; | ||
|  |     [self addValueOrEmpty:eventFailureResponseData.message | ||
|  |                    forKey:@"message" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:eventFailureResponseData.timestamp | ||
|  |                    forKey:@"timestamp" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:eventFailureResponseData.adid | ||
|  |                    forKey:@"adid" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:eventFailureResponseData.eventToken | ||
|  |                    forKey:@"eventToken" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:eventFailureResponseData.callbackId | ||
|  |                    forKey:@"callbackId" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [dictionary setObject:(eventFailureResponseData.willRetry ? @"true" : @"false") | ||
|  |                    forKey:@"willRetry"]; | ||
|  |     if (eventFailureResponseData.jsonResponse != nil) { | ||
|  |         [dictionary setObject:eventFailureResponseData.jsonResponse | ||
|  |                        forKey:@"jsonResponse"]; | ||
|  |     } | ||
|  | 
 | ||
|  |     NSData *dataEventFailure = [NSJSONSerialization dataWithJSONObject:dictionary | ||
|  |                                                                options:0 | ||
|  |                                                                  error:nil]; | ||
|  |     NSString *stringEventFailure = [[NSString alloc] initWithBytes:[dataEventFailure bytes] | ||
|  |                                                             length:[dataEventFailure length] | ||
|  |                                                           encoding:NSUTF8StringEncoding]; | ||
|  |     const char* charArrayEventFailure = [stringEventFailure UTF8String]; | ||
|  |     _eventFailureCallback(charArrayEventFailure); | ||
|  | } | ||
|  | 
 | ||
|  | - (void)adjustSessionTrackingSucceededWannabe:(ADJSessionSuccess *)sessionSuccessResponseData { | ||
|  |     if (nil == sessionSuccessResponseData || _sessionSuccessCallback == nil) { | ||
|  |         return; | ||
|  |     } | ||
|  | 
 | ||
|  |     NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; | ||
|  |     [self addValueOrEmpty:sessionSuccessResponseData.message | ||
|  |                    forKey:@"message" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:sessionSuccessResponseData.timestamp | ||
|  |                    forKey:@"timestamp" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:sessionSuccessResponseData.adid | ||
|  |                    forKey:@"adid" | ||
|  |              toDictionary:dictionary]; | ||
|  |     if (sessionSuccessResponseData.jsonResponse != nil) { | ||
|  |         [dictionary setObject:sessionSuccessResponseData.jsonResponse | ||
|  |                        forKey:@"jsonResponse"]; | ||
|  |     } | ||
|  | 
 | ||
|  |     NSData *dataSessionSuccess = [NSJSONSerialization dataWithJSONObject:dictionary | ||
|  |                                                                  options:0 | ||
|  |                                                                    error:nil]; | ||
|  |     NSString *stringSessionSuccess = [[NSString alloc] initWithBytes:[dataSessionSuccess bytes] | ||
|  |                                                               length:[dataSessionSuccess length] | ||
|  |                                                             encoding:NSUTF8StringEncoding]; | ||
|  |     const char* charArraySessionSuccess = [stringSessionSuccess UTF8String]; | ||
|  |     _sessionSuccessCallback(charArraySessionSuccess); | ||
|  | } | ||
|  | 
 | ||
|  | - (void)adjustSessionTrackingFailedWannabe:(ADJSessionFailure *)sessionFailureResponseData { | ||
|  |     if (nil == sessionFailureResponseData || _sessionFailureCallback == nil) { | ||
|  |         return; | ||
|  |     } | ||
|  | 
 | ||
|  |     NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; | ||
|  |     [self addValueOrEmpty:sessionFailureResponseData.message | ||
|  |                    forKey:@"message" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:sessionFailureResponseData.timestamp | ||
|  |                    forKey:@"timestamp" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [self addValueOrEmpty:sessionFailureResponseData.adid | ||
|  |                    forKey:@"adid" | ||
|  |              toDictionary:dictionary]; | ||
|  |     [dictionary setObject:(sessionFailureResponseData.willRetry ? @"true" : @"false") | ||
|  |                    forKey:@"willRetry"]; | ||
|  |     if (sessionFailureResponseData.jsonResponse != nil) { | ||
|  |         [dictionary setObject:sessionFailureResponseData.jsonResponse | ||
|  |                        forKey:@"jsonResponse"]; | ||
|  |     } | ||
|  | 
 | ||
|  |     NSData *dataSessionFailure = [NSJSONSerialization dataWithJSONObject:dictionary | ||
|  |                                                                  options:0 | ||
|  |                                                                    error:nil]; | ||
|  |     NSString *stringSessionFailure = [[NSString alloc] initWithBytes:[dataSessionFailure bytes] | ||
|  |                                                               length:[dataSessionFailure length] | ||
|  |                                                             encoding:NSUTF8StringEncoding]; | ||
|  |     const char* charArraySessionFailure = [stringSessionFailure UTF8String]; | ||
|  |     _sessionFailureCallback(charArraySessionFailure); | ||
|  | } | ||
|  | 
 | ||
|  | - (BOOL)adjustDeferredDeeplinkReceivedWannabe:(NSURL *)deeplink { | ||
|  |     if (_deferredDeeplinkCallback != nil) { | ||
|  |         NSString *stringDeeplink = [deeplink absoluteString]; | ||
|  |         const char* charDeeplink = [stringDeeplink UTF8String]; | ||
|  |         _deferredDeeplinkCallback(charDeeplink); | ||
|  |     } | ||
|  |     return _shouldLaunchDeferredDeeplink; | ||
|  | } | ||
|  | 
 | ||
|  | - (void)adjustSkanUpdatedWithConversionDataWannabe:(NSDictionary<NSString *,NSString *> *)data { | ||
|  |     if (data == nil || _skanUpdatedCallback == nil) { | ||
|  |         return; | ||
|  |     } | ||
|  | 
 | ||
|  |     NSData *dataSkanUpdatedData = [NSJSONSerialization dataWithJSONObject:data | ||
|  |                                                                   options:0 | ||
|  |                                                                     error:nil]; | ||
|  |     NSString *strSkanUpdatedData = [[NSString alloc] initWithBytes:[dataSkanUpdatedData bytes] | ||
|  |                                                             length:[dataSkanUpdatedData length] | ||
|  |                                                           encoding:NSUTF8StringEncoding]; | ||
|  |     const char* charSkanUpdatedData = [strSkanUpdatedData UTF8String]; | ||
|  |     _skanUpdatedCallback(charSkanUpdatedData); | ||
|  | } | ||
|  | 
 | ||
|  | - (void)swizzleOriginalSelector:(SEL)originalSelector | ||
|  |                    withSelector:(SEL)swizzledSelector { | ||
|  |     Class className = [self class]; | ||
|  |     Method originalMethod = class_getInstanceMethod(className, originalSelector); | ||
|  |     Method swizzledMethod = class_getInstanceMethod(className, swizzledSelector); | ||
|  | 
 | ||
|  |     BOOL didAddMethod = class_addMethod(className, | ||
|  |                                         originalSelector, | ||
|  |                                         method_getImplementation(swizzledMethod), | ||
|  |                                         method_getTypeEncoding(swizzledMethod)); | ||
|  |     if (didAddMethod) { | ||
|  |         class_replaceMethod(className, | ||
|  |                             swizzledSelector, | ||
|  |                             method_getImplementation(originalMethod), | ||
|  |                             method_getTypeEncoding(originalMethod)); | ||
|  |     } else { | ||
|  |         method_exchangeImplementations(originalMethod, swizzledMethod); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | - (void)addValueOrEmpty:(NSObject *)value | ||
|  |                  forKey:(NSString *)key | ||
|  |            toDictionary:(NSMutableDictionary *)dictionary { | ||
|  |     if (nil != value) { | ||
|  |         if ([value isKindOfClass:[NSString class]]) { | ||
|  |             [dictionary setObject:[NSString stringWithFormat:@"%@", value] | ||
|  |                            forKey:key]; | ||
|  |         } else if ([value isKindOfClass:[NSNumber class]]) { | ||
|  |             [dictionary setObject:[NSString stringWithFormat:@"%@", [((NSNumber *)value) stringValue]] | ||
|  |                            forKey:key]; | ||
|  |         } else { | ||
|  |             [dictionary setObject:@"" forKey:key]; | ||
|  |         } | ||
|  |     } else { | ||
|  |         [dictionary setObject:@"" forKey:key]; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | @end |