diff --git a/Branch-TestBed/Branch-SDK-Tests/BNCAPIServerTest.m b/Branch-TestBed/Branch-SDK-Tests/BNCAPIServerTest.m
index 28bb3b3b3..3d55a7128 100644
--- a/Branch-TestBed/Branch-SDK-Tests/BNCAPIServerTest.m
+++ b/Branch-TestBed/Branch-SDK-Tests/BNCAPIServerTest.m
@@ -450,7 +450,7 @@ - (void)testSetSafeTrackServiceURLWithUserTrackingDomain {
XCTAssertEqualObjects(storedUrl, expectedUrl);
storedUrl = [[BNCServerAPI sharedInstance] validationServiceURL];
- expectedUrl = @"https://links.toTestDomain.com/v1/app-link-settings";
+ expectedUrl = @"https://api3.branch.io/v1/app-link-settings";
XCTAssertEqualObjects(storedUrl, expectedUrl);
[BNCServerAPI sharedInstance].useTrackingDomain = NO;
@@ -501,7 +501,7 @@ - (void)testSetSafeTrackServiceURLWithOutUserTrackingDomain {
XCTAssertEqualObjects(storedUrl, expectedUrl);
storedUrl = [[BNCServerAPI sharedInstance] validationServiceURL];
- expectedUrl = @"https://links.toTestDomain.com/v1/app-link-settings";
+ expectedUrl = @"https://api3.branch.io/v1/app-link-settings";
XCTAssertEqualObjects(storedUrl, expectedUrl);
[BNCServerAPI sharedInstance].useTrackingDomain = NO;
diff --git a/Branch-TestBed/Branch-SDK-Tests/BNCODMTests.m b/Branch-TestBed/Branch-SDK-Tests/BNCODMTests.m
index 38d1b0cc2..d1dccffcc 100644
--- a/Branch-TestBed/Branch-SDK-Tests/BNCODMTests.m
+++ b/Branch-TestBed/Branch-SDK-Tests/BNCODMTests.m
@@ -65,7 +65,7 @@ - (void)testSetODMandSDKRequests {
}
- (void)testODMTimeOut {
-
+
NSString* requestUUID = [[NSUUID UUID ] UUIDString];
NSNumber* requestCreationTimeStamp = BNCWireFormatFromDate([NSDate date]);
NSString *odm = @"testODMString";
@@ -80,21 +80,23 @@ - (void)testODMTimeOut {
sleep(10);
- NSDictionary *jsonOpen = [factory dataForOpenWithURLString:@"https://branch.io"];
+ BNCRequestFactory *factory2 = [[BNCRequestFactory alloc] initWithBranchKey:@"key_abcd" UUID:requestUUID TimeStamp:requestCreationTimeStamp];
+ NSDictionary *jsonOpen = [factory2 dataForOpenWithURLString:@"https://branch.io"];
XCTAssertTrue(![odm isEqualToString:[jsonOpen objectForKey:@"odm_info"]]);
self.prefHelper.odmInfo = nil;
self.prefHelper.odmInfoInitDate = nil;
-
+
}
- (void) testODMAPIsNotLoaded {
+
XCTestExpectation *expectation = [self expectationWithDescription:@"Check if ODCManager class is loaded."];
- [[BNCODMInfoCollector instance ] loadODMInfoWithTimeOut:DISPATCH_TIME_FOREVER andCompletionHandler:^(NSString * _Nullable odmInfo, NSError * _Nullable error) {
- if (error.code == BNCClassNotFoundError){
- [expectation fulfill];
- }
+ [[BNCODMInfoCollector instance ] loadODMInfoWithCompletionHandler:^(NSString * _Nullable odmInfo, NSError * _Nullable error) {
+ if (error.code == BNCClassNotFoundError){
+ [expectation fulfill];
+ }
}];
[self waitForExpectationsWithTimeout:15 handler:nil];
}
diff --git a/Branch-TestBed/Branch-SDK-Tests/BNCPreferenceHelperTests.m b/Branch-TestBed/Branch-SDK-Tests/BNCPreferenceHelperTests.m
index 5269501b3..8c9a427b3 100644
--- a/Branch-TestBed/Branch-SDK-Tests/BNCPreferenceHelperTests.m
+++ b/Branch-TestBed/Branch-SDK-Tests/BNCPreferenceHelperTests.m
@@ -414,4 +414,27 @@ - (void)testSaveContentAnalyticsManifest {
XCTAssertEqualObjects(retrievedManifest, dummyManifest);
}
+- (void)testThirdPartyAPIsTimeoutDefaultValue {
+ XCTAssertEqual(self.prefHelper.thirdPartyAPIsWaitTime, 0.5,
+ @"Default third party APIs timeout should be 0.5 seconds");
+}
+
+- (void)testThirdPartyAPIsTimeoutSetterGetter {
+ NSTimeInterval testTimeout1 = 1.0;
+ self.prefHelper.thirdPartyAPIsWaitTime = testTimeout1;
+ XCTAssertEqual(self.prefHelper.thirdPartyAPIsWaitTime, testTimeout1,
+ @"Third party APIs timeout should be settable and retrievable");
+
+ NSTimeInterval testTimeout2 = 2.5;
+ self.prefHelper.thirdPartyAPIsWaitTime = testTimeout2;
+ XCTAssertEqual(self.prefHelper.thirdPartyAPIsWaitTime, testTimeout2,
+ @"Third party APIs timeout should be updatable");
+
+ NSTimeInterval testTimeout3 = 0.1;
+ self.prefHelper.thirdPartyAPIsWaitTime = testTimeout3;
+ XCTAssertEqual(self.prefHelper.thirdPartyAPIsWaitTime, testTimeout3,
+ @"Third party APIs timeout should support small values");
+}
+
+
@end
diff --git a/Branch-TestBed/Branch-SDK-Tests/BranchClassTests.m b/Branch-TestBed/Branch-SDK-Tests/BranchClassTests.m
index cf2bce94c..fd5ee92c3 100644
--- a/Branch-TestBed/Branch-SDK-Tests/BranchClassTests.m
+++ b/Branch-TestBed/Branch-SDK-Tests/BranchClassTests.m
@@ -20,6 +20,7 @@ - (void)writeObjectToDefaults:(NSString *)key value:(NSObject *)value;
@interface BranchClassTests : XCTestCase
@property (nonatomic, strong) Branch *branch;
+@property (nonatomic, strong, readwrite) BNCPreferenceHelper *prefHelper;
@end
@implementation BranchClassTests
@@ -27,6 +28,7 @@ @implementation BranchClassTests
- (void)setUp {
[super setUp];
self.branch = [Branch getInstance];
+ self.prefHelper = [BNCPreferenceHelper sharedInstance];
}
- (void)tearDown {
@@ -261,6 +263,102 @@ - (void)testSetConsumerProtectionAttributionLevel {
}
+- (void)testBranchSetSDKWaitTimeForThirdPartyAPIs {
+ // Test Branch instance method for setting timeout
+ NSTimeInterval testTimeout = 2.0;
+ [Branch setSDKWaitTimeForThirdPartyAPIs:testTimeout];
+
+ // Verify it was set in the preference helper
+ XCTAssertEqual(self.prefHelper.thirdPartyAPIsWaitTime, testTimeout,
+ @"Branch setSDKWaitTimeForThirdPartyAPIs should update preference helper");
+}
+
+- (void)testBranchSetSDKWaitTimeForThirdPartyAPIsMultipleValues {
+ // Test setting multiple different values
+ NSArray *testValues = @[@0.5, @1.0, @1.5, @3.0, @5.0];
+
+ for (NSNumber *timeoutValue in testValues) {
+ NSTimeInterval timeout = [timeoutValue doubleValue];
+ [Branch setSDKWaitTimeForThirdPartyAPIs:timeout];
+
+ XCTAssertEqual(self.prefHelper.thirdPartyAPIsWaitTime, timeout,
+ @"Branch setSDKWaitTimeForThirdPartyAPIs should handle value %.1f", timeout);
+ }
+}
+
+- (void)testTimeoutIntegrationWithPreferenceHelper {
+ // Test that Branch and PreferenceHelper work together correctly
+ NSTimeInterval branchTimeout = 1.8;
+ NSTimeInterval directTimeout = 2.3;
+
+ // Set via Branch
+ [Branch setSDKWaitTimeForThirdPartyAPIs:branchTimeout];
+ XCTAssertEqual(self.prefHelper.thirdPartyAPIsWaitTime, branchTimeout,
+ @"Wait Time set via Branch should be readable from PreferenceHelper");
+
+ // Set directly on PreferenceHelper
+ self.prefHelper.thirdPartyAPIsWaitTime = directTimeout;
+ XCTAssertEqual(self.prefHelper.thirdPartyAPIsWaitTime, directTimeout,
+ @"Wait time set directly should be readable via Branch");
+}
+
+- (void)testTimeoutValueConsistency {
+ // Test that the same instance maintains consistent values
+ NSTimeInterval testTimeout = 1.25;
+
+ [Branch setSDKWaitTimeForThirdPartyAPIs:testTimeout];
+
+ // Read multiple times to ensure consistency
+ for (int i = 0; i < 5; i++) {
+ XCTAssertEqual(self.prefHelper.thirdPartyAPIsWaitTime, testTimeout,
+ @"Timeout value should remain consistent across multiple reads");
+ }
+}
+
+- (void)testBranchSetSDKWaitTimeForThirdPartyAPIsInvalidLowValues {
+
+ NSArray *invalidLowValues = @[@0.0, @-1.0, @-0.5];
+ NSTimeInterval originalTimeout = [BNCPreferenceHelper sharedInstance].thirdPartyAPIsWaitTime;
+
+ for (NSNumber *timeoutValue in invalidLowValues) {
+ NSTimeInterval timeout = [timeoutValue doubleValue];
+ [Branch setSDKWaitTimeForThirdPartyAPIs:timeout];
+ XCTAssertEqual([BNCPreferenceHelper sharedInstance].thirdPartyAPIsWaitTime, originalTimeout,
+ @"Branch setSDKWaitTimeForThirdPartyAPIs should reject invalid low value %.3f", timeout);
+ }
+}
+
+- (void)testBranchsetSDKWaitTimeForThirdPartyAPIsInvalidHighValues {
+
+ NSArray *invalidHighValues = @[@10.1, @15.0, @30.0, @60.0];
+ NSTimeInterval originalTimeout = [BNCPreferenceHelper sharedInstance].thirdPartyAPIsWaitTime;
+
+ for (NSNumber *timeoutValue in invalidHighValues) {
+ NSTimeInterval timeout = [timeoutValue doubleValue];
+ [Branch setSDKWaitTimeForThirdPartyAPIs:timeout];
+ XCTAssertEqual([BNCPreferenceHelper sharedInstance].thirdPartyAPIsWaitTime, originalTimeout,
+ @"Branch setSDKWaitTimeForThirdPartyAPIs should reject invalid high value %.3f", timeout);
+ }
+}
+
+- (void)testBranchSetSDKWaitTimeForThirdPartyAPIsBoundaryValues {
+
+ // Test exactly 10.0 (should be valid)
+ [Branch setSDKWaitTimeForThirdPartyAPIs:10.0];
+ XCTAssertEqual([BNCPreferenceHelper sharedInstance].thirdPartyAPIsWaitTime, 10.0,
+ @"Timeout of exactly 10.0 seconds should be valid");
+
+ // Test just over 10.0 (should be invalid)
+ [Branch setSDKWaitTimeForThirdPartyAPIs:10.0001];
+ XCTAssertEqual([BNCPreferenceHelper sharedInstance].thirdPartyAPIsWaitTime, 10.0,
+ @"Timeout of 10.0001 seconds should be rejected");
+
+ // Test very small positive value (should be valid)
+ [Branch setSDKWaitTimeForThirdPartyAPIs:0.0001];
+ XCTAssertEqual([BNCPreferenceHelper sharedInstance].thirdPartyAPIsWaitTime, 0.0001,
+ @"Very small positive timeout should be valid");
+}
+
- (void)testSetAnonID {
NSString *expectedAnonID = @"static-test-anon-id-12345";
@@ -358,5 +456,4 @@ - (void)testSetAnonID_ThreadSafety {
@"One of the anonID values should be set");
}
-
@end
diff --git a/Branch-TestBed/Branch-TestBed-CI.xctestplan b/Branch-TestBed/Branch-TestBed-CI.xctestplan
index 260e13c5a..5db9a583a 100644
--- a/Branch-TestBed/Branch-TestBed-CI.xctestplan
+++ b/Branch-TestBed/Branch-TestBed-CI.xctestplan
@@ -13,6 +13,7 @@
},
"testTargets" : [
{
+ "enabled" : false,
"target" : {
"containerPath" : "container:Branch-TestBed.xcodeproj",
"identifier" : "E7AC745F2DB064BC002D8C40",
diff --git a/Branch-TestBed/Branch-TestBed.xcodeproj/Branch-TestBed.xctestplan b/Branch-TestBed/Branch-TestBed.xcodeproj/Branch-TestBed.xctestplan
index f4b6ec1ea..cb6dc38fe 100644
--- a/Branch-TestBed/Branch-TestBed.xcodeproj/Branch-TestBed.xctestplan
+++ b/Branch-TestBed/Branch-TestBed.xcodeproj/Branch-TestBed.xctestplan
@@ -37,6 +37,11 @@
}
},
{
+ "skippedTests" : [
+ "Reflection_ODM_Tests",
+ "Reflection_ODM_Tests\/testODMAPICall",
+ "Reflection_ODM_Tests\/testODMAPIsLoaded"
+ ],
"target" : {
"containerPath" : "container:Branch-TestBed.xcodeproj",
"identifier" : "E7AC745F2DB064BC002D8C40",
diff --git a/Branch-TestBed/Branch-TestBed.xcodeproj/project.pbxproj b/Branch-TestBed/Branch-TestBed.xcodeproj/project.pbxproj
index ee284e032..3668d1f55 100644
--- a/Branch-TestBed/Branch-TestBed.xcodeproj/project.pbxproj
+++ b/Branch-TestBed/Branch-TestBed.xcodeproj/project.pbxproj
@@ -234,13 +234,11 @@
E56394312CC7AC9F00E18E65 /* BranchFileLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = E563942F2CC7AC9500E18E65 /* BranchFileLogger.m */; };
E71E397B2DD3C14800110F59 /* BNCInAppBrowser.h in Headers */ = {isa = PBXBuildFile; fileRef = E71E397A2DD3C14800110F59 /* BNCInAppBrowser.h */; };
E72489D228E40D0200DCD8FD /* PasteControlViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E72489D128E40D0200DCD8FD /* PasteControlViewController.m */; };
+ E732827F2E5F7D92005CACC8 /* GoogleAdsOnDeviceConversion in Frameworks */ = {isa = PBXBuildFile; productRef = E732827E2E5F7D92005CACC8 /* GoogleAdsOnDeviceConversion */; };
E7A728BD2AA9A112009343B7 /* BNCAPIServerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E7A728BC2AA9A112009343B7 /* BNCAPIServerTest.m */; };
E7AC74572DB0639E002D8C40 /* BNCODMInfoCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = E7AC74562DB0639E002D8C40 /* BNCODMInfoCollector.h */; };
E7AC74592DB063C6002D8C40 /* BNCODMInfoCollector.m in Sources */ = {isa = PBXBuildFile; fileRef = E7AC74582DB063C6002D8C40 /* BNCODMInfoCollector.m */; };
E7AC745B2DB06407002D8C40 /* BNCODMTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7AC745A2DB06407002D8C40 /* BNCODMTests.m */; };
- E7AC74702DB06992002D8C40 /* GULLogger in Frameworks */ = {isa = PBXBuildFile; productRef = E7AC746F2DB06992002D8C40 /* GULLogger */; };
- E7AC74722DB06992002D8C40 /* GULNetwork in Frameworks */ = {isa = PBXBuildFile; productRef = E7AC74712DB06992002D8C40 /* GULNetwork */; };
- E7AC74752DB069B2002D8C40 /* nanopb in Frameworks */ = {isa = PBXBuildFile; productRef = E7AC74742DB069B2002D8C40 /* nanopb */; };
E7AC747B2DB0700D002D8C40 /* BranchSDK in Frameworks */ = {isa = PBXBuildFile; productRef = E7AC747A2DB0700D002D8C40 /* BranchSDK */; };
E7AC747E2DB0714B002D8C40 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E7AC747D2DB07145002D8C40 /* libc++.tbd */; };
E7AE4A092DFB2C4400696805 /* BranchConfigurationControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7AE4A082DFB2C4400696805 /* BranchConfigurationControllerTests.m */; };
@@ -279,6 +277,13 @@
remoteGlobalIDString = 466B58371B17773000A69EDE;
remoteInfo = Branch;
};
+ E73282812E5F81C9005CACC8 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 670016581940F51400A9E103 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 6700165F1940F51400A9E103;
+ remoteInfo = "Branch-TestBed";
+ };
E7AC74652DB064BC002D8C40 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 670016581940F51400A9E103 /* Project object */;
@@ -631,9 +636,7 @@
files = (
E7AC747E2DB0714B002D8C40 /* libc++.tbd in Frameworks */,
E7AC747B2DB0700D002D8C40 /* BranchSDK in Frameworks */,
- E7AC74752DB069B2002D8C40 /* nanopb in Frameworks */,
- E7AC74722DB06992002D8C40 /* GULNetwork in Frameworks */,
- E7AC74702DB06992002D8C40 /* GULLogger in Frameworks */,
+ E732827F2E5F7D92005CACC8 /* GoogleAdsOnDeviceConversion in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1182,16 +1185,15 @@
);
dependencies = (
E7AC74662DB064BC002D8C40 /* PBXTargetDependency */,
+ E73282822E5F81C9005CACC8 /* PBXTargetDependency */,
);
fileSystemSynchronizedGroups = (
E7AC74612DB064BC002D8C40 /* Reflection_ODM_Tests */,
);
name = Reflection_ODM_Tests;
packageProductDependencies = (
- E7AC746F2DB06992002D8C40 /* GULLogger */,
- E7AC74712DB06992002D8C40 /* GULNetwork */,
- E7AC74742DB069B2002D8C40 /* nanopb */,
E7AC747A2DB0700D002D8C40 /* BranchSDK */,
+ E732827E2E5F7D92005CACC8 /* GoogleAdsOnDeviceConversion */,
);
productName = Reflection_ODM_Tests;
productReference = E7AC74602DB064BC002D8C40 /* Reflection_ODM_Tests.xctest */;
@@ -1254,6 +1256,7 @@
};
E7AC745F2DB064BC002D8C40 = {
CreatedOnToolsVersion = 16.2;
+ TestTargetID = 6700165F1940F51400A9E103;
};
F1D4F9AB1F323F01002D13FF = {
CreatedOnToolsVersion = 8.3.1;
@@ -1273,9 +1276,8 @@
);
mainGroup = 670016571940F51400A9E103;
packageReferences = (
- E7AC746E2DB06992002D8C40 /* XCRemoteSwiftPackageReference "GoogleUtilities" */,
- E7AC74732DB069B2002D8C40 /* XCRemoteSwiftPackageReference "nanopb" */,
E7AC74792DB0700D002D8C40 /* XCLocalSwiftPackageReference "../../ios-branch-deep-linking-attribution" */,
+ E732827D2E5F7D92005CACC8 /* XCRemoteSwiftPackageReference "google-ads-on-device-conversion-ios-sdk" */,
);
productRefGroup = 670016611940F51400A9E103 /* Products */;
projectDirPath = "";
@@ -1555,6 +1557,11 @@
target = 466B58371B17773000A69EDE /* Branch */;
targetProxy = 5F8B7B4121B5F5CD009CE0A6 /* PBXContainerItemProxy */;
};
+ E73282822E5F81C9005CACC8 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 6700165F1940F51400A9E103 /* Branch-TestBed */;
+ targetProxy = E73282812E5F81C9005CACC8 /* PBXContainerItemProxy */;
+ };
E7AC74662DB064BC002D8C40 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 466B58371B17773000A69EDE /* Branch */;
@@ -1891,6 +1898,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
@@ -1899,7 +1907,7 @@
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = R63EM248DP;
- ENABLE_USER_SCRIPT_SANDBOXING = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
@@ -1912,6 +1920,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Branch-TestBed.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Branch-TestBed";
};
name = Debug;
};
@@ -1919,6 +1928,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
@@ -1928,7 +1938,7 @@
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = R63EM248DP;
- ENABLE_USER_SCRIPT_SANDBOXING = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
@@ -1941,6 +1951,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Branch-TestBed.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Branch-TestBed";
};
name = Release;
};
@@ -2067,39 +2078,21 @@
/* End XCLocalSwiftPackageReference section */
/* Begin XCRemoteSwiftPackageReference section */
- E7AC746E2DB06992002D8C40 /* XCRemoteSwiftPackageReference "GoogleUtilities" */ = {
+ E732827D2E5F7D92005CACC8 /* XCRemoteSwiftPackageReference "google-ads-on-device-conversion-ios-sdk" */ = {
isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/google/GoogleUtilities";
+ repositoryURL = "https://github.com/googleads/google-ads-on-device-conversion-ios-sdk";
requirement = {
kind = upToNextMajorVersion;
- minimumVersion = 8.0.2;
- };
- };
- E7AC74732DB069B2002D8C40 /* XCRemoteSwiftPackageReference "nanopb" */ = {
- isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/nanopb/nanopb";
- requirement = {
- kind = revision;
- revision = b7e1104502eca3a213b46303391ca4d3bc8ddec1;
+ minimumVersion = 2.3.0;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
- E7AC746F2DB06992002D8C40 /* GULLogger */ = {
- isa = XCSwiftPackageProductDependency;
- package = E7AC746E2DB06992002D8C40 /* XCRemoteSwiftPackageReference "GoogleUtilities" */;
- productName = GULLogger;
- };
- E7AC74712DB06992002D8C40 /* GULNetwork */ = {
- isa = XCSwiftPackageProductDependency;
- package = E7AC746E2DB06992002D8C40 /* XCRemoteSwiftPackageReference "GoogleUtilities" */;
- productName = GULNetwork;
- };
- E7AC74742DB069B2002D8C40 /* nanopb */ = {
+ E732827E2E5F7D92005CACC8 /* GoogleAdsOnDeviceConversion */ = {
isa = XCSwiftPackageProductDependency;
- package = E7AC74732DB069B2002D8C40 /* XCRemoteSwiftPackageReference "nanopb" */;
- productName = nanopb;
+ package = E732827D2E5F7D92005CACC8 /* XCRemoteSwiftPackageReference "google-ads-on-device-conversion-ios-sdk" */;
+ productName = GoogleAdsOnDeviceConversion;
};
E7AC747A2DB0700D002D8C40 /* BranchSDK */ = {
isa = XCSwiftPackageProductDependency;
diff --git a/Branch-TestBed/Reflection_ODM_Tests.xctestplan b/Branch-TestBed/Reflection_ODM_Tests.xctestplan
index 2130d2322..dd8cbb34e 100644
--- a/Branch-TestBed/Reflection_ODM_Tests.xctestplan
+++ b/Branch-TestBed/Reflection_ODM_Tests.xctestplan
@@ -14,6 +14,11 @@
"testTargets" : [
{
"parallelizable" : true,
+ "skippedTests" : [
+ "Reflection_ODM_Tests",
+ "Reflection_ODM_Tests\/testODMAPICall",
+ "Reflection_ODM_Tests\/testODMAPIsLoaded"
+ ],
"target" : {
"containerPath" : "container:Branch-TestBed.xcodeproj",
"identifier" : "E7AC745F2DB064BC002D8C40",
diff --git a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/Info.plist b/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/Info.plist
deleted file mode 100755
index 93a878439..000000000
--- a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/Info.plist
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
- AvailableLibraries
-
-
- LibraryIdentifier
- ios-arm64
- LibraryPath
- AppAdsOnDeviceConversion.framework
- SupportedArchitectures
-
- arm64
-
- SupportedPlatform
- ios
-
-
- LibraryIdentifier
- ios-arm64_x86_64-simulator
- LibraryPath
- AppAdsOnDeviceConversion.framework
- SupportedArchitectures
-
- arm64
- x86_64
-
- SupportedPlatform
- ios
- SupportedPlatformVariant
- simulator
-
-
- CFBundlePackageType
- XFWK
- XCFrameworkFormatVersion
- 1.0
-
-
diff --git a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/AppAdsOnDeviceConversion b/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/AppAdsOnDeviceConversion
deleted file mode 100755
index fa2869aa1..000000000
Binary files a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/AppAdsOnDeviceConversion and /dev/null differ
diff --git a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Headers/AppAdsOnDeviceConversion.h b/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Headers/AppAdsOnDeviceConversion.h
deleted file mode 100755
index a66e1722c..000000000
--- a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Headers/AppAdsOnDeviceConversion.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#import
-#import
diff --git a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Headers/ODCConversionManager.h b/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Headers/ODCConversionManager.h
deleted file mode 100755
index 3319bb50e..000000000
--- a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Headers/ODCConversionManager.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#import
-
-#import "ODCConversionTypes.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-/// The top level on-device conversion manager singleton that provides methods for fetching the
-/// aggregate conversion info for conversion reports.
-NS_SWIFT_NAME(ConversionManager)
-@interface ODCConversionManager : NSObject
-
-/// Returns the shared ConversionManager instance.
-@property(class, nonatomic, readonly) ODCConversionManager *sharedInstance;
-
-/// The SDK version in the format of three period-separated integers, such as "10.14.1".
-@property(nonatomic, readonly) NSString *versionString;
-
-/// Sets the timestamp when the application was first launched.
-/// @param firstLaunchTime The timestamp when the application was first launched.
-- (void)setFirstLaunchTime:(NSDate *)firstLaunchTime;
-
-/// Asynchronously fetches the aggregate conversion info of the current app instance for conversion
-/// reports.
-///
-/// The aggregate conversion info fetch could fail due to network failures etc.
-///
-/// @param interaction The type of interaction to fetch.
-/// @param completion The completion handler to call when the fetch is complete. This handler is
-/// executed on a system-defined global concurrent queue.
-/// This completion handler takes the following parameters:
-/// aggregateConversionInfo The aggregate conversion info of the current app instance, or
-/// `nil` if it's not available.
-/// error An error object that indicates why the request failed, or `nil` if the request
-/// was successful.
-/// When the aggregate conversion info is expired, both parameters are nil, i.e. the aggregate
-/// conversion info is not available and there is no error.
-- (void)fetchAggregateConversionInfoForInteraction:(ODCInteractionType)interaction
- completion:
- (void (^)(NSString *_Nullable aggregateConversionInfo,
- NSError *_Nullable error))completion;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Headers/ODCConversionTypes.h b/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Headers/ODCConversionTypes.h
deleted file mode 100755
index 9e1bb03d6..000000000
--- a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Headers/ODCConversionTypes.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#import
-
-/// The type of interaction for fetching conversion info.
-typedef NS_ENUM(NSInteger, ODCInteractionType) {
- ODCInteractionTypeInstallation,
-} NS_SWIFT_NAME(InteractionType);
diff --git a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Info.plist b/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Info.plist
deleted file mode 100755
index c1282dfff..000000000
--- a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Info.plist
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
- CFBundleExecutable
- AppAdsOnDeviceConversion
- CFBundleIdentifier
- com.google.ads.AppAdsOnDeviceConversion
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- AppAdsOnDeviceConversion
- CFBundlePackageType
- FMWK
- CFBundleVersion
- 0.8.21
- CFBundleShortVersionString
- 0.8.21
- DTSDKName
- iphonesimulator11.2
- MinimumOSVersion
- 100.0
-
-
diff --git a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Modules/module.modulemap b/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Modules/module.modulemap
deleted file mode 100755
index 17233f6b8..000000000
--- a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Modules/module.modulemap
+++ /dev/null
@@ -1,7 +0,0 @@
-framework module AppAdsOnDeviceConversion {
- umbrella header "AppAdsOnDeviceConversion.h"
- export *
- module * { export * }
- link framework "Foundation"
- link "c++"
-}
diff --git a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/AppAdsOnDeviceConversion b/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/AppAdsOnDeviceConversion
deleted file mode 100755
index 873b8adba..000000000
Binary files a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/AppAdsOnDeviceConversion and /dev/null differ
diff --git a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Headers/AppAdsOnDeviceConversion.h b/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Headers/AppAdsOnDeviceConversion.h
deleted file mode 100755
index a66e1722c..000000000
--- a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Headers/AppAdsOnDeviceConversion.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#import
-#import
diff --git a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Headers/ODCConversionManager.h b/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Headers/ODCConversionManager.h
deleted file mode 100755
index 3319bb50e..000000000
--- a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Headers/ODCConversionManager.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#import
-
-#import "ODCConversionTypes.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-/// The top level on-device conversion manager singleton that provides methods for fetching the
-/// aggregate conversion info for conversion reports.
-NS_SWIFT_NAME(ConversionManager)
-@interface ODCConversionManager : NSObject
-
-/// Returns the shared ConversionManager instance.
-@property(class, nonatomic, readonly) ODCConversionManager *sharedInstance;
-
-/// The SDK version in the format of three period-separated integers, such as "10.14.1".
-@property(nonatomic, readonly) NSString *versionString;
-
-/// Sets the timestamp when the application was first launched.
-/// @param firstLaunchTime The timestamp when the application was first launched.
-- (void)setFirstLaunchTime:(NSDate *)firstLaunchTime;
-
-/// Asynchronously fetches the aggregate conversion info of the current app instance for conversion
-/// reports.
-///
-/// The aggregate conversion info fetch could fail due to network failures etc.
-///
-/// @param interaction The type of interaction to fetch.
-/// @param completion The completion handler to call when the fetch is complete. This handler is
-/// executed on a system-defined global concurrent queue.
-/// This completion handler takes the following parameters:
-/// aggregateConversionInfo The aggregate conversion info of the current app instance, or
-/// `nil` if it's not available.
-/// error An error object that indicates why the request failed, or `nil` if the request
-/// was successful.
-/// When the aggregate conversion info is expired, both parameters are nil, i.e. the aggregate
-/// conversion info is not available and there is no error.
-- (void)fetchAggregateConversionInfoForInteraction:(ODCInteractionType)interaction
- completion:
- (void (^)(NSString *_Nullable aggregateConversionInfo,
- NSError *_Nullable error))completion;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Headers/ODCConversionTypes.h b/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Headers/ODCConversionTypes.h
deleted file mode 100755
index 9e1bb03d6..000000000
--- a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Headers/ODCConversionTypes.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#import
-
-/// The type of interaction for fetching conversion info.
-typedef NS_ENUM(NSInteger, ODCInteractionType) {
- ODCInteractionTypeInstallation,
-} NS_SWIFT_NAME(InteractionType);
diff --git a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Info.plist b/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Info.plist
deleted file mode 100755
index c1282dfff..000000000
--- a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Info.plist
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
- CFBundleExecutable
- AppAdsOnDeviceConversion
- CFBundleIdentifier
- com.google.ads.AppAdsOnDeviceConversion
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- AppAdsOnDeviceConversion
- CFBundlePackageType
- FMWK
- CFBundleVersion
- 0.8.21
- CFBundleShortVersionString
- 0.8.21
- DTSDKName
- iphonesimulator11.2
- MinimumOSVersion
- 100.0
-
-
diff --git a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Modules/module.modulemap b/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Modules/module.modulemap
deleted file mode 100755
index 17233f6b8..000000000
--- a/Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Modules/module.modulemap
+++ /dev/null
@@ -1,7 +0,0 @@
-framework module AppAdsOnDeviceConversion {
- umbrella header "AppAdsOnDeviceConversion.h"
- export *
- module * { export * }
- link framework "Foundation"
- link "c++"
-}
diff --git a/Branch-TestBed/Reflection_ODM_Tests/Reflection_ODM_Tests.m b/Branch-TestBed/Reflection_ODM_Tests/Reflection_ODM_Tests.m
index 1b8b73232..d65973e0f 100644
--- a/Branch-TestBed/Reflection_ODM_Tests/Reflection_ODM_Tests.m
+++ b/Branch-TestBed/Reflection_ODM_Tests/Reflection_ODM_Tests.m
@@ -22,9 +22,16 @@ - (void) testODMAPIsLoaded {
XCTestExpectation *expectation = [self expectationWithDescription:@"Network call"];
- [[BNCODMInfoCollector instance] fetchODMInfoFromDeviceWithInitDate:[NSDate date] andCompletion:^(NSString * _Nonnull odmInfo, NSError * _Nonnull error) {
- if ((error.code != BNCClassNotFoundError) && (error.code != BNCMethodNotFoundError)){
+ [[BNCODMInfoCollector instance] fetchODMInfoFromDeviceWithInitDate:[NSDate date] andCompletion:^(NSString * _Nullable odmInfo, NSError * _Nullable error) {
+ if ( !error) {
[expectation fulfill];
+ } else {
+ if ((error.code != BNCClassNotFoundError) && (error.code != BNCMethodNotFoundError)) {
+ [expectation fulfill];
+ } else {
+ XCTFail(@"Unexpected ODM error: %@", error.localizedDescription);
+ [expectation fulfill];
+ }
}
}];
@@ -32,21 +39,25 @@ - (void) testODMAPIsLoaded {
}
+
- (void) testODMAPICall {
-
+
XCTestExpectation *expectation = [self expectationWithDescription:@"Network call"];
[BNCPreferenceHelper sharedInstance].odmInfo = nil;
- [[BNCODMInfoCollector instance ] loadODMInfoWithTimeOut:15 andCompletionHandler:^(NSString * _Nullable odmInfo, NSError * _Nullable error) {
- if ((error.code != BNCClassNotFoundError) && (error.code != BNCMethodNotFoundError)){
+ [[BNCODMInfoCollector instance ] loadODMInfoWithCompletionHandler:^(NSString * _Nullable odmInfo, NSError * _Nullable error) {
+ if (!error){
if (odmInfo) {
XCTAssertTrue([odmInfo isEqualToString:[BNCPreferenceHelper sharedInstance].odmInfo]);
XCTAssertTrue([BNCPreferenceHelper sharedInstance].odmInfoInitDate != nil);
}
XCTAssertTrue((error == nil), "%s", [[error description] UTF8String]);
[expectation fulfill];
+ } else {
+ XCTFail(@"Unexpected ODM error: %@", error.localizedDescription);
+ [expectation fulfill];
}
}];
- [self waitForExpectationsWithTimeout:30 handler:nil];
+ [self waitForExpectationsWithTimeout:15 handler:nil];
}
@end
diff --git a/Sources/BranchSDK/BNCODMInfoCollector.m b/Sources/BranchSDK/BNCODMInfoCollector.m
index 09bb519d6..d17f2ad19 100644
--- a/Sources/BranchSDK/BNCODMInfoCollector.m
+++ b/Sources/BranchSDK/BNCODMInfoCollector.m
@@ -22,8 +22,6 @@ @interface BNCODMInfoCollector()
@implementation BNCODMInfoCollector
-@synthesize odmInfo = _odmInfo;
-
+ (BNCODMInfoCollector *)instance {
static BNCODMInfoCollector *collector = nil;
static dispatch_once_t onceToken = 0;
@@ -41,51 +39,28 @@ - (instancetype)init {
return self;
}
-- (void) setOdmInfo:(NSString *)odmInfo {
- _odmInfo = odmInfo;
-}
-
-- (NSString *) odmInfo {
- @synchronized (self) {
- // Load ODM info with a time-out of 500 ms. Its must for next call to v1/open.
- if (!_odmInfo) {
- [self loadODMInfoWithTimeOut:dispatch_time(DISPATCH_TIME_NOW, (int64_t)(500 * NSEC_PER_MSEC)) andCompletionHandler:nil]; // Timeout after 500 ms
- }
-
- if (_odmInfo) {
- // Check if odmInfo is within validity window
- NSDate *initTime = self.preferenceHelper.odmInfoInitDate;
- NSTimeInterval validityWindow = self.preferenceHelper.odmInfoValidityWindow;
- if ([self isWithinValidityWindow:initTime timeInterval:validityWindow]) {
- // fetch ODM info from pref helper
- _odmInfo = self.preferenceHelper.odmInfo;
- } else {
- _odmInfo = nil;
- }
- }
- return _odmInfo;
- }
-}
-
-- (void)loadODMInfo {
- [self loadODMInfoWithTimeOut: DISPATCH_TIME_FOREVER andCompletionHandler:nil];
-}
-
-- (void)loadODMInfoWithTimeOut:(dispatch_time_t) timeOut andCompletionHandler:(void (^_Nullable)(NSString * _Nullable odmInfo, NSError * _Nullable error))completion {
+- (void)loadODMInfoWithCompletionHandler:(void (^_Nullable)(NSString * _Nullable odmInfo, NSError * _Nullable error))completion {
- if (self.preferenceHelper.odmInfo) {
- self.odmInfo = self.preferenceHelper.odmInfo;
+ NSString *odmInfoValidated = self.preferenceHelper.odmInfo;
+ if (odmInfoValidated) {
+ // Check if odmInfo is within validity window
+ NSDate *initTime = self.preferenceHelper.odmInfoInitDate;
+ NSTimeInterval validityWindow = self.preferenceHelper.odmInfoValidityWindow;
+ if ([self isWithinValidityWindow:initTime timeInterval:validityWindow]) {
+ // fetch ODM info from pref helper
+ odmInfoValidated = self.preferenceHelper.odmInfo;
+ } else {
+ odmInfoValidated = nil;
+ }
if (completion) {
- completion(_odmInfo, nil);
+ completion(odmInfoValidated, nil);
}
} else {
// Fetch ODM Info from device
NSDate * odmInfofetchingTime = [NSDate date];
- dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self fetchODMInfoFromDeviceWithInitDate:odmInfofetchingTime andCompletion:^(NSString *odmInfo, NSError *error) {
if (odmInfo) {
- self.odmInfo = odmInfo;
// Cache ODM info in pref helper
self.preferenceHelper.odmInfo = odmInfo;
self.preferenceHelper.odmInfoInitDate = odmInfofetchingTime;
@@ -93,9 +68,8 @@ - (void)loadODMInfoWithTimeOut:(dispatch_time_t) timeOut andCompletionHandler:(v
if (completion) {
completion(odmInfo, error);
}
- dispatch_semaphore_signal(semaphore);
+
}];
- dispatch_semaphore_wait(semaphore, timeOut);
}
}
@@ -109,90 +83,89 @@ - (BOOL)isWithinValidityWindow:(NSDate *)initTime timeInterval:(NSTimeInterval)t
}
- (void) fetchODMInfoFromDeviceWithInitDate:(NSDate *) date andCompletion:(void (^)(NSString *odmInfo, NSError *error))completion {
-
- NSError *error = nil ;
-
- Class ODMConversionManagerClass = NSClassFromString(@"ODCConversionManager");
- SEL sharedInstanceSelector = NSSelectorFromString(@"sharedInstance");
-
- if (ODMConversionManagerClass && [ODMConversionManagerClass respondsToSelector:sharedInstanceSelector]) {
+ @synchronized (self) {
- id sharedInstance = ((id (*)(id, SEL))[ODMConversionManagerClass methodForSelector:sharedInstanceSelector])
- (ODMConversionManagerClass, sharedInstanceSelector);
-
- // Set the time when the app was first launched by calling setFirstLaunchTime: dynamically
- SEL setFirstLaunchTimeSelector = NSSelectorFromString(@"setFirstLaunchTime:");
+ NSError *error = nil ;
+
+ Class ODMConversionManagerClass = NSClassFromString(@"ODCConversionManager");
+ SEL sharedInstanceSelector = NSSelectorFromString(@"sharedInstance");
- if ([sharedInstance respondsToSelector:setFirstLaunchTimeSelector]) {
+ if (ODMConversionManagerClass && [ODMConversionManagerClass respondsToSelector:sharedInstanceSelector]) {
- void (*setFirstLaunchTimeMethod)(id, SEL, NSDate *) = (void (*)(id, SEL, NSDate *))
- [sharedInstance methodForSelector:setFirstLaunchTimeSelector];
- setFirstLaunchTimeMethod(sharedInstance, setFirstLaunchTimeSelector, date);
- [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"setFirstLaunchTimeSelector: invoked successfully."] error:nil];
+ id sharedInstance = ((id (*)(id, SEL))[ODMConversionManagerClass methodForSelector:sharedInstanceSelector])
+ (ODMConversionManagerClass, sharedInstanceSelector);
- // Fetch the conversion info. Call fetchAggregateConversionInfoForInteraction:completion dynamically
- SEL fetchAggregateConversionInfoSelector = NSSelectorFromString(@"fetchAggregateConversionInfoForInteraction:completion:");
- if ([sharedInstance respondsToSelector:fetchAggregateConversionInfoSelector]) {
- NSMethodSignature *signature = [sharedInstance methodSignatureForSelector:fetchAggregateConversionInfoSelector];
- NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
- [invocation setTarget:sharedInstance];
- [invocation setSelector:fetchAggregateConversionInfoSelector];
-
- // Since ODCInteractionType is an enum defined in AppAdsOnDeviceConversion.framework and its not accessible via reflection. And since enums in Objective-C are just symbolic constants that get replaced by their underlying integer values at compile time, so defining similar enum here -
- typedef NS_ENUM(NSInteger, ODCInteractionType) {
- ODCInteractionTypeInstallation,
- } ;
+ // Set the time when the app was first launched by calling setFirstLaunchTime: dynamically
+ SEL setFirstLaunchTimeSelector = NSSelectorFromString(@"setFirstLaunchTime:");
+
+ if ([sharedInstance respondsToSelector:setFirstLaunchTimeSelector]) {
- ODCInteractionType arg1 = ODCInteractionTypeInstallation;
- [invocation setArgument:&arg1 atIndex:2];
+ void (*setFirstLaunchTimeMethod)(id, SEL, NSDate *) = (void (*)(id, SEL, NSDate *))
+ [sharedInstance methodForSelector:setFirstLaunchTimeSelector];
+ setFirstLaunchTimeMethod(sharedInstance, setFirstLaunchTimeSelector, date);
+ [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"setFirstLaunchTimeSelector: invoked successfully."] error:nil];
- __weak typeof(self) weakSelf = self;
- self.odmFetchCompletion = ^(NSString *info, NSError *error) {
+ // Fetch the conversion info. Call fetchAggregateConversionInfoForInteraction:completion dynamically
+ SEL fetchAggregateConversionInfoSelector = NSSelectorFromString(@"fetchAggregateConversionInfoForInteraction:completion:");
+ if ([sharedInstance respondsToSelector:fetchAggregateConversionInfoSelector]) {
+ NSMethodSignature *signature = [sharedInstance methodSignatureForSelector:fetchAggregateConversionInfoSelector];
+ NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
+ [invocation setTarget:sharedInstance];
+ [invocation setSelector:fetchAggregateConversionInfoSelector];
+ // Since ODCInteractionType is an enum defined in AppAdsOnDeviceConversion.framework and its not accessible via reflection. And since enums in Objective-C are just symbolic constants that get replaced by their underlying integer values at compile time, so defining similar enum here -
+ typedef NS_ENUM(NSInteger, ODCInteractionType) {
+ ODCInteractionTypeInstallation,
+ } ;
- if (error) {
- [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"ODMConversionManager:fetchInfo Error : %@", error.localizedDescription ] error:error];
- }
+ ODCInteractionType arg1 = ODCInteractionTypeInstallation;
+ [invocation setArgument:&arg1 atIndex:2];
- __strong typeof(self) self = weakSelf;
- if (info) {
- self->_odmInfo = info; // Save new value even if its new.
- }
+ __weak typeof(self) weakSelf = self;
+ self.odmFetchCompletion = ^(NSString *info, NSError *error) {
+
+
+ if (error) {
+ [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"ODMConversionManager:fetchInfo Error : %@", error.localizedDescription ] error:error];
+ }
+
+ __strong typeof(self) self = weakSelf;
+
+ if (completion) {
+ completion( info, error);
+ }
+ [[BranchLogger shared] logVerbose:[NSString stringWithFormat:@"Received Info: %@", info] error:nil];
+ };
+ [invocation setArgument:&_odmFetchCompletion atIndex:3];
+ [invocation invoke];
+ [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"fetchInfo:completion: invoked successfully."] error:nil];
+
+
+ } else {
+ NSString *message = [NSString stringWithFormat:@"Method fetchInfo:completion: not found."] ;
+ error = [NSError branchErrorWithCode:BNCMethodNotFoundError localizedMessage:message];
+ [[BranchLogger shared] logDebug:message error:error ];
if (completion) {
- completion( self->_odmInfo, error);
+ completion( nil, error);
}
- [[BranchLogger shared] logVerbose:[NSString stringWithFormat:@"Received Info: %@", info] error:nil];
- };
-
- [invocation setArgument:&_odmFetchCompletion atIndex:3];
- [invocation invoke];
- [[BranchLogger shared] logDebug:[NSString stringWithFormat:@"fetchInfo:completion: invoked successfully."] error:nil];
-
-
+ }
} else {
- NSString *message = [NSString stringWithFormat:@"Method fetchInfo:completion: not found."] ;
+ NSString *message = [NSString stringWithFormat:@"Method setFirstLaunchTimeSelector: not found."] ;
error = [NSError branchErrorWithCode:BNCMethodNotFoundError localizedMessage:message];
- [[BranchLogger shared] logDebug:message error:error ];
+ [[BranchLogger shared] logDebug:message error:error];
if (completion) {
completion( nil, error);
}
}
} else {
- NSString *message = [NSString stringWithFormat:@"Method setFirstLaunchTimeSelector: not found."] ;
- error = [NSError branchErrorWithCode:BNCMethodNotFoundError localizedMessage:message];
+ NSString *message = [NSString stringWithFormat:@"ODCConversionManager class or sharedInstance method not found. Ignore this error if not using ODM."] ;
+ error = [NSError branchErrorWithCode:BNCClassNotFoundError localizedMessage:message];
[[BranchLogger shared] logDebug:message error:error];
if (completion) {
completion( nil, error);
}
}
- } else {
- NSString *message = [NSString stringWithFormat:@"ODCConversionManager class or sharedInstance method not found."] ;
- error = [NSError branchErrorWithCode:BNCClassNotFoundError localizedMessage:message];
- [[BranchLogger shared] logDebug:message error:error];
- if (completion) {
- completion( nil, error);
- }
}
}
diff --git a/Sources/BranchSDK/BNCPreferenceHelper.m b/Sources/BranchSDK/BNCPreferenceHelper.m
index ca7001583..05c4d84e9 100644
--- a/Sources/BranchSDK/BNCPreferenceHelper.m
+++ b/Sources/BranchSDK/BNCPreferenceHelper.m
@@ -16,6 +16,7 @@
#import "BNCSKAdNetwork.h"
static const NSTimeInterval DEFAULT_TIMEOUT = 5.5;
+static const NSTimeInterval DEFAULT_THIRD_PARTY_APIS_TIMEOUT = 0.5; // 500ms default
static const NSTimeInterval DEFAULT_RETRY_INTERVAL = 0;
static const NSInteger DEFAULT_RETRY_COUNT = 3;
static const NSTimeInterval DEFAULT_REFERRER_GBRAID_WINDOW = 2592000; // 30 days = 2,592,000 seconds
@@ -57,6 +58,7 @@
static NSString * const BRANCH_PREFS_KEY_FIRST_APP_LAUNCH_TIME = @"bnc_first_app_launch_time";
static NSString * const BRANCH_PREFS_KEY_SKAN_HIGHEST_CONV_VALUE_SENT = @"bnc_skan_send_highest_conv_value";
static NSString * const BRANCH_PREFS_KEY_SKAN_INVOKE_REGISTER_APP = @"bnc_invoke_register_app";
+static NSString * const BRANCH_PREFS_KEY_THIRD_PARTY_APIS_TIMEOUT = @"bnc_third_party_apis_timeout";
static NSString * const BRANCH_PREFS_KEY_USE_EU_SERVERS = @"bnc_use_EU_servers";
@@ -114,6 +116,7 @@ @implementation BNCPreferenceHelper
retryCount = _retryCount,
retryInterval = _retryInterval,
timeout = _timeout,
+ thirdPartyAPIsWaitTime = _thirdPartyAPIsWaitTime,
lastStrongMatchDate = _lastStrongMatchDate,
requestMetadataDictionary = _requestMetadataDictionary,
instrumentationDictionary = _instrumentationDictionary,
@@ -156,6 +159,7 @@ - (instancetype)init {
_retryCount = DEFAULT_RETRY_COUNT;
_retryInterval = DEFAULT_RETRY_INTERVAL;
_odmInfoValidityWindow = DEFAULT_ODM_INFO_VALIDITY_WINDOW;
+ _thirdPartyAPIsWaitTime = DEFAULT_THIRD_PARTY_APIS_TIMEOUT;
_isDebug = NO;
_persistPrefsQueue = [[NSOperationQueue alloc] init];
_persistPrefsQueue.maxConcurrentOperationCount = 1;
@@ -759,6 +763,23 @@ - (void) setOdmInfoInitDate:(NSDate *)initDate {
}
}
+- (NSTimeInterval) thirdPartyAPIsWaitTime {
+ @synchronized (self) {
+ _thirdPartyAPIsWaitTime = [self readDoubleFromDefaults:BRANCH_PREFS_KEY_THIRD_PARTY_APIS_TIMEOUT];
+ if (_thirdPartyAPIsWaitTime == NSNotFound) {
+ _thirdPartyAPIsWaitTime = DEFAULT_THIRD_PARTY_APIS_TIMEOUT;
+ }
+ return _thirdPartyAPIsWaitTime;
+ }
+}
+
+- (void) setThirdPartyAPIsWaitTime:(NSTimeInterval)waitTime {
+ @synchronized (self) {
+ _thirdPartyAPIsWaitTime = waitTime;
+ [self writeObjectToDefaults:BRANCH_PREFS_KEY_THIRD_PARTY_APIS_TIMEOUT value:@(waitTime)];
+ }
+}
+
- (NSInteger) skanCurrentWindow {
@synchronized (self) {
_skanCurrentWindow = [self readIntegerFromDefaults:BRANCH_PREFS_KEY_SKAN_CURRENT_WINDOW];
diff --git a/Sources/BranchSDK/BNCRequestFactory.m b/Sources/BranchSDK/BNCRequestFactory.m
index d6aae49e4..a89b6ed51 100644
--- a/Sources/BranchSDK/BNCRequestFactory.m
+++ b/Sources/BranchSDK/BNCRequestFactory.m
@@ -49,6 +49,8 @@ @interface BNCRequestFactory()
@property (nonatomic, strong, readwrite) BNCPasteboard *pasteboard;
@property (nonatomic, strong, readwrite) NSNumber *requestCreationTimeStamp;
@property (nonatomic, strong, readwrite) NSString *requestUUID;
+@property (nonatomic, strong, readwrite) NSString *odmInfo;
+@property (nonatomic, strong, readwrite) NSString *appleAttributionToken;
@end
@@ -72,6 +74,40 @@ - (instancetype)initWithBranchKey:(NSString *)key UUID:(NSString *)requestUUID T
return self;
}
+- (void) loadDataFromThirdPartyAPIs {
+#if !TARGET_OS_TV
+ dispatch_group_t apiGroup = dispatch_group_create();
+ dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+
+ if ([[self.preferenceHelper attributionLevel] isEqualToString:BranchAttributionLevelFull])
+ {
+ dispatch_group_enter(apiGroup);
+ dispatch_async(concurrentQueue, ^{
+ [[BNCODMInfoCollector instance] loadODMInfoWithCompletionHandler:^(NSString * _Nullable odmInfo, NSError * _Nullable error) {
+ self.odmInfo = odmInfo;
+ dispatch_group_leave(apiGroup);
+ }];
+ });
+ }
+
+ if (!self.preferenceHelper.appleAttributionTokenChecked) {
+ dispatch_group_enter(apiGroup);
+ dispatch_async(concurrentQueue, ^{
+ self.appleAttributionToken = [BNCSystemObserver appleAttributionToken];
+ if (self.appleAttributionToken) {
+ self.preferenceHelper.appleAttributionTokenChecked = YES;
+ }
+ dispatch_group_leave(apiGroup);
+ });
+ }
+
+ NSTimeInterval timeoutSeconds = [BNCPreferenceHelper sharedInstance].thirdPartyAPIsWaitTime;
+ dispatch_time_t timeOut = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeoutSeconds * NSEC_PER_SEC));
+ dispatch_group_wait(apiGroup, timeOut);
+#endif
+
+}
+
// SDK level tracking control
// When set to YES, only link creation and resolution calls are allowed.
// NO by default.
@@ -82,6 +118,8 @@ - (BOOL)isTrackingDisabled {
- (NSDictionary *)dataForInstallWithURLString:(NSString *)urlString {
NSMutableDictionary *json = [NSMutableDictionary new];
+ [self loadDataFromThirdPartyAPIs];
+
// All requests
[self addDefaultRequestDataToJSON:json];
@@ -141,6 +179,8 @@ - (NSDictionary *)dataForInstallWithURLString:(NSString *)urlString {
- (NSDictionary *)dataForOpenWithURLString:(NSString *)urlString {
NSMutableDictionary *json = [NSMutableDictionary new];
+ [self loadDataFromThirdPartyAPIs];
+
// All requests
[self addDefaultRequestDataToJSON:json];
@@ -335,10 +375,9 @@ - (void)addSystemObserverDataToJSON:(NSMutableDictionary *)json {
- (void)addAppleAttributionTokenToJSON:(NSMutableDictionary *)json {
// This value is only sent once usually on install
if (!self.preferenceHelper.appleAttributionTokenChecked) {
- NSString *appleAttributionToken = [BNCSystemObserver appleAttributionToken];
- if (appleAttributionToken) {
+ if (self.appleAttributionToken) {
self.preferenceHelper.appleAttributionTokenChecked = YES;
- [self safeSetValue:appleAttributionToken forKey:BRANCH_REQUEST_KEY_APPLE_ATTRIBUTION_TOKEN onDict:json];
+ [self safeSetValue:self.appleAttributionToken forKey:BRANCH_REQUEST_KEY_APPLE_ATTRIBUTION_TOKEN onDict:json];
}
}
}
@@ -347,9 +386,8 @@ - (void)addAppleAttributionTokenToJSON:(NSMutableDictionary *)json {
- (void)addODMInfoToJSON:(NSMutableDictionary *)json {
#if !TARGET_OS_TV
if ([[self.preferenceHelper attributionLevel] isEqualToString:BranchAttributionLevelFull]) {
- NSString *odmInfo = [BNCODMInfoCollector instance].odmInfo ;
- if (odmInfo) {
- [self safeSetValue:odmInfo forKey:BRANCH_REQUEST_KEY_ODM_INFO onDict:json];
+ if (self.odmInfo) {
+ [self safeSetValue:self.odmInfo forKey:BRANCH_REQUEST_KEY_ODM_INFO onDict:json];
NSNumber* odmInitDateInNumberFormat = BNCWireFormatFromDate(self.preferenceHelper.odmInfoInitDate);
[self safeSetValue:odmInitDateInNumberFormat forKey:BRANCH_REQUEST_KEY_ODM_FIRST_OPEN_TIMESTAMP onDict:json];
}
diff --git a/Sources/BranchSDK/BNCSystemObserver.m b/Sources/BranchSDK/BNCSystemObserver.m
index 2bc4b9b83..238ffcb77 100644
--- a/Sources/BranchSDK/BNCSystemObserver.m
+++ b/Sources/BranchSDK/BNCSystemObserver.m
@@ -8,6 +8,8 @@
#import "BNCSystemObserver.h"
#import "BranchLogger.h"
+#import "BNCPreferenceHelper.h"
+
#if __has_feature(modules)
@import UIKit;
@import SystemConfiguration;
@@ -35,32 +37,20 @@ + (NSString *)appleAttributionToken {
return nil;
}
- __block NSString *token = nil;
-
#if !TARGET_OS_TV
if (@available(iOS 14.3, macCatalyst 14.3, *)) {
-
- // We are getting reports on iOS 14.5 that this API can hang, adding a short timeout for now.
- dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
-
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- NSError *error;
- NSString *appleAttributionToken = [AAAttribution attributionTokenWithError:&error];
- if (!error) {
- token = appleAttributionToken;
- }
- dispatch_semaphore_signal(semaphore);
- });
-
- // Apple said this API should respond within 50ms, lets give up after 500 ms
- dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(500 * NSEC_PER_MSEC)));
- if (token == nil) {
- [[BranchLogger shared] logError:[NSString stringWithFormat:@"AppleAttributionToken request timed out"] error:nil];
+ NSError *error;
+ NSString *appleAttributionToken = [AAAttribution attributionTokenWithError:&error];
+ if (error) {
+ [[BranchLogger shared] logError:[NSString stringWithFormat:@"AppleAttributionToken API failed, error: %@", [error description]] error:error];
+ }
+ if (appleAttributionToken == nil) {
+ [[BranchLogger shared] logError:[NSString stringWithFormat:@"AppleAttributionToken returned nil token"] error:nil];
}
+ return appleAttributionToken;
}
#endif
-
- return token;
+ return nil;
}
+ (NSString *)advertiserIdentifier {
diff --git a/Sources/BranchSDK/Branch.m b/Sources/BranchSDK/Branch.m
index 32ee69691..434c9c22d 100644
--- a/Sources/BranchSDK/Branch.m
+++ b/Sources/BranchSDK/Branch.m
@@ -244,7 +244,6 @@ - (id)initWithInterface:(BNCServerInterface *)interface
// queue up async data loading
[self loadApplicationData];
[self loadUserAgent];
- [self startLoadingOfODMInfo];
BranchJsonConfig *config = BranchJsonConfig.instance;
self.deferInitForPluginRuntime = config.deferInitForPluginRuntime;
@@ -539,6 +538,19 @@ - (void)setRetryInterval:(NSTimeInterval)retryInterval {
self.preferenceHelper.retryInterval = retryInterval;
}
++ (void)setSDKWaitTimeForThirdPartyAPIs:(NSTimeInterval)waitTime {
+ @synchronized(self) {
+ if (waitTime <= 0) {
+ [[BranchLogger shared] logWarning:@"Invalid waitTime value. It must be greater than 0. Using default value." error:nil];
+ return;
+ }
+ if (waitTime > 10) {
+ [[BranchLogger shared] logWarning:@"Invalid waitTime value. It must not exceed 10 seconds. Using default value." error:nil];
+ return;
+ }
+ [BNCPreferenceHelper sharedInstance].thirdPartyAPIsWaitTime = waitTime;
+ }
+}
- (void)setRequestMetadataKey:(NSString *)key value:(NSString *)value {
[self.preferenceHelper setRequestMetadataKey:key value:value];
@@ -597,7 +609,6 @@ + (void)setODMInfo:(NSString *)odmInfo andFirstOpenTimestamp:(NSDate *) firstOpe
@synchronized (self) {
[[BNCPreferenceHelper sharedInstance] setOdmInfo:odmInfo];
[BNCPreferenceHelper sharedInstance].odmInfoInitDate = firstOpenTimestamp;
- [[BNCODMInfoCollector instance] loadODMInfo];
}
#else
[[BranchLogger shared] logWarning:@"setODMInfo not supported on tvOS." error:nil];
@@ -1004,15 +1015,6 @@ - (void)loadApplicationData {
});
}
-- (void)startLoadingOfODMInfo {
- #if !TARGET_OS_TV
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- [[BranchLogger shared] logVerbose:@"Loading ODM info ..." error:nil];
- [[BNCODMInfoCollector instance] loadODMInfo];
- });
- #endif
-}
-
#pragma mark - Apple Search Ad Check
diff --git a/Sources/BranchSDK/Private/BNCODMInfoCollector.h b/Sources/BranchSDK/Private/BNCODMInfoCollector.h
index a2e064bd8..18b2ae8d1 100644
--- a/Sources/BranchSDK/Private/BNCODMInfoCollector.h
+++ b/Sources/BranchSDK/Private/BNCODMInfoCollector.h
@@ -19,8 +19,6 @@ NS_ASSUME_NONNULL_BEGIN
@interface BNCODMInfoCollector : NSObject
+ (BNCODMInfoCollector *_Nullable) instance;
-
-@property (nonatomic, copy, readwrite) NSString * _Nullable odmInfo;
/**
* Checks if the given date is within the specified validity window from the current time.
* @param initTime The reference date to check against.
@@ -29,17 +27,11 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (BOOL)isWithinValidityWindow:(NSDate *)initTime timeInterval:(NSTimeInterval)timeInterval;
-/**
- * Loads ODM information either from cache or from the device.
- */
-- (void)loadODMInfo;
-
/**
* Loads ODM information with a specified timeout.
- * @param timeOut The maximum time to wait for ODM information.
* @param completion Optional completion handler called when ODM info is loaded.
*/
-- (void)loadODMInfoWithTimeOut:(dispatch_time_t) timeOut andCompletionHandler:(void (^_Nullable)(NSString * _Nullable odmInfo, NSError * _Nullable error))completion; // Added completion handler for unit tests
+- (void)loadODMInfoWithCompletionHandler:(void (^_Nullable)(NSString * _Nullable odmInfo, NSError * _Nullable error))completion;
- (void)fetchODMInfoFromDeviceWithInitDate:(NSDate *) date andCompletion:(void (^)(NSString *odmInfo, NSError *error))completion;
diff --git a/Sources/BranchSDK/Public/BNCPreferenceHelper.h b/Sources/BranchSDK/Public/BNCPreferenceHelper.h
index f664b7f72..d3253bd5a 100644
--- a/Sources/BranchSDK/Public/BNCPreferenceHelper.h
+++ b/Sources/BranchSDK/Public/BNCPreferenceHelper.h
@@ -46,6 +46,7 @@ NSURL* /* _Nonnull */ BNCURLForBranchDirectory(void);
@property (assign, nonatomic) NSInteger retryCount;
@property (assign, nonatomic) NSTimeInterval retryInterval;
@property (assign, nonatomic) NSTimeInterval timeout;
+@property (assign, nonatomic) NSTimeInterval thirdPartyAPIsWaitTime;
@property (copy, nonatomic) NSString *externalIntentURI;
@property (strong, nonatomic) NSMutableDictionary *savedAnalyticsData;
@property (copy, nonatomic) NSString *lastSystemBuildVersion;
diff --git a/Sources/BranchSDK/Public/Branch.h b/Sources/BranchSDK/Public/Branch.h
index c75d92216..0983a5168 100644
--- a/Sources/BranchSDK/Public/Branch.h
+++ b/Sources/BranchSDK/Public/Branch.h
@@ -752,6 +752,14 @@ Sets a custom base safetrack URL for non-linking calls to the Branch API.
*/
- (void)setNetworkTimeout:(NSTimeInterval)timeout;
+/**
+ Set the SDK wait time for third party APIs (for fetching ODM info and Apple Attribution Token) to finish
+ This timeout should be > 0 and <= 10 seconds.
+
+ @param waitTime Number of seconds before third party API calls are considered timed out. Default is 0.5 seconds (500ms).
+ */
++ (void)setSDKWaitTimeForThirdPartyAPIs:(NSTimeInterval)waitTime;
+
/**
Disable callouts to ad networks for all events for a user; by default Branch sends callouts to ad networks.