diff --git a/adapters/Vungle/Public/Headers/VungleRouterConfiguration.h b/adapters/Vungle/Public/Headers/VungleRouterConfiguration.h index f2dc8cd19..676eee0ce 100644 --- a/adapters/Vungle/Public/Headers/VungleRouterConfiguration.h +++ b/adapters/Vungle/Public/Headers/VungleRouterConfiguration.h @@ -16,8 +16,15 @@ NS_ASSUME_NONNULL_BEGIN +typedef NS_ENUM(NSInteger, GADMAdapterVungleCCPAStatus) { + GADMAdapterVungleCCPAAccepted = 1, + GADMAdapterVungleCCPADenied, +}; + @interface VungleRouterConfiguration : NSObject + (void)setPublishIDFV:(BOOL)publish; ++ (void)setCCPAStatus:(GADMAdapterVungleCCPAStatus)ccpaStatus; ++ (GADMAdapterVungleCCPAStatus)getCCPAStatus; + (void)setMinSpaceForInit:(int)size; + (void)setMinSpaceForAdLoad:(int)size; @end diff --git a/adapters/Vungle/VungleAdapter.xcodeproj/project.pbxproj b/adapters/Vungle/VungleAdapter.xcodeproj/project.pbxproj index 96db429b8..227712d53 100644 --- a/adapters/Vungle/VungleAdapter.xcodeproj/project.pbxproj +++ b/adapters/Vungle/VungleAdapter.xcodeproj/project.pbxproj @@ -33,8 +33,6 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 4075428E2418E7B500DF2AAD /* GADMAdapterVungleBannerRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 4075428C2418E7B500DF2AAD /* GADMAdapterVungleBannerRequest.h */; }; - 4075428F2418E7B500DF2AAD /* GADMAdapterVungleBannerRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4075428D2418E7B500DF2AAD /* GADMAdapterVungleBannerRequest.m */; }; 407621A123F140B800C18557 /* VungleRouterConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 4076219F23F140B800C18557 /* VungleRouterConfiguration.m */; }; 407621A223F140B800C18557 /* VungleRouterConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 407621A023F140B800C18557 /* VungleRouterConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4552392A20B6381E0081388F /* VungleRouterConsent.m in Sources */ = {isa = PBXBuildFile; fileRef = 4552392720B6381D0081388F /* VungleRouterConsent.m */; }; @@ -89,8 +87,6 @@ /* Begin PBXFileReference section */ 00DD26AB22F10DD20039C1D4 /* Script_Validate.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = Script_Validate.sh; sourceTree = ""; }; - 4075428C2418E7B500DF2AAD /* GADMAdapterVungleBannerRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GADMAdapterVungleBannerRequest.h; sourceTree = ""; }; - 4075428D2418E7B500DF2AAD /* GADMAdapterVungleBannerRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GADMAdapterVungleBannerRequest.m; sourceTree = ""; }; 4076219F23F140B800C18557 /* VungleRouterConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VungleRouterConfiguration.m; sourceTree = ""; }; 407621A023F140B800C18557 /* VungleRouterConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VungleRouterConfiguration.h; sourceTree = ""; }; 4552392720B6381D0081388F /* VungleRouterConsent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VungleRouterConsent.m; sourceTree = ""; }; @@ -137,8 +133,6 @@ 7D15756E1EB7FB9200059469 /* VungleAdapter */ = { isa = PBXGroup; children = ( - 4075428C2418E7B500DF2AAD /* GADMAdapterVungleBannerRequest.h */, - 4075428D2418E7B500DF2AAD /* GADMAdapterVungleBannerRequest.m */, 4076219F23F140B800C18557 /* VungleRouterConfiguration.m */, 4593F48B227CDC9300F57AE5 /* GADMAdapterVungleConstants.h */, 4557855A238DE7E700523142 /* GADMAdapterVungleDelegate.h */, @@ -228,7 +222,6 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 4075428E2418E7B500DF2AAD /* GADMAdapterVungleBannerRequest.h in Headers */, 4593F48F227CE28A00F57AE5 /* GADMAdapterVungleUtils.h in Headers */, 407621A223F140B800C18557 /* VungleRouterConfiguration.h in Headers */, A85428E01F11853A00C135E7 /* GADMAdapterVungleInterstitial.h in Headers */, @@ -347,7 +340,6 @@ A85428E11F11853A00C135E7 /* GADMAdapterVungleInterstitial.m in Sources */, A85428E31F11853A00C135E7 /* GADMAdapterVungleRewardBasedVideoAd.m in Sources */, 407621A123F140B800C18557 /* VungleRouterConfiguration.m in Sources */, - 4075428F2418E7B500DF2AAD /* GADMAdapterVungleBannerRequest.m in Sources */, 4593F490227CE28A00F57AE5 /* GADMAdapterVungleUtils.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/adapters/Vungle/VungleAdapter/GADMAdapterVungleBannerRequest.h b/adapters/Vungle/VungleAdapter/GADMAdapterVungleBannerRequest.h deleted file mode 100644 index a9a90980d..000000000 --- a/adapters/Vungle/VungleAdapter/GADMAdapterVungleBannerRequest.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2019 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#import - -@interface GADMAdapterVungleBannerRequest : NSObject - -- (nonnull instancetype)initWithPlacementID:(nonnull NSString *)placementID - uniquePubRequestID:(nullable NSString *)uniquePubRequestID; - -- (BOOL)isEqualToBannerRequest:(nonnull GADMAdapterVungleBannerRequest *)bannerRequest; - -@property(nonatomic, copy, readonly) NSString *_Nonnull placementID; -@property(nonatomic, copy, readonly) NSString *_Nullable uniquePubRequestID; - -@end diff --git a/adapters/Vungle/VungleAdapter/GADMAdapterVungleBannerRequest.m b/adapters/Vungle/VungleAdapter/GADMAdapterVungleBannerRequest.m deleted file mode 100644 index 0b3676442..000000000 --- a/adapters/Vungle/VungleAdapter/GADMAdapterVungleBannerRequest.m +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2019 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#import "GADMAdapterVungleBannerRequest.h" - -@interface GADMAdapterVungleBannerRequest () - -@property(nonatomic, copy) NSString *placementID; -@property(nonatomic, copy) NSString *uniquePubRequestID; - -@end - -@implementation GADMAdapterVungleBannerRequest - -- (nonnull instancetype)initWithPlacementID:(nonnull NSString *)placementID - uniquePubRequestID:(nullable NSString *)uniquePubRequestID { - self = [super init]; - if (self) { - _placementID = [placementID copy]; - _uniquePubRequestID = [uniquePubRequestID copy]; - } - return self; -} - -- (nonnull instancetype)init { - return [self initWithPlacementID:@"" uniquePubRequestID:nil]; -} - -- (instancetype)copyWithZone:(NSZone *)zone { - GADMAdapterVungleBannerRequest *copy = [[[self class] alloc] init]; - if (copy) { - copy.placementID = [self.placementID copyWithZone:zone]; - copy.uniquePubRequestID = [self.uniquePubRequestID copyWithZone:zone]; - } - return copy; -} - -- (BOOL)isEqualToBannerRequest:(GADMAdapterVungleBannerRequest *)bannerRequest { - if (!bannerRequest) { - return NO; - } - - BOOL haveEqualPlacementIDs = [self.placementID isEqualToString:bannerRequest.placementID]; - BOOL haveEqualUniquePubRequestIDs = [self.uniquePubRequestID isEqualToString:bannerRequest.uniquePubRequestID]; - - return haveEqualPlacementIDs && haveEqualUniquePubRequestIDs; -} - -- (BOOL)isEqual:(id)object { - if (self == object) { - return YES; - } - - if (![object isKindOfClass:[GADMAdapterVungleBannerRequest class]]) { - return NO; - } - - return [self isEqualToBannerRequest:(GADMAdapterVungleBannerRequest *)object]; -} - -- (NSUInteger)hash { - return [self.placementID hash] ^ [self.uniquePubRequestID hash]; -} - -@end diff --git a/adapters/Vungle/VungleAdapter/GADMAdapterVungleConstants.h b/adapters/Vungle/VungleAdapter/GADMAdapterVungleConstants.h index 3c35ab505..90bbd5f16 100644 --- a/adapters/Vungle/VungleAdapter/GADMAdapterVungleConstants.h +++ b/adapters/Vungle/VungleAdapter/GADMAdapterVungleConstants.h @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -static NSString *const _Nonnull kGADMAdapterVungleVersion = @"6.5.3.0"; +static NSString *const _Nonnull kGADMAdapterVungleVersion = @"6.7.0.0-early1"; static NSString *const _Nonnull kGADMAdapterVungleApplicationID = @"application_id"; static NSString *const _Nonnull kGADMAdapterVunglePlacementID = @"placementID"; static NSString *const _Nonnull kGADMAdapterVungleErrorDomain = @"com.google.mediation.vungle"; diff --git a/adapters/Vungle/VungleAdapter/GADMAdapterVungleDelegate.h b/adapters/Vungle/VungleAdapter/GADMAdapterVungleDelegate.h index 4f8776fe8..b5f62ad87 100644 --- a/adapters/Vungle/VungleAdapter/GADMAdapterVungleDelegate.h +++ b/adapters/Vungle/VungleAdapter/GADMAdapterVungleDelegate.h @@ -33,8 +33,6 @@ typedef NS_ENUM(NSUInteger, BannerRouterDelegateState) { BannerRouterDelegateStateClosed }; -@class GADMAdapterVungleBannerRequest; - /// Delegate for receiving state change messages from the Vungle SDK. @protocol GADMAdapterVungleDelegate @@ -48,15 +46,22 @@ typedef NS_ENUM(NSUInteger, BannerRouterDelegateState) { - (void)adAvailable; - (void)adNotAvailable:(nonnull NSError *)error; - (void)willShowAd; -- (void)willCloseAd:(BOOL)completedView didDownload:(BOOL)didDownload; -- (void)didCloseAd:(BOOL)completedView didDownload:(BOOL)didDownload; +- (void)willCloseAd; +- (void)didCloseAd; +- (void)trackClick; @optional // Check is banner ad - (BOOL)isBannerAd; -// Get banner request object -@property(nonatomic, nonnull) GADMAdapterVungleBannerRequest *bannerRequest; +// Differentiate two banners with same placement ID +@property(nonatomic, nullable) NSString *uniquePubRequestID; + +// Reward user for watching a Rewarded Video Ad successfully +- (void)rewardUser; + +// App will leave current application +- (void)willLeaveApplication; // Vungle banner ad state. @property(nonatomic, assign) BannerRouterDelegateState bannerState; diff --git a/adapters/Vungle/VungleAdapter/GADMAdapterVungleInterstitial.m b/adapters/Vungle/VungleAdapter/GADMAdapterVungleInterstitial.m index 6eceaba60..b57d15c10 100644 --- a/adapters/Vungle/VungleAdapter/GADMAdapterVungleInterstitial.m +++ b/adapters/Vungle/VungleAdapter/GADMAdapterVungleInterstitial.m @@ -17,7 +17,6 @@ #import "GADMAdapterVungleConstants.h" #import "GADMAdapterVungleRouter.h" #import "GADMAdapterVungleUtils.h" -#import "GADMAdapterVungleBannerRequest.h" @interface GADMAdapterVungleInterstitial () @end @@ -96,26 +95,14 @@ - (void)getBannerWithSize:(GADAdSize)adSize { VungleAdNetworkExtras *networkExtras = [strongConnector networkExtras]; self.desiredPlacement = [GADMAdapterVungleUtils findPlacement:[strongConnector credentials] networkExtras:networkExtras]; - self.bannerRequest = [[GADMAdapterVungleBannerRequest alloc] initWithPlacementID:self.desiredPlacement ?: @"" - uniquePubRequestID:networkExtras.UUID]; - if (!self.desiredPlacement) { + self.uniquePubRequestID = [networkExtras.UUID copy]; + if (!self.desiredPlacement.length) { [strongConnector adapter:self didFailAd:GADMAdapterVungleErrorWithCodeAndDescription( kGADErrorMediationDataError, @"Placement ID not specified.")]; return; } - // Check if a banner or MREC ad has been initiated with the samne PlacementID - // or not. (Vungle supports 4 types of banner currently.) - if (![[GADMAdapterVungleRouter sharedInstance] - canRequestBannerAdForPlacementID:self.bannerRequest]) { - NSError *error = GADMAdapterVungleErrorWithCodeAndDescription( - kGADErrorMediationAdapterError, @"A banner ad type has already been " - @"instantiated. Multiple banner ads are not " - @"supported with Vungle iOS SDK."); - [strongConnector adapter:self didFailAd:error]; - return; - } VungleSDK *sdk = [VungleSDK sharedSDK]; if ([sdk isInitialized]) { @@ -140,7 +127,7 @@ - (void)getInterstitial { id strongConnector = _connector; self.desiredPlacement = [GADMAdapterVungleUtils findPlacement:[strongConnector credentials] networkExtras:[strongConnector networkExtras]]; - if (!self.desiredPlacement) { + if (!self.desiredPlacement.length) { [strongConnector adapter:self didFailAd:GADMAdapterVungleErrorWithCodeAndDescription( kGADErrorMediationDataError, @"Placement ID not specified.")]; @@ -244,7 +231,7 @@ - (BOOL)isBannerAd { @synthesize desiredPlacement; @synthesize adapterAdType; @synthesize bannerState; -@synthesize bannerRequest; +@synthesize uniquePubRequestID; @synthesize isRefreshedForBannerAd; @synthesize isRequestingBannerAdForRefresh; @@ -283,11 +270,8 @@ - (void)willShowAd { } } -- (void)willCloseAd:(BOOL)completedView didDownload:(BOOL)didDownload { +- (void)willCloseAd { id strongConnector = _connector; - if (didDownload) { - [strongConnector adapterDidGetAdClick:self]; - } if ([self isBannerAd]) { self.bannerState = BannerRouterDelegateStateClosing; } @@ -298,7 +282,7 @@ - (void)willCloseAd:(BOOL)completedView didDownload:(BOOL)didDownload { } } -- (void)didCloseAd:(BOOL)completedView didDownload:(BOOL)didDownload { +- (void)didCloseAd { if ([self isBannerAd]) { self.bannerState = BannerRouterDelegateStateClosed; } @@ -308,4 +292,14 @@ - (void)didCloseAd:(BOOL)completedView didDownload:(BOOL)didDownload { } } +- (void)trackClick { + id strongConnector = _connector; + [strongConnector adapterDidGetAdClick:self]; +} + +- (void)willLeaveApplication { + id strongConnector = _connector; + [strongConnector adapterWillLeaveApplication:self]; +} + @end diff --git a/adapters/Vungle/VungleAdapter/GADMAdapterVungleRewardedAd.m b/adapters/Vungle/VungleAdapter/GADMAdapterVungleRewardedAd.m index 0d0a0dc9a..1706eca33 100644 --- a/adapters/Vungle/VungleAdapter/GADMAdapterVungleRewardedAd.m +++ b/adapters/Vungle/VungleAdapter/GADMAdapterVungleRewardedAd.m @@ -69,7 +69,7 @@ - (void)requestRewardedAd { self.desiredPlacement = [GADMAdapterVungleUtils findPlacement:_adConfiguration.credentials.settings networkExtras:_adConfiguration.extras]; - if (!self.desiredPlacement) { + if (!self.desiredPlacement.length) { NSError *error = GADMAdapterVungleErrorWithCodeAndDescription(kGADErrorMediationDataError, @"Placement ID not specified."); _adLoadCompletionHandler(nil, error); @@ -153,25 +153,15 @@ - (void)adAvailable { } } -- (void)didCloseAd:(BOOL)completedView didDownload:(BOOL)didDownload { +- (void)didCloseAd { id strongDelegate = _delegate; - if (completedView) { - [strongDelegate didEndVideo]; - GADAdReward *reward = - [[GADAdReward alloc] initWithRewardType:@"vungle" - rewardAmount:[NSDecimalNumber decimalNumberWithString:@"1"]]; - [strongDelegate didRewardUserWithReward:reward]; - } - if (didDownload) { - [strongDelegate reportClick]; - } [strongDelegate didDismissFullScreenView]; GADMAdapterVungleRewardedAd __weak *weakSelf = self; [[GADMAdapterVungleRouter sharedInstance] removeDelegate:weakSelf]; } -- (void)willCloseAd:(BOOL)completedView didDownload:(BOOL)didDownload { +- (void)willCloseAd { _isRewardedAdPresenting = NO; [_delegate willDismissFullScreenView]; } @@ -188,4 +178,18 @@ - (void)adNotAvailable:(nonnull NSError *)error { [[GADMAdapterVungleRouter sharedInstance] removeDelegate:self]; } +- (void)trackClick { + id strongDelegate = _delegate; + [strongDelegate reportClick]; +} + +- (void)rewardUser { + id strongDelegate = _delegate; + [strongDelegate didEndVideo]; + GADAdReward *reward = + [[GADAdReward alloc] initWithRewardType:@"vungle" + rewardAmount:[NSDecimalNumber decimalNumberWithString:@"1"]]; + [strongDelegate didRewardUserWithReward:reward]; +} + @end diff --git a/adapters/Vungle/VungleAdapter/GADMAdapterVungleRouter.h b/adapters/Vungle/VungleAdapter/GADMAdapterVungleRouter.h index bf79cfcca..113b1fe29 100644 --- a/adapters/Vungle/VungleAdapter/GADMAdapterVungleRouter.h +++ b/adapters/Vungle/VungleAdapter/GADMAdapterVungleRouter.h @@ -19,8 +19,6 @@ extern const CGSize kVNGBannerShortSize; -@class GADMAdapterVungleBannerRequest; - @interface GADMAdapterVungleRouter : NSObject + (nonnull GADMAdapterVungleRouter *)sharedInstance; @@ -39,6 +37,5 @@ extern const CGSize kVNGBannerShortSize; extras:(nullable VungleAdNetworkExtras *)extras forPlacementID:(nonnull NSString *)placementID; - (void)completeBannerAdViewForPlacementID:(nonnull id)delegate; -- (BOOL)canRequestBannerAdForPlacementID:(nonnull GADMAdapterVungleBannerRequest *)bannerRequest; @end diff --git a/adapters/Vungle/VungleAdapter/GADMAdapterVungleRouter.m b/adapters/Vungle/VungleAdapter/GADMAdapterVungleRouter.m index 9eb6bccb1..969d732f2 100644 --- a/adapters/Vungle/VungleAdapter/GADMAdapterVungleRouter.m +++ b/adapters/Vungle/VungleAdapter/GADMAdapterVungleRouter.m @@ -16,10 +16,11 @@ #import "GADMAdapterVungleConstants.h" #import "GADMAdapterVungleUtils.h" #import "VungleRouterConsent.h" -#import "GADMAdapterVungleBannerRequest.h" const CGSize kVNGBannerShortSize = {300, 50}; +static NSString *const _Nonnull kGADMAdapterVungleNullPubRequestID = @"null"; + @implementation GADMAdapterVungleRouter { /// Map table to hold the interstitial or rewarded ad delegates with placement ID as a key. NSMapTable> *_delegates; @@ -28,16 +29,16 @@ @implementation GADMAdapterVungleRouter { NSMapTable> *_initializingDelegates; /// Map table to hold the banner ad delegates with placement ID as a key. - NSMapTable> *_bannerDelegates; - - /// Indicates whether a banner ad is presenting. - BOOL _isBannerPresenting; + NSMapTable> *_bannerDelegates; - /// Vungle's BannerRequest which inclues banner placementID and banner uniquePubRequestID. - GADMAdapterVungleBannerRequest *_bannerRequest; + /// Dictionary to hold the placement ID and uniquePubRequestID for banners are being requested + NSMutableDictionary *_bannerRequestingDict; /// Indicates whether the Vungle SDK is initializing. BOOL _isInitializing; + + /// Vungle's prioritized placementID + NSString *_prioritizedPlacementID; } + (nonnull GADMAdapterVungleRouter *)sharedInstance { @@ -59,6 +60,7 @@ - (id)init { valueOptions:NSPointerFunctionsWeakMemory]; _bannerDelegates = [NSMapTable mapTableWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory]; + _bannerRequestingDict = [NSMutableDictionary dictionary]; } return self; } @@ -93,13 +95,27 @@ - (void)initWithAppId:(nonnull NSString *)appId } _isInitializing = YES; - _isBannerPresenting = NO; //Disable refresh functionality for all banners [[VungleSDK sharedSDK] disableBannerRefresh]; + // Set init options for priority placement + NSMutableDictionary *initOptions = [NSMutableDictionary dictionary]; + if (delegate) { + NSString *priorityPlacementID = delegate.desiredPlacement; + [initOptions setObject:priorityPlacementID forKey:VungleSDKInitOptionKeyPriorityPlacementID]; + _prioritizedPlacementID = [priorityPlacementID copy]; + + NSInteger priorityPlacementAdSize = 1; + GADMAdapterVungleAdType adType = [delegate adapterAdType]; + if (adType == GADMAdapterVungleAdTypeBanner || adType == GADMAdapterVungleAdTypeShortBanner || adType == GADMAdapterVungleAdTypeLeaderboardBanner) { + priorityPlacementAdSize = [self getVungleBannerAdSizeType:adType]; + } + [initOptions setObject:[NSNumber numberWithInteger:priorityPlacementAdSize] forKey:VungleSDKInitOptionKeyPriorityPlacementAdSize]; + } + NSError *err = nil; - [sdk startWithAppId:appId error:&err]; + [sdk startWithAppId:appId options:initOptions error:&err]; if (err) { [self initialized:NO error:err]; } @@ -119,72 +135,48 @@ - (BOOL)isAdCachedForPlacementID:(nonnull NSString *)placementID withDelegate:(n } - (BOOL)addDelegate:(nonnull id)delegate { - if (!delegate) { - return NO; - } - if (delegate.adapterAdType == GADMAdapterVungleAdTypeInterstitial || delegate.adapterAdType == GADMAdapterVungleAdTypeRewarded) { @synchronized(_delegates) { if (![_delegates objectForKey:delegate.desiredPlacement]) { GADMAdapterVungleMapTableSetObjectForKey(_delegates, delegate.desiredPlacement, delegate); + return YES; } } } else if ([delegate respondsToSelector:@selector(isBannerAd)] && [delegate isBannerAd]) { @synchronized(_bannerDelegates) { - // We only support displaying one Vungle Banner Ad at the same time currently - if (_bannerRequest != nil && ![_bannerRequest isEqualToBannerRequest:delegate.bannerRequest]) { - [self checkSamePlacementIDwithNilUniquePubRequestID:delegate.bannerRequest]; - return NO; - } - - if (![_bannerDelegates objectForKey:delegate.bannerRequest]) { - NSEnumerator *enumerator = _bannerDelegates.keyEnumerator; - GADMAdapterVungleBannerRequest *vungleBannerRequest = nil; - while (vungleBannerRequest = [enumerator nextObject]) { - // There is already a banner delegate with same placementID - // but different uniquePubRequestID in _bannerDelegates. - if ([vungleBannerRequest.placementID isEqualToString:delegate.bannerRequest.placementID]) { - return NO; - } else if (vungleBannerRequest.placementID.length > 0 && ![vungleBannerRequest.placementID isEqualToString:delegate.bannerRequest.placementID]) { - // There is already a banner delegate with different placementID in _bannerDelegates. - if (!_bannerRequest) { - _bannerRequest = [vungleBannerRequest copy]; - } - return NO; - } + if (![_bannerDelegates objectForKey:delegate.desiredPlacement] && ![_bannerRequestingDict objectForKey:delegate.desiredPlacement]) { + GADMAdapterVungleMapTableSetObjectForKey(_bannerDelegates, delegate.desiredPlacement, delegate); + GADMAdapterVungleMutableDictionarySetObjectForKey(_bannerRequestingDict, delegate.desiredPlacement, delegate.uniquePubRequestID ? : kGADMAdapterVungleNullPubRequestID); + return YES; + } else if ([_bannerDelegates objectForKey:delegate.desiredPlacement]) { + id bannerDelegate = [_bannerDelegates objectForKey:delegate.desiredPlacement]; + if ([bannerDelegate.uniquePubRequestID isEqualToString:delegate.uniquePubRequestID]){ + /* The isRequestingBannerAdForRefresh flag is used for an edge case, when the old Banner + * delegate is removed from _bannerDelegates and there is a refresh Banner delegate doesn't + * construct Banner view successfully and add to _bannerDelegates yet. Adapter cannot request + * another Banner ad with same placement Id and different uniquePubRequestID. + */ + bannerDelegate.isRequestingBannerAdForRefresh = YES; + delegate.isRefreshedForBannerAd = YES; + return YES; } - GADMAdapterVungleMapTableSetObjectForKey(_bannerDelegates, delegate.bannerRequest, delegate); - _bannerRequest = [delegate.bannerRequest copy]; - } else { - id bannerDelegate = [_bannerDelegates objectForKey:delegate.bannerRequest]; - - /* The isRequestingBannerAdForRefresh flag is used for an edge case, when the old Banner - * delegate is removed from _bannerDelegates and there is a refresh Banner delegate doesn't - * construct Banner view successfully and add to _bannerDelegates yet. Adapter cannot set - * _bannerRequest to nil to prevent requesting another Banner ad with different bannerRequest. - */ - bannerDelegate.isRequestingBannerAdForRefresh = YES; - delegate.isRefreshedForBannerAd = YES; + if (!bannerDelegate.uniquePubRequestID) { + NSLog(@"Ad already loaded for placement ID: %@, and cannot determine if this is a refresh. Set Vungle extras when making an ad request to support refresh on Vungle banner ads.", bannerDelegate.desiredPlacement); + } else { + NSLog(@"Ad already loaded for placement ID: %@", bannerDelegate.desiredPlacement); + } } } } - return YES; + return NO; } - (void)replaceOldBannerDelegateWithDelegate:(nonnull id)delegate { if ([delegate respondsToSelector:@selector(isBannerAd)] && [delegate isBannerAd]) { @synchronized(_bannerDelegates) { - // We only support displaying one Vungle Banner Ad at the same time currently - if (_bannerRequest != nil && ![_bannerRequest isEqualToBannerRequest:delegate.bannerRequest]) { - return; - } - - GADMAdapterVungleMapTableSetObjectForKey(_bannerDelegates, delegate.bannerRequest, delegate); - if (!_bannerRequest) { - _bannerRequest = [delegate.bannerRequest copy]; - } + GADMAdapterVungleMapTableSetObjectForKey(_bannerDelegates, delegate.desiredPlacement, delegate); } } } @@ -195,27 +187,20 @@ - (void)replaceOldBannerDelegateWithDelegate:(nonnull id)getDelegateForPlacement:(nonnull NSString *)placement withBannerRouterDelegateState:(BannerRouterDelegateState)bannerState { id delegate = nil; - if ([placement isEqualToString:_bannerRequest.placementID]) { - @synchronized(_bannerDelegates) { - NSEnumerator *enumerator = _bannerDelegates.keyEnumerator; - GADMAdapterVungleBannerRequest *vungleBannerRequest = nil; - while (vungleBannerRequest = [enumerator nextObject]) { - if ([vungleBannerRequest.placementID isEqualToString:placement]) { - id bannerDelegate = [_bannerDelegates objectForKey:vungleBannerRequest]; - if (bannerDelegate.bannerState == bannerState) { - return bannerDelegate; - } - } - } - } - } else { - @synchronized(_delegates) { - if ([_delegates objectForKey:placement]) { - delegate = [_delegates objectForKey:placement]; + @synchronized(_bannerDelegates) { + if ([_bannerDelegates objectForKey:placement]) { + id bannerDelegate = [_bannerDelegates objectForKey:placement]; + if (bannerDelegate && bannerDelegate.bannerState == bannerState) { + return bannerDelegate; } } } + @synchronized(_delegates) { + if ([_delegates objectForKey:placement]) { + delegate = [_delegates objectForKey:placement]; + } + } return delegate; } @@ -229,12 +214,13 @@ - (void)removeDelegate:(nonnull id)delegate { } } else if ([delegate respondsToSelector:@selector(isBannerAd)] && [delegate isBannerAd]) { @synchronized(_bannerDelegates) { - if (delegate && (delegate == [_bannerDelegates objectForKey:delegate.bannerRequest])) { - GADMAdapterVungleMapTableRemoveObjectForKey(_bannerDelegates, delegate.bannerRequest); + if (delegate && (delegate == [_bannerDelegates objectForKey:delegate.desiredPlacement])) { + GADMAdapterVungleMapTableRemoveObjectForKey(_bannerDelegates, delegate.desiredPlacement); } - if ([delegate.bannerRequest isEqualToBannerRequest:_bannerRequest] || ([delegate.bannerRequest.placementID isEqualToString:_bannerRequest.placementID] && !delegate.bannerRequest.uniquePubRequestID && !_bannerRequest.uniquePubRequestID)) { - if (!_isBannerPresenting && !delegate.isRequestingBannerAdForRefresh) { - _bannerRequest = nil; + NSString *pubRequestID = [_bannerRequestingDict objectForKey:delegate.desiredPlacement]; + if ([pubRequestID isEqualToString:delegate.uniquePubRequestID] || ([pubRequestID isEqualToString:kGADMAdapterVungleNullPubRequestID] && !delegate.uniquePubRequestID)) { + if (!delegate.isRequestingBannerAdForRefresh) { + [_bannerRequestingDict removeObjectForKey:delegate.desiredPlacement]; } } } @@ -261,44 +247,39 @@ - (BOOL)hasDelegateForPlacementID:(nonnull NSString *)placementID return NO; } -- (BOOL)canRequestBannerAdForPlacementID:(nonnull GADMAdapterVungleBannerRequest *)bannerRequest { - @synchronized(_bannerDelegates) { - if (_bannerDelegates.count > 0) { - [self checkSamePlacementIDwithNilUniquePubRequestID:bannerRequest]; - return _bannerRequest == nil || [_bannerRequest isEqualToBannerRequest:bannerRequest]; - } - return YES; - } -} - - (nullable NSError *)loadAd:(nonnull NSString *)placement withDelegate:(nonnull id)delegate { + if (!delegate) { + return GADMAdapterVungleErrorWithCodeAndDescription( + kGADErrorMediationAdapterError, @"Can't load ad when try to add a nil delegate."); + } + id adapterDelegate = [self getDelegateForPlacement:placement]; if (adapterDelegate) { NSError *error = GADMAdapterVungleErrorWithCodeAndDescription( kGADErrorMediationAdapterError, @"Can't request ad if another request is processing."); return error; } + BOOL addSuccessed = [self addDelegate:delegate]; if (!addSuccessed) { - NSError *error = nil; - if (delegate) { - error = GADMAdapterVungleErrorWithCodeAndDescription( - kGADErrorMediationAdapterError, @"A banner ad type has already been " - @"instantiated. Multiple banner ads are not " - @"supported with Vungle iOS SDK."); - } else { - error = GADMAdapterVungleErrorWithCodeAndDescription( - kGADErrorMediationAdapterError, @"Can't load ad when try to add a nil delegate."); - } - return error; + return GADMAdapterVungleErrorWithCodeAndDescription( + kGADErrorMediationAdapterError, @"A banner ad type has already been " + @"instantiated. Multiple banner ads are not " + @"supported with Vungle iOS SDK."); } VungleSDK *sdk = [VungleSDK sharedSDK]; if ([self isAdCachedForPlacementID:placement withDelegate:delegate]) { [delegate adAvailable]; } else { - NSError *loadError; + // We already requested an ad for _prioritizedPlacementID, + // so we don't need to request again. + if ([_prioritizedPlacementID isEqualToString:placement]) { + return nil; + } + + NSError *loadError = nil; GADMAdapterVungleAdType adType = [delegate adapterAdType]; if (adType != GADMAdapterVungleAdTypeBanner && adType != GADMAdapterVungleAdTypeShortBanner && adType != GADMAdapterVungleAdTypeLeaderboardBanner) { if (![sdk loadPlacementWithID:placement error:&loadError]) { @@ -434,15 +415,13 @@ - (void)completeBannerAdViewForPlacementID:(nonnull id delegate = [self getDelegateForPlacement:placementID withBannerRouterDelegateState:BannerRouterDelegateStatePlaying]; - // The delegate is not Interstitial or Rewarded Video Ad - if (!delegate) { - _isBannerPresenting = YES; - } - } + NSLog(@"Vungle: Did show Ad for placement ID:%@", placementID); } -- (void)vungleWillCloseAdWithViewInfo:(nonnull VungleViewInfo *)info - placementID:(nonnull NSString *)placementID { +- (void)vungleWillCloseAdForPlacementID:(nonnull NSString *)placementID { id delegate = [self getDelegateForPlacement:placementID withBannerRouterDelegateState:BannerRouterDelegateStatePlaying]; - [delegate willCloseAd:[info.completedView boolValue] didDownload:[info.didDownload boolValue]]; + [delegate willCloseAd]; } -- (void)vungleDidCloseAdWithViewInfo:(nonnull VungleViewInfo *)info - placementID:(nonnull NSString *)placementID { +- (void)vungleDidCloseAdForPlacementID:(nonnull NSString *)placementID { id delegate = [self getDelegateForPlacement:placementID withBannerRouterDelegateState:BannerRouterDelegateStateClosing]; if (!delegate) { return; } - [delegate didCloseAd:[info.completedView boolValue] didDownload:[info.didDownload boolValue]]; + [delegate didCloseAd]; [self removeDelegate:delegate]; } +- (void)vungleTrackClickForPlacementID:(nullable NSString *)placementID { + id delegate = [self getDelegateForPlacement:placementID + withBannerRouterDelegateState:BannerRouterDelegateStatePlaying]; + [delegate trackClick]; +} + +- (void)vungleRewardUserForPlacementID:(nullable NSString *)placementID { + id delegate = [self getDelegateForPlacement:placementID]; + if (delegate.adapterAdType == GADMAdapterVungleAdTypeRewarded && [delegate respondsToSelector:@selector(rewardUser)]) { + [delegate rewardUser]; + } +} + +- (void)vungleWillLeaveApplicationForPlacementID:(nullable NSString *)placementID { + id delegate = [self getDelegateForPlacement:placementID + withBannerRouterDelegateState:BannerRouterDelegateStatePlaying]; + if ([delegate respondsToSelector:@selector(willLeaveApplication)]) { + [delegate willLeaveApplication]; + } +} + - (void)vungleAdPlayabilityUpdate:(BOOL)isAdPlayable placementID:(nullable NSString *)placementID error:(nullable NSError *)error { diff --git a/adapters/Vungle/VungleAdapter/VungleRouterConfiguration.m b/adapters/Vungle/VungleAdapter/VungleRouterConfiguration.m index ed2b8b989..73f0dd351 100644 --- a/adapters/Vungle/VungleAdapter/VungleRouterConfiguration.m +++ b/adapters/Vungle/VungleAdapter/VungleRouterConfiguration.m @@ -22,6 +22,15 @@ + (void)setPublishIDFV:(BOOL)publish { [VungleSDK setPublishIDFV:publish]; } ++ (void)setCCPAStatus:(GADMAdapterVungleCCPAStatus)ccpaStatus { + VungleCCPAStatus vungleCCPAStatus = (VungleCCPAStatus)ccpaStatus; + [[VungleSDK sharedSDK] updateCCPAStatus:vungleCCPAStatus]; +} + ++ (GADMAdapterVungleCCPAStatus)getCCPAStatus { + return (GADMAdapterVungleCCPAStatus)[[VungleSDK sharedSDK] getCurrentCCPAStatus]; +} + + (void)setMinSpaceForInit:(int)size { if (size >= 0) { [[NSUserDefaults standardUserDefaults] setInteger:size