diff --git a/Adjust.podspec b/Adjust.podspec index 671a0ab60..af71cca67 100644 --- a/Adjust.podspec +++ b/Adjust.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = "Adjust" - s.version = "4.20.0" + s.version = "4.21.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.20.0" } + s.source = { :git => "https://github.com/adjust/ios_sdk.git", :tag => "v4.21.0" } s.ios.deployment_target = '6.0' s.tvos.deployment_target = '9.0' s.framework = 'SystemConfiguration' diff --git a/Adjust.xcodeproj/project.pbxproj b/Adjust.xcodeproj/project.pbxproj index 165783ada..4ebae30f3 100644 --- a/Adjust.xcodeproj/project.pbxproj +++ b/Adjust.xcodeproj/project.pbxproj @@ -2197,7 +2197,7 @@ 9679920518BBAE2800394606 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1100; + LastUpgradeCheck = 1130; ORGANIZATIONNAME = "adjust GmbH"; TargetAttributes = { 9615158E1CD2CB2C0022D336 = { diff --git a/Adjust.xcodeproj/xcshareddata/xcschemes/AdjustSdk.xcscheme b/Adjust.xcodeproj/xcshareddata/xcschemes/AdjustSdk.xcscheme index 3bc3ca30c..40aed6fbe 100644 --- a/Adjust.xcodeproj/xcshareddata/xcschemes/AdjustSdk.xcscheme +++ b/Adjust.xcodeproj/xcshareddata/xcschemes/AdjustSdk.xcscheme @@ -1,6 +1,6 @@ - - - - - - - - - - - - - - - - )attributionHandlerForActivityHandler:(id)activityHandler startsSending:(BOOL)startsSending; @@ -61,5 +62,8 @@ + (void)setBaseUrl:(NSString *)baseUrl; + (void)setGdprUrl:(NSString *)gdprUrl; ++ (void)enableSigning; ++ (void)disableSigning; + + (void)teardown:(BOOL)deleteState; @end diff --git a/Adjust/ADJAdjustFactory.m b/Adjust/ADJAdjustFactory.m index 34dd05e30..2c59c67bd 100644 --- a/Adjust/ADJAdjustFactory.m +++ b/Adjust/ADJAdjustFactory.m @@ -21,6 +21,7 @@ static NSTimeInterval intervalTimerStart = -1; static ADJBackoffStrategy * packageHandlerBackoffStrategy = nil; static ADJBackoffStrategy * sdkClickHandlerBackoffStrategy = nil; +static ADJBackoffStrategy * installSessionBackoffStrategy = nil; static BOOL internalTesting = NO; static NSTimeInterval internalMaxDelayStart = -1; static BOOL internaliAdFrameworkEnabled = YES; @@ -113,6 +114,13 @@ + (ADJBackoffStrategy *)sdkClickHandlerBackoffStrategy { return sdkClickHandlerBackoffStrategy; } ++ (ADJBackoffStrategy *)installSessionBackoffStrategy { + if (installSessionBackoffStrategy == nil) { + return [ADJBackoffStrategy backoffStrategyWithType:ADJShortWait]; + } + return installSessionBackoffStrategy; +} + + (id)attributionHandlerForActivityHandler:(id)activityHandler startsSending:(BOOL)startsSending { @@ -226,6 +234,48 @@ + (void)setGdprUrl:(NSString *)gdprUrl { internalGdprUrl = gdprUrl; } ++ (void)enableSigning { + Class signerClass = NSClassFromString(@"ADJSigner"); + if (signerClass == nil) { + return; + } + + SEL enabledSEL = NSSelectorFromString(@"enableSigning"); + if (![signerClass respondsToSelector:enabledSEL]) { + return; + } + + IMP enableIMP = [signerClass methodForSelector:enabledSEL]; + if (!enableIMP) { + return; + } + + void (*enableFunc)(id, SEL) = (void *)enableIMP; + + enableFunc(signerClass, enabledSEL); +} + ++ (void)disableSigning { + Class signerClass = NSClassFromString(@"ADJSigner"); + if (signerClass == nil) { + return; + } + + SEL disableSEL = NSSelectorFromString(@"disableSigning"); + if (![signerClass respondsToSelector:disableSEL]) { + return; + } + + IMP disableIMP = [signerClass methodForSelector:disableSEL]; + if (!disableIMP) { + return; + } + + void (*disableFunc)(id, SEL) = (void *)disableIMP; + + disableFunc(signerClass, disableSEL); +} + + (void)teardown:(BOOL)deleteState { if (deleteState) { [ADJActivityHandler deleteState]; diff --git a/Adjust/ADJConfig.h b/Adjust/ADJConfig.h index 4437f4182..1bcccf9a2 100644 --- a/Adjust/ADJConfig.h +++ b/Adjust/ADJConfig.h @@ -143,6 +143,16 @@ */ @property (nonatomic, assign) BOOL sendInBackground; +/** + * @brief Enables/disables reading of iAd framework data needed for ASA tracking. + */ +@property (nonatomic, assign) BOOL allowiAdInfoReading; + +/** + * @brief Enables/disables reading of IDFA parameter. + */ +@property (nonatomic, assign) BOOL allowIdfaReading; + /** * @brief Enables delayed start of the SDK. */ diff --git a/Adjust/ADJConfig.m b/Adjust/ADJConfig.m index 5ea1f456d..90abe25ba 100644 --- a/Adjust/ADJConfig.m +++ b/Adjust/ADJConfig.m @@ -60,8 +60,12 @@ - (id)initWithAppToken:(NSString *)appToken _appToken = appToken; _environment = environment; + // default values + self.sendInBackground = NO; self.eventBufferingEnabled = NO; + self.allowIdfaReading = YES; + self.allowiAdInfoReading = YES; return self; } @@ -190,6 +194,8 @@ -(id)copyWithZone:(NSZone *)zone copy.defaultTracker = [self.defaultTracker copyWithZone:zone]; copy.eventBufferingEnabled = self.eventBufferingEnabled; copy.sendInBackground = self.sendInBackground; + copy.allowIdfaReading = self.allowIdfaReading; + copy.allowiAdInfoReading = self.allowiAdInfoReading; copy.delayStart = self.delayStart; copy.userAgent = [self.userAgent copyWithZone:zone]; copy.externalDeviceId = [self.externalDeviceId copyWithZone:zone]; diff --git a/Adjust/ADJPackageBuilder.m b/Adjust/ADJPackageBuilder.m index a3e342bba..bd961883b 100644 --- a/Adjust/ADJPackageBuilder.m +++ b/Adjust/ADJPackageBuilder.m @@ -60,6 +60,9 @@ - (ADJActivityPackage *)buildSessionPackage:(BOOL)isInDelay { sessionPackage.activityKind = ADJActivityKindSession; sessionPackage.suffix = @""; sessionPackage.parameters = parameters; + + [self signWithSigV2Plugin:sessionPackage]; + return sessionPackage; } @@ -77,6 +80,8 @@ - (ADJActivityPackage *)buildEventPackage:(ADJEvent *)event eventPackage.partnerParameters = event.partnerParameters; } + [self signWithSigV2Plugin:eventPackage]; + return eventPackage; } @@ -87,6 +92,9 @@ - (ADJActivityPackage *)buildInfoPackage:(NSString *)infoSource { infoPackage.activityKind = ADJActivityKindInfo; infoPackage.suffix = @""; infoPackage.parameters = parameters; + + [self signWithSigV2Plugin:infoPackage]; + return infoPackage; } @@ -97,6 +105,9 @@ - (ADJActivityPackage *)buildAdRevenuePackage:(NSString *)source payload:(NSData adRevenuePackage.activityKind = ADJActivityKindAdRevenue; adRevenuePackage.suffix = @""; adRevenuePackage.parameters = parameters; + + [self signWithSigV2Plugin:adRevenuePackage]; + return adRevenuePackage; } @@ -107,6 +118,9 @@ - (ADJActivityPackage *)buildClickPackage:(NSString *)clickSource { clickPackage.activityKind = ADJActivityKindClick; clickPackage.suffix = @""; clickPackage.parameters = parameters; + + [self signWithSigV2Plugin:clickPackage]; + return clickPackage; } @@ -117,6 +131,9 @@ - (ADJActivityPackage *)buildAttributionPackage:(NSString *)initiatedBy { attributionPackage.activityKind = ADJActivityKindAttribution; attributionPackage.suffix = @""; attributionPackage.parameters = parameters; + + [self signWithSigV2Plugin:attributionPackage]; + return attributionPackage; } @@ -127,6 +144,9 @@ - (ADJActivityPackage *)buildGdprPackage { gdprPackage.activityKind = ADJActivityKindGdpr; gdprPackage.suffix = @""; gdprPackage.parameters = parameters; + + [self signWithSigV2Plugin:gdprPackage]; + return gdprPackage; } @@ -137,6 +157,9 @@ - (ADJActivityPackage *)buildDisableThirdPartySharingPackage { dtpsPackage.activityKind = ADJActivityKindDisableThirdPartySharing; dtpsPackage.suffix = @""; dtpsPackage.parameters = parameters; + + [self signWithSigV2Plugin:dtpsPackage]; + return dtpsPackage; } @@ -164,6 +187,37 @@ + (void)parameters:(NSMutableDictionary *)parameters setString:(NSString *)value #pragma mark - Private & helper methods +- (void)signWithSigV2Plugin:(ADJActivityPackage *)activityPackage { + Class signerClass = NSClassFromString(@"ADJSigner"); + if (signerClass == nil) { + return; + } + + SEL signSEL = NSSelectorFromString(@"sign:withActivityKind:withSdkVersion:"); + if (![signerClass respondsToSelector:signSEL]) { + return; + } + + NSMutableDictionary * parameters = activityPackage.parameters; + const char * activityKindChar = [[ADJActivityKindUtil activityKindToString:activityPackage.activityKind] UTF8String]; + const char * sdkVersionChar = [activityPackage.clientSdk UTF8String]; + /* + [ADJSigner sign:parameters + withActivityKind:activityKindChar + withSdkVersion:sdkVersionChar]; + */ + NSMethodSignature *signMethodSignature = [signerClass methodSignatureForSelector:signSEL]; + NSInvocation *signInvocation = [NSInvocation invocationWithMethodSignature:signMethodSignature]; + [signInvocation setSelector: signSEL]; + [signInvocation setTarget:signerClass]; + + [signInvocation setArgument:¶meters atIndex: 2]; + [signInvocation setArgument:&activityKindChar atIndex: 3]; + [signInvocation setArgument:&sdkVersionChar atIndex: 4]; + + [signInvocation invoke]; +} + - (NSMutableDictionary *)getSessionParameters:(BOOL)isInDelay { NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; @@ -186,7 +240,9 @@ - (NSMutableDictionary *)getSessionParameters:(BOOL)isInDelay { [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"]; - [ADJPackageBuilder parameters:parameters setString:UIDevice.currentDevice.adjIdForAdvertisers forKey:@"idfa"]; + 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:[ADJUtil getInstallTime] forKey:@"installed_at"]; @@ -253,7 +309,9 @@ - (NSMutableDictionary *)getEventParameters:(BOOL)isInDelay forEventPackage:(ADJ [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"]; - [ADJPackageBuilder parameters:parameters setString:UIDevice.currentDevice.adjIdForAdvertisers forKey:@"idfa"]; + 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"]; @@ -324,7 +382,9 @@ - (NSMutableDictionary *)getInfoParameters:(NSString *)source { [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:UIDevice.currentDevice.adjIdForAdvertisers forKey:@"idfa"]; + 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 setBool:YES forKey:@"needs_response_details"]; [ADJPackageBuilder parameters:parameters setString:self.adjustConfig.secretId forKey:@"secret_id"]; @@ -349,26 +409,51 @@ - (NSMutableDictionary *)getInfoParameters:(NSString *)source { - (NSMutableDictionary *)getAdRevenueParameters:(NSString *)source payload:(NSData *)payload { NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; - [ADJPackageBuilder parameters:parameters setString:self.adjustConfig.appToken forKey:@"app_token"]; [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.adjustConfig.defaultTracker forKey:@"default_tracker"]; + [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:UIDevice.currentDevice.adjIdForAdvertisers forKey:@"idfa"]; + [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:[ADJUtil getInstallTime] forKey:@"installed_at"]; + [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 setString:source forKey:@"source"]; [ADJPackageBuilder parameters:parameters setData:payload forKey:@"payload"]; + [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 setDuration:self.activityState.lastInterval forKey:@"last_interval"]; [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 { @@ -376,6 +461,12 @@ - (NSMutableDictionary *)getAdRevenueParameters:(NSString *)source payload:(NSDa } } +#if !TARGET_OS_TV + [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; } @@ -406,7 +497,9 @@ - (NSMutableDictionary *)getClickParameters:(NSString *)source { [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"]; - [ADJPackageBuilder parameters:parameters setString:UIDevice.currentDevice.adjIdForAdvertisers forKey:@"idfa"]; + 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:[ADJUtil getInstallTime] forKey:@"installed_at"]; @@ -471,7 +564,9 @@ - (NSMutableDictionary *)getAttributionParameters:(NSString *)initiatedBy { [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:UIDevice.currentDevice.adjIdForAdvertisers forKey:@"idfa"]; + 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:initiatedBy forKey:@"initiated_by"]; [ADJPackageBuilder parameters:parameters setBool:YES forKey:@"needs_response_details"]; @@ -510,7 +605,9 @@ - (NSMutableDictionary *)getGdprParameters { [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:UIDevice.currentDevice.adjIdForAdvertisers forKey:@"idfa"]; + 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 setBool:YES forKey:@"needs_response_details"]; [ADJPackageBuilder parameters:parameters setString:self.deviceInfo.osBuild forKey:@"os_build"]; @@ -559,7 +656,9 @@ - (NSMutableDictionary *)getDisableThirdPartySharingParameters { [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"]; - [ADJPackageBuilder parameters:parameters setString:UIDevice.currentDevice.adjIdForAdvertisers forKey:@"idfa"]; + 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:[ADJUtil getInstallTime] forKey:@"installed_at"]; diff --git a/Adjust/ADJPackageHandler.m b/Adjust/ADJPackageHandler.m index 48f22115f..38122469b 100644 --- a/Adjust/ADJPackageHandler.m +++ b/Adjust/ADJPackageHandler.m @@ -13,6 +13,7 @@ #import "ADJAdjustFactory.h" #import "ADJBackoffStrategy.h" #import "ADJPackageBuilder.h" +#import "ADJUserDefaults.h" static NSString * const kPackageQueueFilename = @"AdjustIoPackageQueue"; static const char * const kInternalQueueName = "io.adjust.PackageQueue"; @@ -25,7 +26,8 @@ @interface ADJPackageHandler() @property (nonatomic, strong) dispatch_semaphore_t sendingSemaphore; @property (nonatomic, strong) id requestHandler; @property (nonatomic, strong) NSMutableArray *packageQueue; -@property (nonatomic, strong) ADJBackoffStrategy * backoffStrategy; +@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; @@ -51,6 +53,7 @@ - (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]; @@ -110,8 +113,13 @@ - (void)closeFirstPackage:(ADJResponseData *)responseData } NSInteger retries = [activityPackage increaseRetries]; - NSTimeInterval waitTime = [ADJUtil waitingTime:retries backoffStrategy:self.backoffStrategy]; - NSString * waitTimeFormatted = [ADJUtil secondsNumberFormat:waitTime]; + NSTimeInterval waitTime; + if ([activityPackage activityKind] == ADJActivityKindSession && [ADJUserDefaults getInstallTracked] == NO) { + waitTime = [ADJUtil waitingTime:retries backoffStrategy:self.backoffStrategyForInstallSession]; + } else { + waitTime = [ADJUtil waitingTime:retries backoffStrategy:self.backoffStrategy]; + } + NSString *waitTimeFormatted = [ADJUtil secondsNumberFormat:waitTime]; [self.logger verbose:@"Waiting for %@ seconds before retrying the %d time", waitTimeFormatted, retries]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(waitTime * NSEC_PER_SEC)), self.internalQueue, work); diff --git a/Adjust/ADJUtil.m b/Adjust/ADJUtil.m index db7f2eede..523ab3450 100644 --- a/Adjust/ADJUtil.m +++ b/Adjust/ADJUtil.m @@ -40,7 +40,7 @@ static CTTelephonyNetworkInfo *networkInfo = nil; #endif -static NSString * const kClientSdk = @"ios4.20.0"; +static NSString * const kClientSdk = @"ios4.21.0"; static NSString * const kDeeplinkParam = @"deep_link="; static NSString * const kSchemeDelimiter = @"://"; static NSString * const kDefaultScheme = @"AdjustUniversalScheme"; @@ -286,28 +286,42 @@ + (NSDictionary *)buildJsonDict:(NSData *)jsonData + (id)readObject:(NSString *)fileName objectName:(NSString *)objectName class:(Class)classToRead { - // Try to read from Application Support directory first. NSString *documentsFilePath = [ADJUtil getFilePathInDocumentsDir:fileName]; NSString *appSupportFilePath = [ADJUtil getFilePathInAppSupportDir:fileName]; + // Try to read from Application Support directory first. @try { - id appSupportObject = [NSKeyedUnarchiver unarchiveObjectWithFile:appSupportFilePath]; - if ([appSupportObject isKindOfClass:classToRead]) { - // Successfully read object from Application Support folder, return it. - if ([appSupportObject isKindOfClass:[NSArray class]]) { - [[ADJAdjustFactory logger] debug:@"Package handler read %d packages", [appSupportObject count]]; - } else { - [[ADJAdjustFactory logger] debug:@"Read %@: %@", objectName, appSupportObject]; + id appSupportObject; +#if !TARGET_OS_TV + if (@available(iOS 11.0, *)) { +#else + if (@available(tvOS 11.0, *)) { +#endif + NSData *data = [NSData dataWithContentsOfFile:appSupportFilePath]; + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; + [unarchiver setRequiresSecureCoding:NO]; + appSupportObject = [unarchiver decodeObjectOfClass:classToRead forKey:NSKeyedArchiveRootObjectKey]; + } else { + appSupportObject = [NSKeyedUnarchiver unarchiveObjectWithFile:appSupportFilePath]; + } + + if (appSupportObject != nil) { + if ([appSupportObject isKindOfClass:classToRead]) { + // Successfully read object from Application Support folder, return it. + if ([appSupportObject isKindOfClass:[NSArray class]]) { + [[ADJAdjustFactory logger] debug:@"Package handler read %d packages", [appSupportObject count]]; + } else { + [[ADJAdjustFactory logger] debug:@"Read %@: %@", objectName, appSupportObject]; + } + + // Just in case check if old file exists in Documents folder and if yes, remove it. + [ADJUtil deleteFileInPath:documentsFilePath]; + + return appSupportObject; } - // Just in case check if old file exists in Documents folder and if yes, remove it. - [ADJUtil deleteFileInPath:documentsFilePath]; - return appSupportObject; - } else if (appSupportObject == nil) { - // [[ADJAdjustFactory logger] verbose:@"%@ file not found", appSupportFilePath]; - [[ADJAdjustFactory logger] verbose:@"%@ file not found in \"Application Support/Adjust\" folder", fileName]; } else { // [[ADJAdjustFactory logger] error:@"Failed to read %@ file", appSupportFilePath]; - [[ADJAdjustFactory logger] error:@"Failed to read %@ file from \"Application Support/Adjust\" folder", fileName]; + [[ADJAdjustFactory logger] debug:@"File %@ not found in \"Application Support/Adjust\" folder", fileName]; } } @catch (NSException *ex) { // [[ADJAdjustFactory logger] error:@"Failed to read %@ file (%@)", appSupportFilePath, ex]; @@ -317,7 +331,20 @@ + (id)readObject:(NSString *)fileName // If in here, for some reason, reading of file from Application Support folder failed. // Let's check the Documents folder. @try { - id documentsObject = [NSKeyedUnarchiver unarchiveObjectWithFile:documentsFilePath]; + id documentsObject; +#if !TARGET_OS_TV + if (@available(iOS 11.0, *)) { +#else + if (@available(tvOS 11.0, *)) { +#endif + NSData *data = [NSData dataWithContentsOfFile:documentsFilePath]; + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; + [unarchiver setRequiresSecureCoding:NO]; + documentsObject = [unarchiver decodeObjectOfClass:classToRead forKey:NSKeyedArchiveRootObjectKey]; + } else { + documentsObject = [NSKeyedUnarchiver unarchiveObjectWithFile:documentsFilePath]; + } + if (documentsObject != nil) { // Successfully read object from Documents folder. if ([documentsObject isKindOfClass:[NSArray class]]) { @@ -325,29 +352,44 @@ + (id)readObject:(NSString *)fileName } else { [[ADJAdjustFactory logger] debug:@"Read %@: %@", objectName, documentsObject]; } + // Do the file migration. [[ADJAdjustFactory logger] verbose:@"Migrating %@ file from Documents to \"Application Support/Adjust\" folder", fileName]; [ADJUtil migrateFileFromPath:documentsFilePath toPath:appSupportFilePath]; + return documentsObject; - } else if (documentsObject == nil) { - // [[ADJAdjustFactory logger] verbose:@"%@ file not found", documentsFilePath]; - [[ADJAdjustFactory logger] verbose:@"%@ file not found in Documents folder", fileName]; } else { // [[ADJAdjustFactory logger] error:@"Failed to read %@ file", documentsFilePath]; - [[ADJAdjustFactory logger] error:@"Failed to read %@ file from Documents folder", fileName]; + [[ADJAdjustFactory logger] debug:@"File %@ not found in Documents folder", fileName]; } } @catch (NSException *ex) { // [[ADJAdjustFactory logger] error:@"Failed to read %@ file (%@)", documentsFilePath, ex]; [[ADJAdjustFactory logger] error:@"Failed to read %@ file from Documents folder (%@)", fileName, ex]; } + return nil; } + (void)writeObject:(id)object fileName:(NSString *)fileName objectName:(NSString *)objectName { + BOOL result; NSString *filePath = [ADJUtil getFilePathInAppSupportDir:fileName]; - BOOL result = (filePath != nil) && [NSKeyedArchiver archiveRootObject:object toFile:filePath]; + +#if !TARGET_OS_TV + if (@available(iOS 11.0, *)) { +#else + if (@available(tvOS 11.0, *)) { +#endif + NSError *errorArchiving = nil; + NSError *errorWriting = nil; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:object requiringSecureCoding:NO error:&errorArchiving]; + [data writeToFile:filePath options:NSDataWritingAtomic error:&errorWriting]; + result = (filePath != nil) && (errorArchiving == nil) && (errorWriting == nil); + } else { + result = (filePath != nil) && [NSKeyedArchiver archiveRootObject:object toFile:filePath]; + } + if (result == YES) { [ADJUtil excludeFromBackup:filePath]; if ([object isKindOfClass:[NSArray class]]) { @@ -473,10 +515,10 @@ + (void)sendGetRequest:(NSURL *)baseUrl NSMutableDictionary *parametersCopy = [[NSMutableDictionary alloc] initWithCapacity:[activityPackage.parameters count]]; [parametersCopy addEntriesFromDictionary:activityPackage.parameters]; - NSString *appSecret = [ADJUtil extractAppSecret:parametersCopy]; - NSString *secretId = [ADJUtil extractSecretId:parametersCopy]; [ADJUtil extractEventCallbackId:parametersCopy]; + NSString * authorizationHeader = [ADJUtil buildAuthorizationHeader:parametersCopy activityKind:activityPackage.activityKind]; + NSMutableURLRequest *request = [ADJUtil requestForGetPackage:activityPackage.path clientSdk:activityPackage.clientSdk parameters:parametersCopy @@ -485,22 +527,19 @@ + (void)sendGetRequest:(NSURL *)baseUrl [ADJUtil sendRequest:request prefixErrorMessage:prefixErrorMessage activityPackage:activityPackage - secretId:secretId - appSecret:appSecret + authorizationHeader:authorizationHeader responseDataHandler:responseDataHandler]; } + (void)sendRequest:(NSMutableURLRequest *)request prefixErrorMessage:(NSString *)prefixErrorMessage activityPackage:(ADJActivityPackage *)activityPackage - secretId:(NSString *)secretId - appSecret:(NSString *)appSecret +authorizationHeader:(NSString *)authorizationHeader responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler { [ADJUtil sendRequest:request prefixErrorMessage:prefixErrorMessage suffixErrorMessage:nil - secretId:secretId - appSecret:appSecret + authorizationHeader:authorizationHeader activityPackage:activityPackage responseDataHandler:responseDataHandler]; } @@ -510,14 +549,15 @@ + (void)sendPostRequest:(NSURL *)baseUrl prefixErrorMessage:(NSString *)prefixErrorMessage suffixErrorMessage:(NSString *)suffixErrorMessage activityPackage:(ADJActivityPackage *)activityPackage - responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler { + responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler +{ NSMutableDictionary *parametersCopy = [[NSMutableDictionary alloc] initWithCapacity:[activityPackage.parameters count]]; [parametersCopy addEntriesFromDictionary:activityPackage.parameters]; - NSString *appSecret = [ADJUtil extractAppSecret:parametersCopy]; - NSString *secretId = [ADJUtil extractSecretId:parametersCopy]; [ADJUtil extractEventCallbackId:parametersCopy]; + NSString * authorizationHeader = [ADJUtil buildAuthorizationHeader:parametersCopy activityKind:activityPackage.activityKind]; + NSMutableURLRequest *request = [ADJUtil requestForPostPackage:activityPackage.path clientSdk:activityPackage.clientSdk parameters:parametersCopy @@ -525,8 +565,7 @@ + (void)sendPostRequest:(NSURL *)baseUrl [ADJUtil sendRequest:request prefixErrorMessage:prefixErrorMessage suffixErrorMessage:suffixErrorMessage - secretId:secretId - appSecret:appSecret + authorizationHeader:authorizationHeader activityPackage:activityPackage responseDataHandler:responseDataHandler]; } @@ -534,15 +573,13 @@ + (void)sendPostRequest:(NSURL *)baseUrl + (void)sendRequest:(NSMutableURLRequest *)request prefixErrorMessage:(NSString *)prefixErrorMessage suffixErrorMessage:(NSString *)suffixErrorMessage - secretId:(NSString *)secretId - appSecret:(NSString *)appSecret +authorizationHeader:(NSString *)authorizationHeader activityPackage:(ADJActivityPackage *)activityPackage -responseDataHandler:(void (^)(ADJResponseData *responseData))responseDataHandler { - NSString *authHeader = [ADJUtil buildAuthorizationHeader:appSecret - secretId:secretId - activityPackage:activityPackage]; - if (authHeader != nil) { - [request setValue:authHeader forHTTPHeaderField:@"Authorization"]; +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"]; @@ -564,6 +601,53 @@ + (void)sendRequest:(NSMutableURLRequest *)request } } ++ (NSString *)buildAuthorizationHeader:(NSMutableDictionary *)parameters + activityKind:(ADJActivityKind)activityKind +{ + NSString * secretId = [ADJUtil extractSecretId:parameters]; + NSString * signature = [ADJUtil extractSignature:parameters]; + NSString * headersId = [ADJUtil extractHeadersId:parameters]; + NSString * authorizationHeader = [ADJUtil buildAuthorizationHeaderV2:signature + secretId:secretId + headersId:headersId]; + if (authorizationHeader != nil) { + return authorizationHeader; + } + + NSString * appSecret = [ADJUtil extractAppSecret:parameters]; + return [ADJUtil buildAuthorizationHeaderV1:appSecret + secretId:secretId + parameters:parameters + activityKind:activityKind]; +} + ++ (NSString *)extractSecretId:(NSMutableDictionary *)parameters { + NSString *appSecret = [parameters objectForKey:@"secret_id"]; + if (appSecret == nil) { + return nil; + } + [parameters removeObjectForKey:@"secret_id"]; + return appSecret; +} + ++ (NSString *)extractSignature:(NSMutableDictionary *)parameters { + NSString *appSecret = [parameters objectForKey:@"signature"]; + if (appSecret == nil) { + return nil; + } + [parameters removeObjectForKey:@"signature"]; + return appSecret; +} + ++ (NSString *)extractHeadersId:(NSMutableDictionary *)parameters { + NSString *appSecret = [parameters objectForKey:@"headers_id"]; + if (appSecret == nil) { + return nil; + } + [parameters removeObjectForKey:@"headers_id"]; + return appSecret; +} + + (NSString *)extractAppSecret:(NSMutableDictionary *)parameters { NSString *appSecret = [parameters objectForKey:@"app_secret"]; if (appSecret == nil) { @@ -573,13 +657,23 @@ + (NSString *)extractAppSecret:(NSMutableDictionary *)parameters { return appSecret; } -+ (NSString *)extractSecretId:(NSMutableDictionary *)parameters { - NSString *appSecret = [parameters objectForKey:@"secret_id"]; - if (appSecret == nil) { ++ (NSString *)buildAuthorizationHeaderV2:(NSString *)signature + secretId:(NSString*)secretId + headersId:(NSString*)headersId +{ + if (secretId == nil || signature == nil || headersId == nil) { return nil; } - [parameters removeObjectForKey:@"secret_id"]; - return appSecret; + + 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=\"adj1\""]; + + NSString * authorizationHeader = [NSString stringWithFormat:@"Signature %@,%@,%@,%@", + signatureHeader, secretIdHeader, algorithmHeader, idHeader]; + + return authorizationHeader; } + (void)extractEventCallbackId:(NSMutableDictionary *)parameters { @@ -629,15 +723,16 @@ + (NSMutableURLRequest *)requestForPostPackage:(NSString *)path return request; } -+ (NSString *)buildAuthorizationHeader:(NSString *)appSecret ++ (NSString *)buildAuthorizationHeaderV1:(NSString *)appSecret secretId:(NSString *)secretId - activityPackage:(ADJActivityPackage *)activityPackage { + parameters:(NSMutableDictionary *)parameters + activityKind:(ADJActivityKind)activityKind +{ if (appSecret == nil) { return nil; } - NSMutableDictionary *parameters = activityPackage.parameters; - NSString *activityKindS = [ADJActivityKindUtil activityKindToString:activityPackage.activityKind]; + NSString *activityKindS = [ADJActivityKindUtil activityKindToString:activityKind]; NSDictionary *signatureParameters = [ADJUtil buildSignatureParameters:parameters appSecret:appSecret activityKindS:activityKindS]; @@ -670,7 +765,6 @@ + (NSString *)buildAuthorizationHeader:(NSString *)appSecret signatureHeader, algorithmHeader, fieldsHeader]; - [ADJAdjustFactory.logger debug:@"authorizationHeader %@", authorizationHeader]; return authorizationHeader; } diff --git a/Adjust/Adjust.h b/Adjust/Adjust.h index 5f20d6ed0..bf1d1163d 100644 --- a/Adjust/Adjust.h +++ b/Adjust/Adjust.h @@ -2,7 +2,7 @@ // Adjust.h // Adjust // -// V4.20.0 +// V4.21.0 // Created by Christian Wellenbrock (wellle) on 23rd July 2013. // Copyright © 2012-2017 Adjust GmbH. All rights reserved. // @@ -25,6 +25,8 @@ @property (nonatomic, assign) BOOL deleteState; @property (nonatomic, assign) BOOL noBackoffWait; @property (nonatomic, assign) BOOL iAdFrameworkEnabled; +@property (nonatomic, assign) BOOL enableSigning; +@property (nonatomic, assign) BOOL disableSigning; @end diff --git a/Adjust/Adjust.m b/Adjust/Adjust.m index 68abb3823..0e0d01042 100644 --- a/Adjust/Adjust.m +++ b/Adjust/Adjust.m @@ -494,6 +494,14 @@ - (void)setTestOptions:(AdjustTestOptions *)testOptions { [ADJAdjustFactory setPackageHandlerBackoffStrategy:[ADJBackoffStrategy backoffStrategyWithType:ADJNoWait]]; } + if (testOptions.enableSigning) { + [ADJAdjustFactory enableSigning]; + } + + if (testOptions.disableSigning) { + [ADJAdjustFactory disableSigning]; + } + [ADJAdjustFactory setiAdFrameworkEnabled:testOptions.iAdFrameworkEnabled]; } diff --git a/AdjustBridge/AdjustBridgeRegister.m b/AdjustBridge/AdjustBridgeRegister.m index ccb50ff78..95f43cb68 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.20.0'; + return 'web-bridge4.21.0'; } }, setTestOptions: function(testOptions) { diff --git a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m index 9874970dd..3fb6de374 100644 --- a/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m +++ b/AdjustTests/AdjustTestApp/AdjustTestApp/ATAAdjustCommandExecutor.m @@ -135,6 +135,20 @@ - (void)testOptions:(NSDictionary *)parameters { testOptions.iAdFrameworkEnabled = YES; } } + if ([parameters objectForKey:@"enableSigning"]) { + NSString *enableSigningStr = [parameters objectForKey:@"enableSigning"][0]; + testOptions.enableSigning = NO; + if ([enableSigningStr isEqualToString:@"true"]) { + testOptions.enableSigning = YES; + } + } + if ([parameters objectForKey:@"disableSigning"]) { + NSString *disableSigningStr = [parameters objectForKey:@"disableSigning"][0]; + testOptions.disableSigning = NO; + if ([disableSigningStr isEqualToString:@"true"]) { + testOptions.disableSigning = YES; + } + } if ([parameters objectForKey:@"teardown"]) { NSArray *teardownOptions = [parameters objectForKey:@"teardown"]; for (int i = 0; i < teardownOptions.count; i = i + 1) { @@ -150,6 +164,7 @@ - (void)testOptions:(NSDictionary *)parameters { if ([teardownOption isEqualToString:@"resetTest"]) { self.savedConfigs = [NSMutableDictionary dictionary]; self.savedEvents = [NSMutableDictionary dictionary]; + self.adjustDelegate = nil; testOptions.timerIntervalInMilliseconds = [NSNumber numberWithInt:-1000]; testOptions.timerStartInMilliseconds = [NSNumber numberWithInt:-1000]; testOptions.sessionIntervalInMilliseconds = [NSNumber numberWithInt:-1000]; @@ -273,6 +288,16 @@ - (void)config:(NSDictionary *)parameters { NSString *sendInBackgroundS = [parameters objectForKey:@"sendInBackground"][0]; [adjustConfig setSendInBackground:[sendInBackgroundS boolValue]]; } + + if ([parameters objectForKey:@"allowIdfaReading"]) { + NSString *allowIdfaReadingS = [parameters objectForKey:@"allowIdfaReading"][0]; + [adjustConfig setAllowIdfaReading:[allowIdfaReadingS boolValue]]; + } + + if ([parameters objectForKey:@"allowiAdInfoReading"]) { + NSString *allowiAdInfoReadingS = [parameters objectForKey:@"allowiAdInfoReading"][0]; + [adjustConfig setAllowiAdInfoReading:[allowiAdInfoReadingS boolValue]]; + } if ([parameters objectForKey:@"userAgent"]) { NSString *userAgent = [parameters objectForKey:@"userAgent"][0]; diff --git a/AdjustTests/AdjustTestLibrary/AdjustTestLibrary.xcodeproj/project.pbxproj b/AdjustTests/AdjustTestLibrary/AdjustTestLibrary.xcodeproj/project.pbxproj index 1d763b7bd..96f92f278 100644 --- a/AdjustTests/AdjustTestLibrary/AdjustTestLibrary.xcodeproj/project.pbxproj +++ b/AdjustTests/AdjustTestLibrary/AdjustTestLibrary.xcodeproj/project.pbxproj @@ -251,7 +251,7 @@ 6F0842042007766700568A31 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1130; ORGANIZATIONNAME = adjust; TargetAttributes = { 20E71745203B162B0073AC91 = { diff --git a/AdjustTests/AdjustUnitTests/ADJPackageFields.m b/AdjustTests/AdjustUnitTests/ADJPackageFields.m index a9bbbd340..e134d5353 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.20.0"; + self.clientSdk = @"ios4.21.0"; self.suffix = @""; self.environment = @"sandbox"; diff --git a/AdjustTests/AdjustWebBridgeTestApp/AdjustWebBridgeTestApp.xcodeproj/xcshareddata/xcschemes/AdjustWebBridgeTestApp.xcscheme b/AdjustTests/AdjustWebBridgeTestApp/AdjustWebBridgeTestApp.xcodeproj/xcshareddata/xcschemes/AdjustWebBridgeTestApp.xcscheme index ff7bd0b93..5f563c310 100644 --- a/AdjustTests/AdjustWebBridgeTestApp/AdjustWebBridgeTestApp.xcodeproj/xcshareddata/xcschemes/AdjustWebBridgeTestApp.xcscheme +++ b/AdjustTests/AdjustWebBridgeTestApp/AdjustWebBridgeTestApp.xcodeproj/xcshareddata/xcschemes/AdjustWebBridgeTestApp.xcscheme @@ -1,6 +1,6 @@ - - - - + + - - - - - - + + + + @@ -39,17 +48,6 @@ - - - - - - - - 4.20.0' +pod 'Adjust', '~> 4.21.0' ``` or: ```ruby -pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.20.0' +pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.21.0' ``` --- diff --git a/VERSION b/VERSION index bafdf705c..7c6be3171 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.20.0 +4.21.0 diff --git a/doc/chinese/README.md b/doc/chinese/README.md index 7268697ae..2d2ae8d36 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.20.0' +pod 'Adjust', '~> 4.21.0' ``` 或: ```ruby -pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.20.0' +pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.21.0' ``` --- diff --git a/doc/english/migrate.md b/doc/english/migrate.md index 8a87b6d55..34307476d 100644 --- a/doc/english/migrate.md +++ b/doc/english/migrate.md @@ -1,4 +1,4 @@ -## Migrate your adjust SDK for iOS to v4.20.0 from v3.4.0 +## Migrate your adjust SDK for iOS to v4.21.0 from v3.4.0 ### Initial setup diff --git a/doc/english/web_views.md b/doc/english/web_views.md index 4e46d3edb..933b9aab1 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.20.0' +pod 'Adjust/WebBridge', '~> 4.21.0' ``` --- diff --git a/doc/japanese/README.md b/doc/japanese/README.md index c49229654..93711ca11 100644 --- a/doc/japanese/README.md +++ b/doc/japanese/README.md @@ -25,13 +25,13 @@ adjust SDKをiOSプロジェクトに連携する手順を説明します。 [こちらの手順](#sdk-integrate)に進んでください。 ```ruby -pod 'Adjust', '~> 4.20.0' +pod 'Adjust', '~> 4.21.0' ``` または ```ruby -pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.20.0' +pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.21.0' ``` --- diff --git a/doc/korean/README.md b/doc/korean/README.md index 6dd8991b9..e68cdc7a8 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.20.0' +pod 'Adjust', '~> 4.21.0' ``` 또는: ```ruby -pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.20.0' +pod 'Adjust', :git => 'https://github.com/adjust/ios_sdk.git', :tag => 'v4.21.0' ``` --- diff --git a/doc/korean/web_views.md b/doc/korean/web_views.md index d9a26600a..e6654672d 100644 --- a/doc/korean/web_views.md +++ b/doc/korean/web_views.md @@ -6,13 +6,13 @@ ## 목차 -* [앱 예시](#example-apps) +* [앱 예시](#example-app) * [기본 연동](#basic-integration) - * [웹 브리지가있는 SDK를 프로젝트에 추가] (# sdk-add) + * [웹 브리지가있는 SDK를 프로젝트에 추가](#sdk-add) * [iOS 프레임워크 추가](#sdk-frameworks) * [앱에 SDK 연동](#sdk-integrate) - * [AdjustBridge를 앱에 연동] (# bridge-integrate-app) - * [AdjustBridge를 웹뷰에 연동] (# bridge-integrate-web) + * [AdjustBridge를 앱에 연동](#bridge-integrate-app) + * [AdjustBridge를 웹뷰에 연동](#bridge-integrate-web) * [기본 설정](#basic-setup) * [Adjust 로](#adjust-logging) * [앱 빌드하기](#build-the-app) @@ -32,7 +32,7 @@ * [오프라인 모드](#offline-mode) * [이벤트 버퍼링](#event-buffering) * [GDPR 잊혀질 권리(Right to be Forgotten)](#gdpr-forget-me) - * [타사 공유 비활성화] (# disable-third-party-sharing) + * [타사 공유 비활성화](#disable-third-party-sharing) * [SDK 서명](#sdk-signature) * [백그라운드 추적](#background-tracking) * [기기 ID](#device-ids) @@ -63,8 +63,8 @@ iOS 개발용 Xcode를 사용한다는 가정하에 iOS 프로젝트에 Adjust S [CocoaPods][cocoapods]를 사용하는 경우, 다음 내용을 'Podfile'에 추가한 후 [해당 단계](#sdk-integrate)를 완료하세요. -ruby -pod 'Adjust/WebBridge', '~> 4.20.0' +```ruby +pod 'Adjust/WebBridge', '~> 4.21.0' ``` --- @@ -77,7 +77,7 @@ github "adjust/ios_sdk" --- -프로젝트에 Adjust SDK를 프레임워크로 추가하여 연동할 수도 있습니다. [releases page] [releases]에서`AdjustSdkWebBridge.framework.zip`을 찾을 수 있습니다 여기에는 동적 프레임이 포함되어 있습니다. \ +프로젝트에 Adjust SDK를 프레임워크로 추가하여 연동할 수도 있습니다. [releases page][releases]에서`AdjustSdkWebBridge.framework.zip`을 찾을 수 있습니다 여기에는 동적 프레임이 포함되어 있습니다. \ ### iOS 프레임워크 추가 @@ -226,11 +226,11 @@ setupWebViewJavascriptBridge(function(bridge) { 앱을 빌드하고 실행합니다. 빌드를 성공적으로 완료했다면, 콘솔에서 SDK 로그를 꼼꼼하게 살펴보시기 바랍니다. 앱이 시작된 후 앱을 처음으로 출시한 경우, 'Install tracked' 로그 정보를 반드시 확인하세요. -## 부가 기능 +## 부가 기능 Adjust SDK를 프로젝트에 연동하면 다음 기능을 활용할 수 있습니다. -### 이벤트 추적 +### 이벤트 추적 Adjust를 사용하여 이벤트를 트래킹할 수 있습니다. 특정 버튼에 대한 모든 탭을 트래킹하려는 경우를 가정해 보겠습니다. adjust 대시보드에서 이벤트 토큰을 생성합니다. 이는 'abc123'와 같은 형태입니다. 버튼의 'onclick' method에서 탭을 트래킹하기 위해 다음 줄을 추가합니다: @@ -556,7 +556,7 @@ adjustConfig.setSendInBackground(true); Adjust SDK를 사용하면 일부 기기 식별자를 얻을 수 있습니다. -### iOS 광고 식별자 +### iOS 광고 식별자 특정 서비스(예: Google Analytics)는 중복 보고를 방지하기 위해 기기 및 클라이언트 ID 통합을 요청합니다. diff --git a/doc/migrate.md b/doc/migrate.md index 5235a07d1..fc3809a80 100644 --- a/doc/migrate.md +++ b/doc/migrate.md @@ -1,4 +1,4 @@ -## Migrate your Adjust SDK for iOS to v4.20.0 from v3.4.0 +## Migrate your Adjust SDK for iOS to v4.21.0 from v3.4.0 ### Initial setup diff --git a/examples/AdjustExample-iMessage/AdjustExample-iMessage.xcodeproj/xcshareddata/xcschemes/AdjustExample-iMessage MessagesExtension.xcscheme b/examples/AdjustExample-iMessage/AdjustExample-iMessage.xcodeproj/xcshareddata/xcschemes/AdjustExample-iMessage MessagesExtension.xcscheme index fa9dd7b9e..cd4c7302b 100644 --- a/examples/AdjustExample-iMessage/AdjustExample-iMessage.xcodeproj/xcshareddata/xcschemes/AdjustExample-iMessage MessagesExtension.xcscheme +++ b/examples/AdjustExample-iMessage/AdjustExample-iMessage.xcodeproj/xcshareddata/xcschemes/AdjustExample-iMessage MessagesExtension.xcscheme @@ -1,6 +1,6 @@ - - - - + + - - - - - - + + - -