diff --git a/Modules/module.modulemap b/Modules/module.modulemap index 190f72db..11ed991f 100644 --- a/Modules/module.modulemap +++ b/Modules/module.modulemap @@ -10,6 +10,9 @@ framework module UnityAds { header "UnityAdsInitializationDelegate.h" header "UnityAdsInitializationError.h" header "UnityAdsLoadDelegate.h" + header "UADSBaseOptions.h" + header "UADSLoadOptions.h" + header "UADSShowOptions.h" header "USRVUnityPurchasing.h" header "USRVUnityPurchasingDelegate.h" diff --git a/UnityAds.podspec b/UnityAds.podspec index 72343aa4..6b3806ad 100644 --- a/UnityAds.podspec +++ b/UnityAds.podspec @@ -1,12 +1,12 @@ Pod::Spec.new do |s| s.name = 'UnityAds' - s.version = '3.5.1' + s.version = '3.6.0' s.license = { :type => 'Unity License', :file => 'LICENSE' } s.author = { 'UnityAds' => 'itunes@unity3d.com' } s.homepage = 'https://unity3d.com/services/ads' s.summary = 'Monetize your entire player base and reach new audiences with video ads.' s.platform = :ios - s.source = { :http => 'https://github.com/Unity-Technologies/unity-ads-ios/releases/download/3.5.1/UnityAds.framework.zip' } + s.source = { :http => 'https://github.com/Unity-Technologies/unity-ads-ios/releases/download/3.6.0/UnityAds.framework.zip' } s.ios.deployment_target = '9.0' s.ios.vendored_frameworks = 'UnityAds.framework' s.ios.xcconfig = { 'OTHER_LDFLAGS' => '-framework UnityAds' } diff --git a/UnityAdsTests/Ads/Load/UADSLoadModuleTests.m b/UnityAdsTests/Ads/Load/UADSLoadModuleTests.m index f998805d..cb6ff04f 100644 --- a/UnityAdsTests/Ads/Load/UADSLoadModuleTests.m +++ b/UnityAdsTests/Ads/Load/UADSLoadModuleTests.m @@ -3,6 +3,7 @@ #import "USRVSdkProperties.h" #import "USRVInitializationNotificationCenter.h" #import "USRVWebViewApp.h" +#import "UADSLoadOptions.h" @interface UnityAdsLoadDelegateMock : NSObject @property (strong) NSMutableArray* adLoaded; @@ -41,14 +42,18 @@ @interface MockLoadWebViewApp : USRVWebViewApp { } @property (nonatomic, strong) XCTestExpectation *loadCallExpectation; @property (strong) UADSLoadModule* loadModule; +@property NSArray *params; - (void)simulateLoadCall; - (void)simulateFailedLoadCall; - (void)simulateLoadCallTimeout; + @end @implementation MockLoadWebViewApp +@synthesize params; + - (instancetype)initWithLoadModule:(UADSLoadModule*)loadModule { if (self = [super init]) { self.loadModule = loadModule; @@ -60,7 +65,7 @@ - (BOOL)invokeMethod:(NSString *)methodName className:(NSString *)className rece self->receiverClass = receiverClass; self->callback = callback; - self->params = params; + self.params = params; [_loadCallExpectation fulfill]; return YES; @@ -83,7 +88,7 @@ - (void)simulateLoadCall { [invocation retainArguments]; [invocation invoke]; - NSDictionary* dict = self->params[0]; + NSDictionary* dict = self.params[0]; [_loadModule sendAdLoaded:[dict objectForKey:@"placementId"] listenerId:[dict objectForKey:@"listenerId"]]; } @@ -123,6 +128,7 @@ - (void)simulateLoadCallTimeout { [invocation retainArguments]; [invocation invoke]; } + @end @interface UADSLoadModule (Test) @@ -157,7 +163,7 @@ -(void)testLoadAfterInitialized { UnityAdsLoadDelegateMock* delegate = [[UnityAdsLoadDelegateMock alloc] init]; - [self.loadModule load:@"test" loadDelegate:delegate]; + [self.loadModule load:@"test" options:[UADSLoadOptions new] loadDelegate:delegate]; [self waitForExpectationsWithTimeout:1 handler:nil]; @@ -185,7 +191,7 @@ -(void)testLoadAfterInitialized_WithWebViewTimeout { UnityAdsLoadDelegateMock* delegate = [[UnityAdsLoadDelegateMock alloc] init]; - [self.loadModule load:@"test" loadDelegate:delegate]; + [self.loadModule load:@"test" options:[UADSLoadOptions new] loadDelegate:delegate]; [self waitForExpectationsWithTimeout:1 handler:nil]; @@ -211,7 +217,7 @@ -(void)testLoadAfterInitialized_WithFailedInvocation { UnityAdsLoadDelegateMock* delegate = [[UnityAdsLoadDelegateMock alloc] init]; - [self.loadModule load:@"test" loadDelegate:delegate]; + [self.loadModule load:@"test" options:[UADSLoadOptions new] loadDelegate:delegate]; [self waitForExpectationsWithTimeout:1 handler:nil]; @@ -239,7 +245,7 @@ -(void)testLoadAfterInitialized_ListenerCleanup { UnityAdsLoadDelegateMock* delegate = [[UnityAdsLoadDelegateMock alloc] init]; - [self.loadModule load:@"test" loadDelegate:delegate]; + [self.loadModule load:@"test" options:[UADSLoadOptions new] loadDelegate:delegate]; [self waitForExpectationsWithTimeout:1 handler:nil]; @@ -268,7 +274,7 @@ -(void)testLoadAfterInitialized_WithHardcodedTimeout { UnityAdsLoadDelegateMock* delegate = [[UnityAdsLoadDelegateMock alloc] init]; - [self.loadModule load:@"test" loadDelegate:delegate]; + [self.loadModule load:@"test" options:[UADSLoadOptions new] loadDelegate:delegate]; [self waitForExpectationsWithTimeout:1 handler:nil]; @@ -285,6 +291,41 @@ -(void)testLoadAfterInitialized_WithHardcodedTimeout { XCTAssertEqualObjects(@[@"test"], delegate.adFailedToLoad); } +-(void)testLoadAfterInitialized_WithCorrectLoadOptions { + MockLoadWebViewApp* mock = [[MockLoadWebViewApp alloc] initWithLoadModule:_loadModule]; + [USRVWebViewApp setCurrentApp:mock]; + + [USRVSdkProperties setInitialized:YES]; + + XCTestExpectation* expectation = [self expectationWithDescription:@"load call"]; + mock.loadCallExpectation = expectation; + + UnityAdsLoadDelegateMock* delegate = [[UnityAdsLoadDelegateMock alloc] init]; + UADSLoadOptions* loadOptions = [UADSLoadOptions new]; + [loadOptions setAdMarkup:@"MyAdMarkup"]; + [loadOptions setObjectId:@"MyObjectID"]; + + [self.loadModule load:@"test" options:loadOptions loadDelegate:delegate]; + + [self waitForExpectationsWithTimeout:1 handler:nil]; + + expectation = [self expectationWithDescription:@"event call"]; + delegate.expectation = expectation; + + [mock simulateLoadCall]; + + [self waitForExpectationsWithTimeout:1 handler:nil]; + + NSDictionary *options = [[[mock params] objectAtIndex:0] objectForKey:@"options"]; + + XCTAssertEqual(1, delegate.adLoaded.count); + XCTAssertEqualObjects(@[@"test"], delegate.adLoaded); + XCTAssertEqual(0, delegate.adFailedToLoad.count); + + XCTAssertEqual(@"MyAdMarkup", [options objectForKey:@"adMarkup"]); + XCTAssertEqual(@"MyObjectID", [options objectForKey:@"objectId"]); +} + -(void)testLoadBeforeInitialized { MockLoadWebViewApp* mock = [[MockLoadWebViewApp alloc] initWithLoadModule:_loadModule]; [USRVWebViewApp setCurrentApp:mock]; @@ -296,7 +337,7 @@ -(void)testLoadBeforeInitialized { UnityAdsLoadDelegateMock* delegate = [[UnityAdsLoadDelegateMock alloc] init]; - [self.loadModule load:@"test" loadDelegate:delegate]; + [self.loadModule load:@"test" options:[UADSLoadOptions new] loadDelegate:delegate]; [USRVSdkProperties setInitialized:YES]; [_loadModule sdkDidInitialize]; @@ -324,7 +365,7 @@ -(void)testLoadBeforeInitialized_InitFailed { UnityAdsLoadDelegateMock* delegate = [[UnityAdsLoadDelegateMock alloc] init]; - [self.loadModule load:@"test" loadDelegate:delegate]; + [self.loadModule load:@"test" options:[UADSLoadOptions new] loadDelegate:delegate]; XCTestExpectation* expectation = [self expectationWithDescription:@"event call"]; delegate.expectation = expectation; diff --git a/UnityAdsTests/Ads/Options/LoadOptionsTest.m b/UnityAdsTests/Ads/Options/LoadOptionsTest.m new file mode 100644 index 00000000..647e9856 --- /dev/null +++ b/UnityAdsTests/Ads/Options/LoadOptionsTest.m @@ -0,0 +1,51 @@ +#import +#import "UADSLoadOptions.h" + +@interface LoadOptionsTest : XCTestCase + +@property UADSLoadOptions* loadOptions; + +@end + +@implementation LoadOptionsTest + +- (void)setUp { + self.loadOptions = [UADSLoadOptions new]; +} + +- (void)tearDown { + self.loadOptions = nil; +} + +- (void)testAdMarkup { + [self.loadOptions setAdMarkup:@"MyAdMarkup"]; + + XCTAssertEqual(@"MyAdMarkup", [self.loadOptions adMarkup]); + XCTAssertEqual(@"MyAdMarkup", [self.loadOptions.dictionary objectForKey:@"adMarkup"]); + + XCTAssertEqual(1, [self.loadOptions.dictionary count]); +} + +- (void)testObjectId { + [self.loadOptions setObjectId:@"MyObjectId"]; + + XCTAssertEqual(@"MyObjectId", [self.loadOptions objectId]); + XCTAssertEqual(@"MyObjectId", [self.loadOptions.dictionary objectForKey:@"objectId"]); + + XCTAssertEqual(1, [self.loadOptions.dictionary count]); +} + +- (void)testObjectIdAndAdMarkup { + [self.loadOptions setObjectId:@"MyObjectId"]; + [self.loadOptions setAdMarkup:@"MyAdMarkup"]; + + XCTAssertEqual(@"MyObjectId", [self.loadOptions objectId]); + XCTAssertEqual(@"MyObjectId", [self.loadOptions.dictionary objectForKey:@"objectId"]); + + XCTAssertEqual(@"MyAdMarkup", [self.loadOptions adMarkup]); + XCTAssertEqual(@"MyAdMarkup", [self.loadOptions.dictionary objectForKey:@"adMarkup"]); + + XCTAssertEqual(2, [self.loadOptions.dictionary count]); +} + +@end diff --git a/UnityAdsTests/Ads/Options/ShowOptionsTest.m b/UnityAdsTests/Ads/Options/ShowOptionsTest.m new file mode 100644 index 00000000..77e8c6cc --- /dev/null +++ b/UnityAdsTests/Ads/Options/ShowOptionsTest.m @@ -0,0 +1,27 @@ +#import +#import "UADSShowOptions.h" + +@interface ShowOptionsTest : XCTestCase + +@property UADSShowOptions* showOptions; + +@end + +@implementation ShowOptionsTest + +- (void)setUp { + self.showOptions = [UADSShowOptions new]; +} + +- (void)tearDown { + self.showOptions = nil; +} + +- (void)testObjectId { + [self.showOptions setObjectId:@"MyObjectId"]; + XCTAssertEqual(@"MyObjectId", [self.showOptions objectId]); + XCTAssertEqual(@"MyObjectId", [self.showOptions.dictionary objectForKey:@"objectId"]); + XCTAssertEqual(1, [self.showOptions.dictionary count]); +} + +@end diff --git a/UnityAdsTests/TokenStorageTests.m b/UnityAdsTests/TokenStorageTests.m new file mode 100644 index 00000000..6d5a10a6 --- /dev/null +++ b/UnityAdsTests/TokenStorageTests.m @@ -0,0 +1,132 @@ +#import +#import "UnityAdsTests-Bridging-Header.h" + +@interface TokenStorageEventHandlerMock : NSObject + +@property int queueEmptyCount; +@property int accessTokenCount; +@property NSMutableArray* indecies; + +- (void) sendQueueEmpty; +- (void) sendTokenAccessIndex:(NSNumber*)index; + +@end + +@implementation TokenStorageEventHandlerMock + +- (void) sendQueueEmpty { + self.queueEmptyCount++; +} + +- (void) sendTokenAccessIndex:(NSNumber*)index { + self.accessTokenCount++; + + if (self.indecies == nil) { + self.indecies = [NSMutableArray new]; + } + + [self.indecies addObject:index]; +} + +@end + +@interface TokenStorageTests : XCTestCase + +@property UADSTokenStorage* tokenStorage; +@property TokenStorageEventHandlerMock* eventHandlerMock; + +@end + +@implementation TokenStorageTests + +- (void)setUp { + [super setUp]; + + self.eventHandlerMock = [TokenStorageEventHandlerMock new]; + self.tokenStorage = [[UADSTokenStorage alloc] initWithEventHandler:self.eventHandlerMock]; +} + +- (void)tearDown { + [super tearDown]; +} + +- (void)testCreateToken { + [self.tokenStorage createTokens:@[@"token1", @"token2", @"token3"]]; + + XCTAssertEqual([self.tokenStorage getToken], @"token1"); + XCTAssertEqual([self.tokenStorage getToken], @"token2"); + XCTAssertEqual([self.tokenStorage getToken], @"token3"); + XCTAssertEqual([self.tokenStorage getToken], nil); +} + +- (void)testDeleteToken { + [self.tokenStorage createTokens:@[@"token1", @"token2", @"token3"]]; + [self.tokenStorage deleteTokens]; + + XCTAssertEqual([self.tokenStorage getToken], nil); +} + +- (void)testAppendToken { + [self.tokenStorage createTokens:@[@"token1"]]; + [self.tokenStorage appendTokens:@[@"token2", @"token3"]]; + + XCTAssertEqual([self.tokenStorage getToken], @"token1"); + XCTAssertEqual([self.tokenStorage getToken], @"token2"); + XCTAssertEqual([self.tokenStorage getToken], @"token3"); + XCTAssertEqual([self.tokenStorage getToken], nil); +} + +- (void)testAppendTokenOnEmptyStorage { + [self.tokenStorage deleteTokens]; + [self.tokenStorage appendTokens:@[@"token1", @"token2"]]; + + XCTAssertEqual([self.tokenStorage getToken], @"token1"); + XCTAssertEqual([self.tokenStorage getToken], @"token2"); + XCTAssertEqual([self.tokenStorage getToken], nil); +} + +- (void)testAppendTokenWithoutQueueShouldNotCrashApp { + [self.tokenStorage appendTokens:@[@"token2", @"token3"]]; +} + + +- (void)testGetTokenWhenNoQueue { + XCTAssertEqual([self.tokenStorage getToken], nil); + XCTAssertEqual(self.eventHandlerMock.queueEmptyCount, 0); + XCTAssertEqual(self.eventHandlerMock.accessTokenCount, 0); +} + +- (void)testGetTokenAccessToken { + [self.tokenStorage createTokens:@[@"token1"]]; + + XCTAssertEqual([self.tokenStorage getToken], @"token1"); + XCTAssertEqual(self.eventHandlerMock.queueEmptyCount, 0); + XCTAssertEqual(self.eventHandlerMock.accessTokenCount, 1); + + NSArray *myArray = @[@0]; + XCTAssertEqualObjects(self.eventHandlerMock.indecies, myArray); +} + +- (void)testGetTokenEmptyQueue { + [self.tokenStorage createTokens:@[]]; + + XCTAssertEqual([self.tokenStorage getToken], nil); + XCTAssertEqual(self.eventHandlerMock.queueEmptyCount, 1); + XCTAssertEqual(self.eventHandlerMock.accessTokenCount, 0); +} + +- (void)testGetTokenAccessTokenInPeekMode { + [self.tokenStorage setPeekMode:YES]; + + [self.tokenStorage createTokens:@[@"token1", @"token2"]]; + + XCTAssertEqual([self.tokenStorage getToken], @"token1"); + XCTAssertEqual([self.tokenStorage getToken], @"token1"); + XCTAssertEqual(self.eventHandlerMock.queueEmptyCount, 0); + XCTAssertEqual(self.eventHandlerMock.accessTokenCount, 2); + + NSArray *myArray = @[@0, @1]; + XCTAssertEqualObjects(self.eventHandlerMock.indecies, myArray); +} + +@end diff --git a/UnityAdsTests/UnityAdsTests-Bridging-Header.h b/UnityAdsTests/UnityAdsTests-Bridging-Header.h index 3c2f0d39..3511c04a 100644 --- a/UnityAdsTests/UnityAdsTests-Bridging-Header.h +++ b/UnityAdsTests/UnityAdsTests-Bridging-Header.h @@ -32,6 +32,7 @@ #import "UADSVideoPlayerHandler.h" #import "USRVWebRequestWithUrlConnection.h" #import "USRVWebRequestFactory.h" +#import "UADSTokenStorage.h" // METADATA #import "UADSMetaData.h" diff --git a/UnityServices/Ads/Api/UADSApiToken.h b/UnityServices/Ads/Api/UADSApiToken.h new file mode 100644 index 00000000..5640c1ea --- /dev/null +++ b/UnityServices/Ads/Api/UADSApiToken.h @@ -0,0 +1,2 @@ +@interface UADSApiToken : NSObject +@end diff --git a/UnityServices/Ads/Api/UADSApiToken.m b/UnityServices/Ads/Api/UADSApiToken.m new file mode 100644 index 00000000..bff03565 --- /dev/null +++ b/UnityServices/Ads/Api/UADSApiToken.m @@ -0,0 +1,27 @@ +#import "UADSApiToken.h" +#import "USRVWebViewCallback.h" +#import "UADSTokenStorage.h" + +@implementation UADSApiToken + ++(void)WebViewExposed_createTokens:(NSArray *)tokens callback:(USRVWebViewCallback *)callback { + [[UADSTokenStorage sharedInstance] createTokens:tokens]; + [callback invoke:nil]; +} + ++(void)WebViewExposed_appendTokens:(NSArray*)tokens callback:(USRVWebViewCallback *)callback { + [[UADSTokenStorage sharedInstance] appendTokens:tokens]; + [callback invoke:nil]; +} + ++(void)WebViewExposed_deleteTokens:(USRVWebViewCallback *)callback { + [[UADSTokenStorage sharedInstance] deleteTokens]; + [callback invoke:nil]; +} + ++(void)WebViewExposed_setPeekMode:(NSNumber *)value callback:(USRVWebViewCallback *)callback { + [[UADSTokenStorage sharedInstance] setPeekMode:[value boolValue]]; + [callback invoke:nil]; +} + +@end diff --git a/UnityServices/Ads/Configuration/UADSAdsModuleConfiguration.m b/UnityServices/Ads/Configuration/UADSAdsModuleConfiguration.m index 9e9c8db9..2050962b 100644 --- a/UnityServices/Ads/Configuration/UADSAdsModuleConfiguration.m +++ b/UnityServices/Ads/Configuration/UADSAdsModuleConfiguration.m @@ -2,6 +2,7 @@ #import "UADSPlacement.h" #import "UADSLoadModule.h" #import "UADSWebViewShowOperation.H" +#import "UADSTokenStorage.h" @implementation UADSAdsModuleConfiguration @@ -14,7 +15,8 @@ @implementation UADSAdsModuleConfiguration @"UADSApiPlacement", @"UADSApiPurchasing", @"UADSAdsProperties", - @"UADSApiLoad" + @"UADSApiLoad", + @"UADSApiToken" ]; } @@ -22,6 +24,7 @@ - (BOOL)resetState:(USRVConfiguration *)configuration { [UADSPlacement reset]; [UADSWebViewShowOperation setConfiguration:configuration]; [UADSLoadModule setConfiguration:configuration]; + [[UADSTokenStorage sharedInstance] deleteTokens]; return true; } diff --git a/UnityServices/Ads/Load/UADSLoadModule.h b/UnityServices/Ads/Load/UADSLoadModule.h index dae01d8d..a007edf7 100644 --- a/UnityServices/Ads/Load/UADSLoadModule.h +++ b/UnityServices/Ads/Load/UADSLoadModule.h @@ -1,11 +1,12 @@ #import "USRVInitializationDelegate.h" #import "UnityAdsLoadDelegate.h" #import "USRVConfiguration.h" +#import "UADSLoadOptions.h" @interface UADSLoadModule : NSObject +(instancetype _Nonnull )sharedInstance; --(void)load:(NSString *_Nonnull)placementId loadDelegate:(nullable id)loadDelegate; +-(void)load:(NSString *_Nonnull)placementId options:(UADSLoadOptions*_Nonnull)options loadDelegate:(nullable id)loadDelegate; -(void)sendAdLoaded:(NSString*_Nonnull)placementId listenerId:(NSString*_Nonnull)listenerId; diff --git a/UnityServices/Ads/Load/UADSLoadModule.m b/UnityServices/Ads/Load/UADSLoadModule.m index 385c4100..d6a65095 100644 --- a/UnityServices/Ads/Load/UADSLoadModule.m +++ b/UnityServices/Ads/Load/UADSLoadModule.m @@ -16,6 +16,7 @@ @interface LoadEventState : NSObject { @property(nonatomic, readwrite) NSString* placementId; @property(nonatomic, readwrite) NSString* listenerId; @property(nonatomic, readwrite) NSNumber* time; +@property(nonatomic, readwrite) UADSLoadOptions* options; @property(nonatomic, strong) id delegate; @end @@ -67,13 +68,17 @@ -(instancetype)initWithNotificationCenter:(NSObject )loadDelegate { +-(void) load:(NSString *)placementId + options:(UADSLoadOptions*)options +loadDelegate:(nullable id)loadDelegate { if (placementId == nil || [placementId isEqual: @""]) { [loadDelegate unityAdsAdFailedToLoad:placementId]; return; } - LoadEventState* loadEventState = [self createLoadEventState:placementId listener:loadDelegate]; + LoadEventState* loadEventState = [self createLoadEventState:placementId + options:options + listener:loadDelegate]; if ([USRVSdkProperties isInitialized]) { dispatch_async(_loadQueue, ^{ @@ -86,7 +91,9 @@ -(void)load:(NSString *)placementId loadDelegate:(nullable id)listener { +-(LoadEventState*)createLoadEventState:(NSString*)placementId + options:(UADSLoadOptions*)options + listener:(id)listener { NSString* listenerId = [[NSUUID UUID] UUIDString]; @@ -95,6 +102,7 @@ -(LoadEventState*)createLoadEventState:(NSString*)placementId listener:(id)eventHandler; + +- (void)createTokens:(NSArray*) tokens; +- (void)appendTokens:(NSArray*) tokens; +- (NSString*)getToken; +- (void)deleteTokens; +- (void)setPeekMode:(BOOL)mode; + +@end diff --git a/UnityServices/Ads/Token/UADSTokenStorage.m b/UnityServices/Ads/Token/UADSTokenStorage.m new file mode 100644 index 00000000..a7485c13 --- /dev/null +++ b/UnityServices/Ads/Token/UADSTokenStorage.m @@ -0,0 +1,93 @@ +#import "UADSTokenStorage.h" +#import "UADSTokenStorageEventHandler.h" + +@interface UADSTokenStorage () + +@property id eventHandler; +@property NSMutableArray* queue; +@property int accessCounter; +@property (nonatomic) BOOL peekMode; +@property dispatch_queue_t dispatchQueue; + +@property NSObject* lockObject; + +@end + +@implementation UADSTokenStorage + ++(instancetype)sharedInstance { + static UADSTokenStorage *sharedTokenStorage = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedTokenStorage = [[UADSTokenStorage alloc] initWithEventHandler:[UADSTokenStorageEventHandler new]]; + }); + return sharedTokenStorage; +} + +- (instancetype)initWithEventHandler:(id)eventHandler { + self = [super init]; + + if (self) { + self.eventHandler = eventHandler; + _peekMode = NO; + _lockObject = [NSObject new]; + } + + return self; +} + +- (void)createTokens:(NSArray*) tokens { + @synchronized (_lockObject) { + self.accessCounter = 0; + self.queue = [[NSMutableArray alloc] initWithCapacity:tokens.count]; + [self.queue addObjectsFromArray:tokens]; + } +} + +- (void)appendTokens:(NSArray*) tokens { + @synchronized (_lockObject) { + if (self.queue == nil) { + self.accessCounter = 0; + self.queue = [[NSMutableArray alloc] initWithCapacity:tokens.count]; + } + + [self.queue addObjectsFromArray:tokens]; + } +} + +- (void)setPeekMode:(BOOL)mode { + @synchronized (_lockObject) { + _peekMode = mode; + } +} + +- (NSString*)getToken { + @synchronized (_lockObject) { + if (self.queue == nil) { + return nil; + } + if (self.queue.count == 0) { + [self.eventHandler sendQueueEmpty]; + return nil; + } + + [self.eventHandler sendTokenAccessIndex:[NSNumber numberWithInt:self.accessCounter++]]; + + NSString* nextToken = self.queue[0]; + + if (!self.peekMode) { + [self.queue removeObjectAtIndex:0]; + } + + return nextToken; + } +} + +- (void)deleteTokens { + @synchronized (_lockObject) { + self.queue = nil; + self.accessCounter = 0; + } +} + +@end diff --git a/UnityServices/Ads/Token/UADSTokenStorageEvent.h b/UnityServices/Ads/Token/UADSTokenStorageEvent.h new file mode 100644 index 00000000..73ba61e7 --- /dev/null +++ b/UnityServices/Ads/Token/UADSTokenStorageEvent.h @@ -0,0 +1,8 @@ +#import + +typedef NS_ENUM(NSInteger, UnityAdsTokenStorageEvent) { + kUnityAdsTokenStorageQueueEmpty, + kUnityAdsTokenStorageAccessToken +}; + +NSString *UADSNSStringFromTokenStorageEvent(UnityAdsTokenStorageEvent); diff --git a/UnityServices/Ads/Token/UADSTokenStorageEvent.m b/UnityServices/Ads/Token/UADSTokenStorageEvent.m new file mode 100644 index 00000000..8be9fad2 --- /dev/null +++ b/UnityServices/Ads/Token/UADSTokenStorageEvent.m @@ -0,0 +1,13 @@ +#import "UADSTokenStorageEvent.h" + +static NSString *unityAdTokenStorageEventQueueEmpty = @"QUEUE_EMPTY"; +static NSString *unityAdTokenStorageEventTokenAccess = @"TOKEN_ACCESS"; + +NSString *UADSNSStringFromTokenStorageEvent(UnityAdsTokenStorageEvent event) { + switch (event) { + case kUnityAdsTokenStorageQueueEmpty: + return unityAdTokenStorageEventQueueEmpty; + case kUnityAdsTokenStorageAccessToken: + return unityAdTokenStorageEventTokenAccess; + } +} diff --git a/UnityServices/Ads/Token/UADSTokenStorageEventHandler.h b/UnityServices/Ads/Token/UADSTokenStorageEventHandler.h new file mode 100644 index 00000000..eb5e9193 --- /dev/null +++ b/UnityServices/Ads/Token/UADSTokenStorageEventHandler.h @@ -0,0 +1,8 @@ +#import "UADSTokenStorageEventProtocol.h" + +@interface UADSTokenStorageEventHandler : NSObject + +- (void) sendQueueEmpty; +- (void) sendTokenAccess:(NSNumber*)index; + +@end diff --git a/UnityServices/Ads/Token/UADSTokenStorageEventHandler.m b/UnityServices/Ads/Token/UADSTokenStorageEventHandler.m new file mode 100644 index 00000000..2cbadf8e --- /dev/null +++ b/UnityServices/Ads/Token/UADSTokenStorageEventHandler.m @@ -0,0 +1,20 @@ +#import "UADSTokenStorageEventHandler.h" +#import "USRVWebViewApp.h" +#import "USRVWebViewEventCategory.h" +#import "UADSTokenStorageEvent.h" + +@implementation UADSTokenStorageEventHandler + +- (void) sendQueueEmpty { + dispatch_async(dispatch_get_main_queue(), ^{ + [[USRVWebViewApp getCurrentApp] sendEvent:UADSNSStringFromTokenStorageEvent(kUnityAdsTokenStorageQueueEmpty) category:USRVNSStringFromWebViewEventCategory(kUnityServicesWebViewEventCategoryTokenApi) params:@[]]; + }); +} + +- (void) sendTokenAccessIndex:(NSNumber*)index { + dispatch_async(dispatch_get_main_queue(), ^{ + [[USRVWebViewApp getCurrentApp] sendEvent:UADSNSStringFromTokenStorageEvent(kUnityAdsTokenStorageAccessToken) category:USRVNSStringFromWebViewEventCategory(kUnityServicesWebViewEventCategoryTokenApi) params:@[index]]; + }); +} + +@end diff --git a/UnityServices/Ads/Token/UADSTokenStorageEventProtocol.h b/UnityServices/Ads/Token/UADSTokenStorageEventProtocol.h new file mode 100644 index 00000000..c2b99fcb --- /dev/null +++ b/UnityServices/Ads/Token/UADSTokenStorageEventProtocol.h @@ -0,0 +1,6 @@ +@protocol UADSTokenStorageEventProtocol + +- (void) sendQueueEmpty; +- (void) sendTokenAccessIndex:(NSNumber*)index; + +@end diff --git a/UnityServices/Ads/UnityAds.h b/UnityServices/Ads/UnityAds.h index 16ecd9c8..7ce77203 100644 --- a/UnityServices/Ads/UnityAds.h +++ b/UnityServices/Ads/UnityAds.h @@ -34,6 +34,8 @@ #import "UnityAdsInitializationError.h" #import "UnityAdsInitializationDelegate.h" #import "UnityAdsLoadDelegate.h" +#import "UADSLoadOptions.h" +#import "UADSShowOptions.h" NS_ASSUME_NONNULL_BEGIN @@ -159,7 +161,21 @@ NS_ASSUME_NONNULL_BEGIN * @param placementId The placement ID, as defined in Unity Ads admin tools. * @param loadDelegate The load delegate. */ -+ (void)load:(NSString *)placementId loadDelegate:(nullable id)loadDelegate; ++ (void) load:(NSString *)placementId + loadDelegate:(nullable id)loadDelegate; + +/** + * Load a placement to make it available to show. Ads generally take a few seconds to finish loading before they can be shown. + * Note: The `load` API is in closed beta and available upon invite only. If you would like to be considered for the beta, please contact Unity Ads Support. + * + * @param placementId The placement ID, as defined in Unity Ads admin tools. + * @param options The load options. + * @param loadDelegate The load delegate. + */ ++ (void) load:(NSString *)placementId + options:(UADSLoadOptions *)options + loadDelegate:(nullable id)loadDelegate; + /** * Show an ad using the defaul placement. @@ -174,6 +190,14 @@ NS_ASSUME_NONNULL_BEGIN * @param placementId The placement ID, as defined in Unity Ads admin tools. */ + (void)show:(UIViewController *)viewController placementId:(NSString *)placementId; +/** + * Show an ad using the provided placement ID. + * + * @param viewController The `UIViewController` that is to present the ad view controller. + * @param placementId The placement ID, as defined in Unity Ads admin tools. + * @param options Additional options + */ ++ (void)show:(UIViewController *)viewController placementId:(NSString *)placementId options:(UADSShowOptions *)options; /** * Provides the currently assigned `UnityAdsDelegate`. Meant to support use of single delegate * @@ -263,6 +287,12 @@ NS_ASSUME_NONNULL_BEGIN * @return If `YES`, Unity Ads has been successfully initialized. */ + (BOOL)isInitialized; +/** + * Get request token. + * + * @return Active token or null if no active token is available. + */ ++ (NSString* __nullable)getToken; @end diff --git a/UnityServices/Ads/UnityAds.m b/UnityServices/Ads/UnityAds.m index 3cbf4f83..7f4babeb 100644 --- a/UnityServices/Ads/UnityAds.m +++ b/UnityServices/Ads/UnityAds.m @@ -8,6 +8,7 @@ #import "UADSWebViewShowOperation.h" #import "UnityAdsDelegateUtil.h" #import "UADSLoadModule.h" +#import "UADSTokenStorage.h" @implementation UnityAds @@ -69,8 +70,16 @@ + (void)load:(NSString *)placementId { [self load:placementId loadDelegate:nil]; } -+ (void)load:(NSString *)placementId loadDelegate:(nullable id)loadDelegate { - [[UADSLoadModule sharedInstance] load:placementId loadDelegate:loadDelegate]; ++ (void)load:(NSString *)placementId +loadDelegate:(nullable id)loadDelegate { + [self load:placementId options:[UADSLoadOptions new] loadDelegate:loadDelegate]; +} + ++ (void) load:(NSString *)placementId + options:(UADSLoadOptions *)options + loadDelegate:(nullable id)loadDelegate; + { + [[UADSLoadModule sharedInstance] load:placementId options:options loadDelegate:loadDelegate]; } + (void)show:(UIViewController *)viewController { @@ -82,6 +91,10 @@ + (void)show:(UIViewController *)viewController { } + (void)show:(UIViewController *)viewController placementId:(NSString *)placementId { + [UnityAds show:viewController placementId:placementId options:[UADSShowOptions new]]; +} + ++ (void)show:(UIViewController *)viewController placementId:(NSString *)placementId options:(UADSShowOptions *)options { [USRVClientProperties setCurrentViewController:viewController]; if ([UnityAds isReady:placementId]) { USRVLogInfo(@"Unity Ads opening new ad unit for placement %@", placementId); @@ -92,7 +105,9 @@ + (void)show:(UIViewController *)viewController placementId:(NSString *)placemen @"supportedOrientations" : [NSNumber numberWithInt:[USRVClientProperties getSupportedOrientations]], @"supportedOrientationsPlist" : [USRVClientProperties getSupportedOrientationsPlist], @"statusBarOrientation" : [NSNumber numberWithInteger:statusBarOrientation], - @"statusBarHidden" : [NSNumber numberWithBool: [UIApplication sharedApplication].isStatusBarHidden]}; + @"statusBarHidden" : [NSNumber numberWithBool: [UIApplication sharedApplication].isStatusBarHidden], + @"options" : options.dictionary + }; UADSWebViewShowOperation *operation = [[UADSWebViewShowOperation alloc] initWithPlacementId:placementId @@ -174,6 +189,10 @@ + (void)handleShowError:(NSString *)placementId unityAdsError:(UnityAdsError)uni } } ++ (NSString* __nullable)getToken { + return [[UADSTokenStorage sharedInstance] getToken]; +} + @end @implementation UnityServicesListener diff --git a/UnityServices/Core/Properties/USRVSdkProperties.m b/UnityServices/Core/Properties/USRVSdkProperties.m index 00f8cab7..b904adb4 100644 --- a/UnityServices/Core/Properties/USRVSdkProperties.m +++ b/UnityServices/Core/Properties/USRVSdkProperties.m @@ -7,12 +7,12 @@ NSString * const kUnityServicesLocalStorageFilePrefix = @"UnityAdsStorage-"; NSString * const kUnityServicesWebviewBranchInfoDictionaryKey = @"UADSWebviewBranch"; NSString * const kUnityServicesWebviewConfigInfoDictionaryKey = @"UADSWebviewConfig"; -NSString * const kUnityServicesVersionName = @"3.5.1"; +NSString * const kUnityServicesVersionName = @"3.6.0"; NSString * const kUnityServicesFlavorDebug = @"debug"; NSString * const kUnityServicesFlavorRelease = @"release"; NSString * const kChinaIsoAlpha2Code = @"CN"; NSString * const kChinaIsoAlpha3Code = @"CHN"; -int const kUnityServicesVersionCode = 3510; +int const kUnityServicesVersionCode = 3600; @implementation USRVSdkProperties diff --git a/UnityServices/Core/WebView/USRVWebViewEventCategory.h b/UnityServices/Core/WebView/USRVWebViewEventCategory.h index 3e72b576..14a0521a 100644 --- a/UnityServices/Core/WebView/USRVWebViewEventCategory.h +++ b/UnityServices/Core/WebView/USRVWebViewEventCategory.h @@ -18,7 +18,8 @@ typedef NS_ENUM(NSInteger, UnityServicesWebViewEventCategory) { kUnityServicesWebViewEventCategoryPermissions, kUnityServicesWebViewEventCategoryNativeError, kUnityServicesWebViewEventCategoryWebAuthSession, - kUnityServicesWebViewEventCategoryLoadApi + kUnityServicesWebViewEventCategoryLoadApi, + kUnityServicesWebViewEventCategoryTokenApi }; NSString *USRVNSStringFromWebViewEventCategory(UnityServicesWebViewEventCategory); diff --git a/UnityServices/Core/WebView/USRVWebViewEventCategory.m b/UnityServices/Core/WebView/USRVWebViewEventCategory.m index 970654df..c76c6304 100644 --- a/UnityServices/Core/WebView/USRVWebViewEventCategory.m +++ b/UnityServices/Core/WebView/USRVWebViewEventCategory.m @@ -18,6 +18,7 @@ static NSString * const eventCategoryNativeError = @"NATIVE_ERROR"; static NSString * const eventCategoryWebAuthSession = @"WEB_AUTH_SESSION"; static NSString * const eventCategoryLoadApi = @"LOAD_API"; +static NSString * const eventCategoryTokenApi = @"TOKEN"; NSString *USRVNSStringFromWebViewEventCategory(UnityServicesWebViewEventCategory category) { switch (category) { @@ -57,5 +58,7 @@ return eventCategoryWebAuthSession; case kUnityServicesWebViewEventCategoryLoadApi: return eventCategoryLoadApi; + case kUnityServicesWebViewEventCategoryTokenApi: + return eventCategoryTokenApi; } } diff --git a/generate-project.rb b/generate-project.rb index 41be50f0..31f81fd0 100755 --- a/generate-project.rb +++ b/generate-project.rb @@ -91,6 +91,9 @@ def create_groups_from_dir(root_dir, parent_group, target, is_example_project = /UnityAdsInitializationDelegate\.h/, /UnityAdsInitializationError\.h/, /UnityAdsLoadDelegate\.h/, + /UADSBaseOptions\.h/, + /UADSLoadOptions\.h/, + /UADSShowOptions\.h/, # Banners /UADSBanner\.h/, diff --git a/scripts/gitlab/analyze.sh b/scripts/gitlab/analyze.sh deleted file mode 100755 index 29e80f2b..00000000 --- a/scripts/gitlab/analyze.sh +++ /dev/null @@ -1,11 +0,0 @@ -set -e -o xtrace - -mkdir build || true -touch build/analyze-output.txt -bundle exec fastlane analyze 2>&1 | tee build/analyze-output.txt - -ANALYSIS=$(awk '/Analyzing/{y=1}y' build/analyze-output.txt) -if grep -q "⚠️" <<< $ANALYSIS; then - echo "Please fix the warnings found during static analysis!" - exit 1; -fi diff --git a/scripts/gitlab/hybrid-test.sh b/scripts/gitlab/hybrid-test.sh deleted file mode 100755 index 6f817a6d..00000000 --- a/scripts/gitlab/hybrid-test.sh +++ /dev/null @@ -1,19 +0,0 @@ -set -e - -bundle exec fastlane hybrid_test - -HYBRID_TEST_LOG=~/Library/Logs/scan/UnityAdsHybridTests-UnityAdsHybridTests.log - -PASSING=$(grep -o -m 1 "[0-9]\+ passing \(.*\)" $HYBRID_TEST_LOG) || true -PENDING=$(grep -o -m 1 "[0-9]\+ pending" $HYBRID_TEST_LOG) || true -FAILING=$(grep -o -m 1 "[0-9]\+ failing" $HYBRID_TEST_LOG) || true - -printf "${PASSING}\n${PENDING}\n${FAILING}\n" - -if grep -q "[0-9]\+ failing" <<< $FAILING; then - printf "Hybrid Tests Failed!\n${FAILING}\n" - exit 1; -else - echo "Finished Hybrid Testing Successfully" - exit 0; -fi diff --git a/scripts/gitlab/post-internal-github-release.sh b/scripts/gitlab/post-internal-github-release.sh deleted file mode 100755 index 61083415..00000000 --- a/scripts/gitlab/post-internal-github-release.sh +++ /dev/null @@ -1,37 +0,0 @@ -set -o xtrace - -CURRENT_COMMIT_ID=${CI_COMMIT_SHA}; -echo "CURRENT_COMMIT_ID=$CURRENT_COMMIT_ID"; - -echo "CI_COMMIT_REF_NAME=$CI_COMMIT_REF_NAME"; -[[ $CI_COMMIT_REF_NAME =~ ^release\/([0-9\.]*)$ ]]; -RELEASE_VERSION=${BASH_REMATCH[1]}; -if [[ ! $RELEASE_VERSION ]]; then - [[ $CI_COMMIT_REF_NAME =~ ^feature\/gitlab-release-stage$ ]]; - RELEASE_VERSION=${BASH_REMATCH[0]}; -fi -echo "RELEASE_VERSION=$RELEASE_VERSION"; - -make verify-release-build; - -if [[ $CURRENT_COMMIT_ID && $RELEASE_VERSION && $GITHUB_PERSONAL_ACCESS_TOKEN ]]; then - CREATE_RELEASE_RESPONSE=$(curl -X POST --fail \ - -H "Authorization: token $GITHUB_PERSONAL_ACCESS_TOKEN" \ - -d "{ \"tag_name\": \"${RELEASE_VERSION}\", \"target_commitish\": \"${CURRENT_COMMIT_ID}\", \"name\": \"Unity Ads ${RELEASE_VERSION}\", \"body\": \"Unity Ads ${RELEASE_VERSION}\", \"draft\": true }" \ - "https://api.github.com/repos/Applifier/unity-ads-ios/releases"); - UPLOAD_URL=$(echo "$CREATE_RELEASE_RESPONSE" | jq -r '.upload_url' | cut -f1 -d"{") - if [[ UPLOAD_URL && UPLOAD_URL != null ]]; then - echo "UPLOAD_URL=$UPLOAD_URL"; - curl -X POST --fail \ - -H "Authorization: token $GITHUB_PERSONAL_ACCESS_TOKEN" \ - -H "Content-Type: application/zip" \ - --data-binary @UnityAds.framework.zip \ - "$UPLOAD_URL?name=UnityAds.framework.zip&label=UnityAds.framework.zip"; - else - echo "UPLOAD_URL not found"; - exit 1; - fi -else - echo "CURRENT_COMMIT_ID or RELEASE_VERSION or GITHUB_PERSONAL_ACCESS_TOKEN not found"; - exit 1; -fi diff --git a/scripts/gitlab/post-public-github-release.sh b/scripts/gitlab/post-public-github-release.sh deleted file mode 100644 index 005c3f9a..00000000 --- a/scripts/gitlab/post-public-github-release.sh +++ /dev/null @@ -1,37 +0,0 @@ -set -o xtrace - -CURRENT_COMMIT_ID=${CI_COMMIT_SHA}; -echo "CURRENT_COMMIT_ID=$CURRENT_COMMIT_ID"; - -echo "CI_COMMIT_REF_NAME=$CI_COMMIT_REF_NAME"; -[[ $CI_COMMIT_REF_NAME =~ ^release\/([0-9\.]*)$ ]]; -RELEASE_VERSION=${BASH_REMATCH[1]}; -if [[ ! $RELEASE_VERSION ]]; then - [[ $CI_COMMIT_REF_NAME =~ ^feature\/gitlab-release-stage$ ]]; - RELEASE_VERSION=${BASH_REMATCH[0]}; -fi -echo "RELEASE_VERSION=$RELEASE_VERSION"; - -make verify-release-build; - -if [[ $CURRENT_COMMIT_ID && $RELEASE_VERSION && $GITHUB_PERSONAL_ACCESS_TOKEN ]]; then - CREATE_RELEASE_RESPONSE=$(curl -X POST --fail \ - -H "Authorization: token $GITHUB_PERSONAL_ACCESS_TOKEN" \ - -d "{ \"tag_name\": \"${RELEASE_VERSION}\", \"target_commitish\": \"${CURRENT_COMMIT_ID}\", \"name\": \"Unity Ads ${RELEASE_VERSION}\", \"body\": \"Unity Ads ${RELEASE_VERSION}\", \"draft\": true }" \ - "https://api.github.com/repos/Unity-Technologies/unity-ads-ios/releases"); - UPLOAD_URL=$(echo "$CREATE_RELEASE_RESPONSE" | jq -r '.upload_url' | cut -f1 -d"{") - if [[ UPLOAD_URL && UPLOAD_URL != null ]]; then - echo "UPLOAD_URL=$UPLOAD_URL"; - curl -X POST --fail \ - -H "Authorization: token $GITHUB_PERSONAL_ACCESS_TOKEN" \ - -H "Content-Type: application/zip" \ - --data-binary @UnityAds.framework.zip \ - "$UPLOAD_URL?name=UnityAds.framework.zip&label=UnityAds.framework.zip"; - else - echo "UPLOAD_URL not found"; - exit 1; - fi -else - echo "CURRENT_COMMIT_ID or RELEASE_VERSION or GITHUB_PERSONAL_ACCESS_TOKEN not found"; - exit 1; -fi diff --git a/scripts/gitlab/setup.sh b/scripts/gitlab/setup.sh deleted file mode 100755 index bc3dd83a..00000000 --- a/scripts/gitlab/setup.sh +++ /dev/null @@ -1,3 +0,0 @@ -set -o xtrace - -bundle exec fastlane gitlab_match diff --git a/set_properties_for_testing.rb b/set_properties_for_testing.rb deleted file mode 100644 index cbb9234e..00000000 --- a/set_properties_for_testing.rb +++ /dev/null @@ -1,69 +0,0 @@ -require 'bundler' -Bundler.require(:default) - -INFO_PLIST_PATH = 'UnityAdsExample/Info.plist' -INFO_PLIST_ATS_KEY = 'NSAppTransportSecurity' -INFO_PLIST_ATS_EXCEPTION_DOMAINS_KEY = 'NSExceptionDomains' -INFO_PLIST_ATS_EXCEPTION_DOMAINS_INCLUDES_SUBDOMAINS_KEY = 'NSIncludesSubdomains' -INFO_PLIST_ATS_EXCEPTION_DOMAINS_ALLOW_HTTP_REQUESTS_KEY = 'NSTemporaryExceptionAllowsInsecureHTTPLoads' -INFO_PLIST_UADS_TEST_SERVER_ADDRESS_KEY = "UADSTestServerAddress" - -class InfoPlist - def initialize(file_path) - @info_plist_path = file_path - begin - @info_plist_hash = Plist::parse_xml(file_path) - rescue Exception => e - puts "Cannot read plist from file '#{file_path}': #{e}" - raise e - end - end - - def set_server(server_address, port) - plist_entry_hash = {INFO_PLIST_ATS_EXCEPTION_DOMAINS_KEY => {server_address => - {INFO_PLIST_ATS_EXCEPTION_DOMAINS_INCLUDES_SUBDOMAINS_KEY => true, - INFO_PLIST_ATS_EXCEPTION_DOMAINS_ALLOW_HTTP_REQUESTS_KEY => true}}} - - @info_plist_hash[INFO_PLIST_ATS_KEY] = plist_entry_hash - test_server_address = "http://#{server_address}#{":#{port}" if port}" - @info_plist_hash[INFO_PLIST_UADS_TEST_SERVER_ADDRESS_KEY] = test_server_address - end - - def clear - @info_plist_hash.delete(INFO_PLIST_UADS_TEST_SERVER_ADDRESS_KEY) - @info_plist_hash.delete(INFO_PLIST_ATS_KEY) - end - - def to_file - begin - File.open(@info_plist_path, 'wb') do |fh| - fh.write(@info_plist_hash.to_plist) - end - rescue Exception => e - puts "Cannot write plist to file '#{@info_plist_path}': #{e}" - raise e - end - end -end - -# Handle command line arguments -opts = Optimist::options do - opt :server, "Set test-server address (for example: terminal.applifier.info (no leading 'http://'))", :type => :string - opt :port, "Set test-server port", :type => :int - opt :clear, "Clear testing entries from plist" -end - -if opts[:clear] - ip = InfoPlist.new(INFO_PLIST_PATH) - ip.clear - ip.to_file - exit -end - -if opts[:server] - ip = InfoPlist.new(INFO_PLIST_PATH) - ip.set_server(opts[:server], opts[:port]) - ip.to_file -else - Optimist::die "Please set server-address" -end diff --git a/set_webview_plist.rb b/set_webview_plist.rb deleted file mode 100755 index 7a833917..00000000 --- a/set_webview_plist.rb +++ /dev/null @@ -1,64 +0,0 @@ -require 'bundler' -Bundler.require(:default) - -INFO_PLIST_PATH = 'UnityAdsExample/Info.plist' -INFO_PLIST_WEBVIEW_KEY = 'UADSWebviewBranch' - -class InfoPlist - def initialize(file_path) - @info_plist_path = file_path - begin - @info_plist_hash = Plist::parse_xml(file_path) - rescue Exception => e - puts "Cannot read plist from file '#{file_path}': #{e}" - raise e - end - end - - def set_webview(webview_string) - begin - @info_plist_hash[INFO_PLIST_WEBVIEW_KEY] = webview_string - rescue Exception => e - puts "Unable to add webview '#{webview_string}' to key '#{INFO_PLIST_WEBVIEW_KEY}' in plist: #{e}" - raise e - end - end - - def clear_webview - @info_plist_hash[INFO_PLIST_WEBVIEW_KEY] && @info_plist_hash.delete(INFO_PLIST_WEBVIEW_KEY) - end - - def list_current - puts "#{@info_plist_hash[INFO_PLIST_WEBVIEW_KEY]}" - end - - def to_file - begin - File.open(@info_plist_path, 'wb') do |fh| - fh.write(@info_plist_hash.to_plist) - end - rescue Exception => e - puts "Cannot write plist to file '#{@info_plist_path}': #{e}" - raise e - end - end -end - -# Handle command line arguments -opts = Optimist::options do - opt :webview, "Webview that ads sdk will use in the build", - :type => :string -end - -webview = opts[:webview] - -if !opts[:webview] - Optimist::die "Webview not given, exiting" - exit -end - -ip = InfoPlist.new(INFO_PLIST_PATH) - -ip.clear_webview -ip.set_webview(webview) -ip.to_file