From 09ea63cde6d1b6053582862fa88343cac1ae7daa Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Thu, 28 Nov 2024 11:17:24 +0200 Subject: [PATCH 01/18] feat: ad view custom renderer prototype --- .../Sources/PrebidAdMobBannerAdapter.swift | 16 +- ...dMAXMediationAdapter+MAAdViewAdapter.swift | 28 ++- .../InternalTestApp.xcodeproj/project.pbxproj | 13 ++ .../Model/TestCasesManager.swift | 4 +- .../SampleCustomAdViewRenderer.swift | 77 ++++++++ .../SampleCustomRenderer.swift | 83 ++++++++ .../CustomRendererBannerController.swift | 17 +- ...CustomRendererInterstitialController.swift | 16 +- .../OpenX/CustomRenderer/SampleAdView.swift | 80 ++++++++ .../SampleCustomAdViewRenderer.swift | 42 ++++ PrebidMobile.xcodeproj/project.pbxproj | 18 +- .../ConfigurationAndTargeting/Prebid.swift | 12 +- .../PluginRenderer/PBMAdViewDelegate.swift | 14 -- .../PrebidMobilePluginRegister.swift | 86 +++++---- .../PrebidMobilePluginRenderer.swift | 77 +++++--- .../PluginRenderer/SampleCustomRenderer.swift | 83 -------- .../AdLoading/BannerAdLoaderDelegate.swift | 5 - .../GAM/AdLoading/PBMAdLoadFlowController.m | 1 + .../GAM/AdLoading/PBMBannerAdLoader.m | 58 ++++-- .../Prebid/Integrations/GAM/BannerView.swift | 180 ++++++++++-------- .../BannerEventHandlerStandalone.swift | 1 + .../DisplayViewInteractionDelegate.swift | 15 +- .../DisplayViewLoadingDelegate.swift | 12 +- .../InterstitialController.swift | 11 +- .../PBMDisplayView+InternalState.h | 4 +- .../Prebid/PBMCacheRenderers/PBMDisplayView.h | 12 +- .../Prebid/PBMCacheRenderers/PBMDisplayView.m | 70 +++++-- .../PrebidBannerRenderer.swift | 150 +++++++++++++++ .../PrebidBannerViewRenderer.swift | 51 +++++ .../PrebidDisplayViewRenderer.swift | 50 +++++ .../PBMCacheRenderers/PrebidRenderer.swift | 119 ------------ .../Prebid/PBMCore/Bid.swift | 47 ++--- .../Prebid/PBMCore/BidResponse.swift | 8 - 33 files changed, 954 insertions(+), 506 deletions(-) create mode 100644 InternalTestApp/PrebidMobileDemoRendering/SampleCustomAdViewRenderer.swift create mode 100644 InternalTestApp/PrebidMobileDemoRendering/SampleCustomRenderer.swift rename InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/{ => OpenX}/CustomRenderer/CustomRendererBannerController.swift (96%) rename InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/{ => OpenX}/CustomRenderer/CustomRendererInterstitialController.swift (94%) create mode 100644 InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/SampleAdView.swift create mode 100644 InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/SampleCustomAdViewRenderer.swift delete mode 100644 PrebidMobile/PrebidMobileRendering/PluginRenderer/PBMAdViewDelegate.swift delete mode 100644 PrebidMobile/PrebidMobileRendering/PluginRenderer/SampleCustomRenderer.swift create mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerRenderer.swift create mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerViewRenderer.swift create mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidDisplayViewRenderer.swift delete mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift diff --git a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobBannerAdapter.swift b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobBannerAdapter.swift index 07822e3f3..836724534 100644 --- a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobBannerAdapter.swift +++ b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobBannerAdapter.swift @@ -83,18 +83,18 @@ public class PrebidAdMobBannerAdapter: displayView?.interactionDelegate = self displayView?.loadingDelegate = self - displayView?.displayAd() + displayView?.loadAd() } // MARK: - DisplayViewLoadingDelegate - public func displayViewDidLoadAd(_ displayView: PBMDisplayView) { + public func displayViewDidLoadAd(_ displayView: UIView) { if let handler = completionHandler { delegate = handler(self, nil) } } - public func displayView(_ displayView: PBMDisplayView, didFailWithError error: Error) { + public func displayView(_ displayView: UIView, didFailWithError error: Error) { if let handler = completionHandler { delegate = handler(nil, error) } @@ -102,23 +102,23 @@ public class PrebidAdMobBannerAdapter: // MARK: - PBMDisplayViewInteractionDelegate - public func trackImpression(forDisplayView: PBMDisplayView) { + public func trackImpression(for displayView: UIView) { delegate?.reportImpression() } - public func viewControllerForModalPresentation(fromDisplayView: PBMDisplayView) -> UIViewController? { + public func viewControllerForModalPresentation(from displayView: UIView) -> UIViewController? { return adConfiguration?.topViewController ?? UIApplication.shared.windows.first?.rootViewController } - public func didLeaveApp(from displayView: PBMDisplayView) { + public func didLeaveApp(from displayView: UIView) { delegate?.reportClick() } - public func willPresentModal(from displayView: PBMDisplayView) { + public func willPresentModal(from displayView: UIView) { delegate?.willPresentFullScreenView() } - public func didDismissModal(from displayView: PBMDisplayView) { + public func didDismissModal(from displayView: UIView) { delegate?.willDismissFullScreenView() delegate?.didDismissFullScreenView() } diff --git a/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAAdViewAdapter.swift b/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAAdViewAdapter.swift index 67cb939a0..0e06c6efc 100644 --- a/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAAdViewAdapter.swift +++ b/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAAdViewAdapter.swift @@ -17,7 +17,10 @@ import Foundation import PrebidMobile import AppLovinSDK -extension PrebidMAXMediationAdapter: MAAdViewAdapter, DisplayViewLoadingDelegate, DisplayViewInteractionDelegate { +extension PrebidMAXMediationAdapter: + MAAdViewAdapter, + DisplayViewLoadingDelegate, + DisplayViewInteractionDelegate { // MARK: - MAAdViewAdapter @@ -59,41 +62,36 @@ extension PrebidMAXMediationAdapter: MAAdViewAdapter, DisplayViewLoadingDelegate displayView?.interactionDelegate = self displayView?.loadingDelegate = self - displayView?.displayAd() + displayView?.loadAd() } // MARK: - DisplayViewLoadingDelegate - public func displayViewDidLoadAd(_ displayView: PBMDisplayView) { + public func displayViewDidLoadAd(_ displayView: UIView) { bannerDelegate?.didLoadAd(forAdView: displayView) } - public func displayView(_ displayView: PBMDisplayView, didFailWithError error: Error) { + public func displayView(_ displayView: UIView, didFailWithError error: Error) { let maError = MAAdapterError(nsError: error) bannerDelegate?.didFailToLoadAdViewAdWithError(maError) } // MARK: DisplayViewInteractionDelegate - public func trackImpression(forDisplayView: PBMDisplayView) { - - } - - public func viewControllerForModalPresentation(fromDisplayView: PBMDisplayView) -> UIViewController? { + public func viewControllerForModalPresentation(from displayView: UIView) -> UIViewController? { return UIApplication.shared.windows.first?.rootViewController } - public func didLeaveApp(from displayView: PBMDisplayView) { - - } - - public func willPresentModal(from displayView: PBMDisplayView) { + public func willPresentModal(from displayView: UIView) { bannerDelegate?.didClickAdViewAd() bannerDelegate?.didExpandAdViewAd() } - public func didDismissModal(from displayView: PBMDisplayView) { + public func didDismissModal(from displayView: UIView) { bannerDelegate?.didHideAdViewAd() bannerDelegate?.didCollapseAdViewAd() } + + public func trackImpression(for displayView: UIView) {} + public func didLeaveApp(from displayView: UIView) {} } diff --git a/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj b/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj index 9b7ee2550..704df261d 100644 --- a/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj +++ b/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj @@ -51,6 +51,10 @@ 53A369092AB996EF00A03B3E /* PrebidMultiformatConfigurationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A369072AB996EF00A03B3E /* PrebidMultiformatConfigurationController.swift */; }; 53A651842AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A651832AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift */; }; 53A651852AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A651832AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift */; }; + 53BFCD032CF792FB00A3287A /* SampleCustomAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD022CF792FB00A3287A /* SampleCustomAdViewRenderer.swift */; }; + 53BFCD042CF792FB00A3287A /* SampleCustomAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD022CF792FB00A3287A /* SampleCustomAdViewRenderer.swift */; }; + 53BFCD0C2CF8F56300A3287A /* SampleAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */; }; + 53BFCD0D2CF8F56300A3287A /* SampleAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */; }; 53ED2FD329798104007D13EE /* LogInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D70F6A24E546DD0048CC78 /* LogInfo.swift */; }; 53ED2FD429798104007D13EE /* PrebidOriginalAPINativeController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5397BD2D2937821D00ABDA22 /* PrebidOriginalAPINativeController.swift */; }; 53ED2FD529798104007D13EE /* AdapterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6EB3CC211336D300317ED9 /* AdapterViewController.swift */; }; @@ -394,6 +398,8 @@ 53A369042AB98F9700A03B3E /* PrebidOriginalAPIMultiformatInAppNativeController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidOriginalAPIMultiformatInAppNativeController.swift; sourceTree = ""; }; 53A369072AB996EF00A03B3E /* PrebidMultiformatConfigurationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidMultiformatConfigurationController.swift; sourceTree = ""; }; 53A651832AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidOriginalAPIMultiformatNativeStylesController.swift; sourceTree = ""; }; + 53BFCD022CF792FB00A3287A /* SampleCustomAdViewRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleCustomAdViewRenderer.swift; sourceTree = ""; }; + 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAdView.swift; sourceTree = ""; }; 53ED304329798104007D13EE /* InternalTestApp-Skadn.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "InternalTestApp-Skadn.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 53ED305129798DBC007D13EE /* Info-Skadn.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Skadn.plist"; sourceTree = ""; }; 5B03D44524F5455F002F2B35 /* PBMGAMBannerEventHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PBMGAMBannerEventHandlerTests.swift; sourceTree = ""; }; @@ -669,6 +675,7 @@ 3493022024740BD8004A6086 /* OpenX */ = { isa = PBXGroup; children = ( + 3CC4A3E72C11F93A00B97128 /* CustomRenderer */, 3493022124740BEE004A6086 /* PrebidBannerController.swift */, 34FC0CF324ADD3A80045553E /* PrebidInterstitialController.swift */, 34BA95FF249CC118006AE372 /* PrebidRewardedController.swift */, @@ -701,6 +708,8 @@ 3CC4A3E72C11F93A00B97128 /* CustomRenderer */ = { isa = PBXGroup; children = ( + 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */, + 53BFCD022CF792FB00A3287A /* SampleCustomAdViewRenderer.swift */, 3CC4A3E82C11F96800B97128 /* CustomRendererBannerController.swift */, 3C28C9D72C35713B00D0A7DB /* CustomRendererInterstitialController.swift */, ); @@ -1572,6 +1581,7 @@ 53ED2FE829798104007D13EE /* PrebidBannerController.swift in Sources */, 53ED2FE929798104007D13EE /* PrebidBannerConfigurationController.swift in Sources */, 53ED2FEA29798104007D13EE /* TestCase.swift in Sources */, + 53BFCD032CF792FB00A3287A /* SampleCustomAdViewRenderer.swift in Sources */, 53ED2FEB29798104007D13EE /* PrebidAdMobNativeViewController.swift in Sources */, 53ED2FEC29798104007D13EE /* PrebidInterstitialController.swift in Sources */, 53ED2FED29798104007D13EE /* PrebidOriginalAPIDisplayInterstitialController.swift in Sources */, @@ -1616,6 +1626,7 @@ 53ED301129798104007D13EE /* AppConfiguration.swift in Sources */, 53ED301229798104007D13EE /* ReactiveSdkInitFlag.swift in Sources */, 53ED301329798104007D13EE /* PrebidOriginalAPINativeBannerController.swift in Sources */, + 53BFCD0C2CF8F56300A3287A /* SampleAdView.swift in Sources */, 53ED301429798104007D13EE /* TestCasesSectionsViewController.swift in Sources */, 3C28C9D92C35713B00D0A7DB /* CustomRendererInterstitialController.swift in Sources */, 53ED301529798104007D13EE /* AppSettingsKeys.swift in Sources */, @@ -1668,6 +1679,7 @@ 3493022224740BEE004A6086 /* PrebidBannerController.swift in Sources */, 5BDB85DA2739794900A529F6 /* PrebidBannerConfigurationController.swift in Sources */, 5B3EEDE52101FB8800BAA0C4 /* TestCase.swift in Sources */, + 53BFCD042CF792FB00A3287A /* SampleCustomAdViewRenderer.swift in Sources */, 92C475122796FF8400C26E27 /* PrebidAdMobNativeViewController.swift in Sources */, 34FC0CF424ADD3A80045553E /* PrebidInterstitialController.swift in Sources */, 5397BD26293760F500ABDA22 /* PrebidOriginalAPIDisplayInterstitialController.swift in Sources */, @@ -1712,6 +1724,7 @@ D551B96F21491AAA00FFF51D /* AppConfiguration.swift in Sources */, 346C6F5725DFAB7E00457DD3 /* ReactiveSdkInitFlag.swift in Sources */, 5397BD2C2937764100ABDA22 /* PrebidOriginalAPINativeBannerController.swift in Sources */, + 53BFCD0D2CF8F56300A3287A /* SampleAdView.swift in Sources */, 5B3EEDE22101EDA200BAA0C4 /* TestCasesSectionsViewController.swift in Sources */, 3C28C9D82C35713B00D0A7DB /* CustomRendererInterstitialController.swift in Sources */, ACC41ACD2444EADB00B9A3A7 /* AppSettingsKeys.swift in Sources */, diff --git a/InternalTestApp/PrebidMobileDemoRendering/Model/TestCasesManager.swift b/InternalTestApp/PrebidMobileDemoRendering/Model/TestCasesManager.swift index f05b106ae..58b485eb2 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/Model/TestCasesManager.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/Model/TestCasesManager.swift @@ -593,9 +593,7 @@ struct TestCaseManager { let bannerController = CustomRendererBannerController(rootController: adapterVC) bannerController.adSizes = [CGSize(width: 320, height: 50)] - - bannerController.prebidConfigId = "prebid-ita-banner-320-50-meta-custom-renderer"; - + bannerController.prebidConfigId = "prebid-ita-banner-320-50-meta-custom-banner-view-renderer" adapterVC.setup(adapter: bannerController) setupCustomParams(for: bannerController.prebidConfigId) diff --git a/InternalTestApp/PrebidMobileDemoRendering/SampleCustomAdViewRenderer.swift b/InternalTestApp/PrebidMobileDemoRendering/SampleCustomAdViewRenderer.swift new file mode 100644 index 000000000..5651447b8 --- /dev/null +++ b/InternalTestApp/PrebidMobileDemoRendering/SampleCustomAdViewRenderer.swift @@ -0,0 +1,77 @@ +/*   Copyright 2018-2021 Prebid.org, Inc. + + 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 UIKit +import PrebidMobile + +public class SampleCustomBannerViewRenderer: NSObject, PrebidMobilePluginRenderer { + + public let name = "SampleCustomBannerViewRenderer" + public let version = "1.0.0" + public var data: [AnyHashable: Any]? + + public func isSupportRendering(for format: AdFormat?) -> Bool { + AdFormat.allCases.contains(where: { $0 == format }) + } + + private weak var loadingDelegate: DisplayViewLoadingDelegate? + private weak var interactionDelegate: DisplayViewInteractionDelegate? + private weak var currentAdView: UIView? + + public func createBannerAdView( + with frame: CGRect, + bid: Bid, + adConfiguration: AdUnitConfig, + connection: PrebidServerConnectionProtocol, + loadingDelegate: DisplayViewLoadingDelegate?, + interactionDelegate: DisplayViewInteractionDelegate? + ) -> UIView { + + self.interactionDelegate = interactionDelegate + self.loadingDelegate = loadingDelegate + + let bannerView = UIView(frame: frame) + + let label = UILabel() + label.text = "Prebid SDK - Custom Renderer" + label.textAlignment = .center + label.textColor = .black + label.backgroundColor = .yellow + label.translatesAutoresizingMaskIntoConstraints = false + + bannerView.addSubview(label) + + NSLayoutConstraint.activate([ + label.centerXAnchor.constraint(equalTo: bannerView.centerXAnchor), + label.centerYAnchor.constraint(equalTo: bannerView.centerYAnchor), + label.widthAnchor.constraint(equalTo: bannerView.widthAnchor), + label.heightAnchor.constraint(equalTo: bannerView.heightAnchor) + ]) + + currentAdView = bannerView + + loadingDelegate?.displayViewDidLoadAd(bannerView) + + return bannerView + } + + public func createInterstitialController( + bid: Bid, + adConfiguration: AdUnitConfig, + connection: PrebidServerConnectionProtocol, + adViewManagerDelegate adViewDelegate: InterstitialController?, + videoControlsConfig: VideoControlsConfiguration? + ) {} +} diff --git a/InternalTestApp/PrebidMobileDemoRendering/SampleCustomRenderer.swift b/InternalTestApp/PrebidMobileDemoRendering/SampleCustomRenderer.swift new file mode 100644 index 000000000..155d14b3c --- /dev/null +++ b/InternalTestApp/PrebidMobileDemoRendering/SampleCustomRenderer.swift @@ -0,0 +1,83 @@ +/*   Copyright 2018-2021 Prebid.org, Inc. + + 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 UIKit +import PrebidMobile + +public class SampleCustomAdViewRenderer: NSObject, PrebidMobilePluginRenderer { + + public let name = "SampleCustomRenderer" + public let version = "1.0.0" + public var data: [AnyHashable: Any]? + + public func isSupportRendering(for format: AdFormat?) -> Bool { + AdFormat.allCases.contains(where: { $0 == format }) + } + + private weak var loadingDelegate: DisplayViewLoadingDelegate? + private weak var interactionDelegate: DisplayViewInteractionDelegate? + private weak var currentAdView: UIView? + + public func createBannerAdView( + with frame: CGRect, + bid: Bid, + adConfiguration: AdUnitConfig, + connection: PrebidServerConnectionProtocol, + loadingDelegate: DisplayViewLoadingDelegate?, + interactionDelegate: DisplayViewInteractionDelegate? + ) -> UIView { + + self.interactionDelegate = interactionDelegate + self.loadingDelegate = loadingDelegate + + let bannerView = UIView(frame: frame) + + let label = UILabel() + label.text = "Prebid SDK - Custom Renderer" + label.textAlignment = .center + label.textColor = .black + label.backgroundColor = .yellow + label.translatesAutoresizingMaskIntoConstraints = false + + bannerView.addSubview(label) + + NSLayoutConstraint.activate([ + label.centerXAnchor.constraint(equalTo: bannerView.centerXAnchor), + label.centerYAnchor.constraint(equalTo: bannerView.centerYAnchor), + label.widthAnchor.constraint(equalTo: bannerView.widthAnchor), + label.heightAnchor.constraint(equalTo: bannerView.heightAnchor) + ]) + + currentAdView = bannerView + + loadingDelegate?.displayViewDidLoadAd(bannerView) + + return bannerView + } + + public func createInterstitialController( + bid: Bid, + adConfiguration: AdUnitConfig, + connection: PrebidServerConnectionProtocol, + adViewManagerDelegate adViewDelegate: InterstitialController?, + videoControlsConfig: VideoControlsConfiguration? + ) {} + + public func setupBid( + _ bid: Bid, + adConfiguration: AdUnitConfig, + connection: PrebidServerConnectionProtocol + ) {} +} diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/CustomRenderer/CustomRendererBannerController.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererBannerController.swift similarity index 96% rename from InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/CustomRenderer/CustomRendererBannerController.swift rename to InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererBannerController.swift index 8370e7b31..efed8e37d 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/CustomRenderer/CustomRendererBannerController.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererBannerController.swift @@ -16,7 +16,11 @@ import UIKit import PrebidMobile -class CustomRendererBannerController: NSObject, AdaptedController, PrebidConfigurableBannerController, BannerViewDelegate { +class CustomRendererBannerController: + NSObject, + AdaptedController, + PrebidConfigurableBannerController, + BannerViewDelegate { var refreshInterval: TimeInterval = 0 @@ -39,7 +43,7 @@ class CustomRendererBannerController: NSObject, AdaptedController, PrebidConfigu private let reloadButton = ThreadCheckingButton() private let stopRefreshButton = ThreadCheckingButton() - private let sampleCustomRenderer = SampleCustomRenderer() + private let sampleCustomRenderer = SampleCustomAdViewRenderer() let lastLoadedAdSizeLabel = UILabel() private let configIdLabel = UILabel() @@ -47,6 +51,7 @@ class CustomRendererBannerController: NSObject, AdaptedController, PrebidConfigu required init(rootController: AdapterViewController) { super.init() self.rootController = rootController + Prebid.registerPluginRenderer(sampleCustomRenderer) reloadButton.addTarget(self, action: #selector(reload), for: .touchUpInside) @@ -70,9 +75,11 @@ class CustomRendererBannerController: NSObject, AdaptedController, PrebidConfigu let size = adSizes[0] - adBannerView = BannerView(frame: CGRect(origin: .zero, size: size), - configID: prebidConfigId, - adSize: size) + adBannerView = BannerView( + frame: CGRect(origin: .zero, size: size), + configID: prebidConfigId, + adSize: size + ) if (refreshInterval > 0) { adBannerView?.refreshInterval = refreshInterval diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/CustomRenderer/CustomRendererInterstitialController.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererInterstitialController.swift similarity index 94% rename from InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/CustomRenderer/CustomRendererInterstitialController.swift rename to InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererInterstitialController.swift index 42d8d7058..dd6b83da4 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/CustomRenderer/CustomRendererInterstitialController.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererInterstitialController.swift @@ -17,8 +17,11 @@ import UIKit import GoogleMobileAds import PrebidMobile -class CustomRendererInterstitialController: NSObject, AdaptedController, - PrebidConfigurableController, InterstitialAdUnitDelegate { +class CustomRendererInterstitialController: + NSObject, + AdaptedController, + PrebidConfigurableController, + InterstitialAdUnitDelegate { var prebidConfigId = "" var storedAuctionResponse: String? @@ -26,6 +29,7 @@ class CustomRendererInterstitialController: NSObject, AdaptedController, var adFormats: Set? private var interstitialController : InterstitialRenderingAdUnit? + private let sampleCustomRenderer = SampleCustomAdViewRenderer() private weak var adapterViewController: AdapterViewController? @@ -35,7 +39,6 @@ class CustomRendererInterstitialController: NSObject, AdaptedController, private let interstitialDidDismissAdButton = EventReportContainer() private let interstitialWillLeaveApplicationButton = EventReportContainer() private let interstitialDidClickAdButton = EventReportContainer() - private let sampleCustomRenderer = SampleCustomRenderer() private let configIdLabel = UILabel() @@ -74,8 +77,11 @@ class CustomRendererInterstitialController: NSObject, AdaptedController, Prebid.shared.storedAuctionResponse = storedAuctionResponse } - interstitialController = InterstitialRenderingAdUnit(configID: prebidConfigId, - minSizePercentage: CGSize(width: 30, height: 30)) + interstitialController = InterstitialRenderingAdUnit( + configID: prebidConfigId, + minSizePercentage: CGSize(width: 30, height: 30) + ) + interstitialController?.delegate = self // Custom video configuarion diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/SampleAdView.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/SampleAdView.swift new file mode 100644 index 000000000..873204418 --- /dev/null +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/SampleAdView.swift @@ -0,0 +1,80 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 UIKit +import WebKit +import PrebidMobile + +class SampleAdView: UIView { + + weak var interactionDelegate: DisplayViewInteractionDelegate? + weak var loadingDelegate: DisplayViewLoadingDelegate? + + private let webView: WKWebView = { + let webView = WKWebView() + webView.translatesAutoresizingMaskIntoConstraints = false + return webView + }() + + private let customRendererLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.text = "Custom Renderer" + label.textColor = .white + label.font = UIFont.boldSystemFont(ofSize: 10) + label.backgroundColor = UIColor.black.withAlphaComponent(0.5) + label.textAlignment = .center + label.layer.cornerRadius = 5 + label.layer.masksToBounds = true + label.numberOfLines = 0 + return label + }() + + override init(frame: CGRect) { + super.init(frame: frame) + setupView() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupView() + } + + func displayAd(_ bid: Bid) { + if let adm = bid.adm { + webView.loadHTMLString(adm, baseURL: nil) + loadingDelegate?.displayViewDidLoadAd(self) + } else { + print("Error displaying an ad: No ADM data found in bid response.") + } + } + + private func setupView() { + addSubview(webView) + addSubview(customRendererLabel) + + NSLayoutConstraint.activate([ + webView.topAnchor.constraint(equalTo: topAnchor), + webView.leadingAnchor.constraint(equalTo: leadingAnchor), + webView.trailingAnchor.constraint(equalTo: trailingAnchor), + webView.bottomAnchor.constraint(equalTo: bottomAnchor), + + customRendererLabel.topAnchor.constraint(equalTo: topAnchor, constant: 5), + customRendererLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 10), + customRendererLabel.heightAnchor.constraint(equalToConstant: 40), + customRendererLabel.widthAnchor.constraint(equalToConstant: 50) + ]) + } +} diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/SampleCustomAdViewRenderer.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/SampleCustomAdViewRenderer.swift new file mode 100644 index 000000000..ef293f6be --- /dev/null +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/SampleCustomAdViewRenderer.swift @@ -0,0 +1,42 @@ +/*   Copyright 2018-2021 Prebid.org, Inc. + + 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 UIKit +import PrebidMobile + +public class SampleCustomAdViewRenderer: NSObject, PrebidMobileAdViewPluginRenderer { + + public let name = "SampleCustomAdViewRenderer" + public let version = "1.0.0" + public var data: [AnyHashable: Any]? + + public func isSupportRendering(for format: AdFormat?) -> Bool { + AdFormat.allCases.contains(where: { $0 == format }) + } + + public func createAdView( + with frame: CGRect, + bid: Bid, + adConfiguration: AdUnitConfig, + loadingDelegate: DisplayViewLoadingDelegate?, + interactionDelegate: DisplayViewInteractionDelegate? + ) -> UIView { + let bannerView = SampleAdView(frame: frame) + bannerView.interactionDelegate = interactionDelegate + bannerView.loadingDelegate = loadingDelegate + bannerView.displayAd(bid) + return bannerView + } +} diff --git a/PrebidMobile.xcodeproj/project.pbxproj b/PrebidMobile.xcodeproj/project.pbxproj index 38eb9de04..133361aa3 100644 --- a/PrebidMobile.xcodeproj/project.pbxproj +++ b/PrebidMobile.xcodeproj/project.pbxproj @@ -807,10 +807,8 @@ 9743CB86235F264B002E2CAA /* NativeEventTrackerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9743CB85235F264B002E2CAA /* NativeEventTrackerTests.swift */; }; A908694229E05EAF00B37479 /* PrebidMobilePluginRegister.swift in Sources */ = {isa = PBXBuildFile; fileRef = A908694129E05EAF00B37479 /* PrebidMobilePluginRegister.swift */; }; A908694429E05ED500B37479 /* PrebidMobilePluginRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A908694329E05ED500B37479 /* PrebidMobilePluginRenderer.swift */; }; - A908694629E05F7900B37479 /* PrebidRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A908694529E05F7900B37479 /* PrebidRenderer.swift */; }; + A908694629E05F7900B37479 /* PrebidDisplayViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A908694529E05F7900B37479 /* PrebidDisplayViewRenderer.swift */; }; A9750D7A2ABB9A300066E4E6 /* PluginEventListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9750D792ABB9A300066E4E6 /* PluginEventListener.swift */; }; - A9A3396B2AC57193006AD0E7 /* PBMAdViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9A3396A2AC57193006AD0E7 /* PBMAdViewDelegate.swift */; }; - F95DA2072C87567D0068A2BB /* SampleCustomRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F95DA2062C87567D0068A2BB /* SampleCustomRenderer.swift */; }; FA5AD5E42271FA4100C8F274 /* ConstantsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA5AD5E32271FA4100C8F274 /* ConstantsTest.swift */; }; FA9D7F2722E8A83D006FCBEF /* AdViewUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA9D7F2622E8A83D006FCBEF /* AdViewUtilsTests.swift */; }; FAA29904242D1C27002ACBF2 /* TargetingObjCTests.m in Sources */ = {isa = PBXBuildFile; fileRef = FAA29903242D1C27002ACBF2 /* TargetingObjCTests.m */; }; @@ -1730,10 +1728,8 @@ 979177962201AF5F00E624CE /* DispatcherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DispatcherTests.swift; sourceTree = ""; }; A908694129E05EAF00B37479 /* PrebidMobilePluginRegister.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidMobilePluginRegister.swift; sourceTree = ""; }; A908694329E05ED500B37479 /* PrebidMobilePluginRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidMobilePluginRenderer.swift; sourceTree = ""; }; - A908694529E05F7900B37479 /* PrebidRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidRenderer.swift; sourceTree = ""; }; + A908694529E05F7900B37479 /* PrebidDisplayViewRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidDisplayViewRenderer.swift; sourceTree = ""; }; A9750D792ABB9A300066E4E6 /* PluginEventListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PluginEventListener.swift; sourceTree = ""; }; - A9A3396A2AC57193006AD0E7 /* PBMAdViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PBMAdViewDelegate.swift; sourceTree = ""; }; - F95DA2062C87567D0068A2BB /* SampleCustomRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SampleCustomRenderer.swift; sourceTree = ""; }; FA4A88432497A99D00FDCBB6 /* Swizzling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Swizzling.swift; sourceTree = ""; }; FA5AD5E32271FA4100C8F274 /* ConstantsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConstantsTest.swift; sourceTree = ""; }; FA85F9B4264946FC00B8BE72 /* TestUtils.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = TestUtils.xcodeproj; path = ../tools/TestUtils/TestUtils.xcodeproj; sourceTree = ""; }; @@ -2436,15 +2432,15 @@ 5BC37786271F1CFE00444D5E /* PBMCacheRenderers */ = { isa = PBXGroup; children = ( + 5BC3778C271F1CFE00444D5E /* PBMDisplayView.h */, 5BC37787271F1CFE00444D5E /* PBMDisplayView.m */, 5BC37788271F1CFE00444D5E /* PBMDisplayView+InternalState.h */, 5BC3778B271F1CFE00444D5E /* InterstitialControllerLoadingDelegate.swift */, - 5BC3778C271F1CFE00444D5E /* PBMDisplayView.h */, 5BC3778D271F1CFE00444D5E /* InterstitialControllerInteractionDelegate.swift */, 5BC3778E271F1CFE00444D5E /* InterstitialController.swift */, 5BC3778F271F1CFE00444D5E /* DisplayViewLoadingDelegate.swift */, 5BC37790271F1CFE00444D5E /* DisplayViewInteractionDelegate.swift */, - A908694529E05F7900B37479 /* PrebidRenderer.swift */, + A908694529E05F7900B37479 /* PrebidDisplayViewRenderer.swift */, ); path = PBMCacheRenderers; sourceTree = ""; @@ -3276,11 +3272,9 @@ A908694029E05E8D00B37479 /* PluginRenderer */ = { isa = PBXGroup; children = ( - F95DA2062C87567D0068A2BB /* SampleCustomRenderer.swift */, A908694129E05EAF00B37479 /* PrebidMobilePluginRegister.swift */, A908694329E05ED500B37479 /* PrebidMobilePluginRenderer.swift */, A9750D792ABB9A300066E4E6 /* PluginEventListener.swift */, - A9A3396A2AC57193006AD0E7 /* PBMAdViewDelegate.swift */, ); path = PluginRenderer; sourceTree = ""; @@ -4104,7 +4098,6 @@ FAEE4D20262DC2B200AD9966 /* Signals.swift in Sources */, 5BC37A79271F1D0000444D5E /* PBMVastTransactionFactory.m in Sources */, 5BC37911271F1CFF00444D5E /* PBMDeepLinkPlus.m in Sources */, - A9A3396B2AC57193006AD0E7 /* PBMAdViewDelegate.swift in Sources */, 5BC378DD271F1CFF00444D5E /* PBMORTBPmp.m in Sources */, 5BC378CE271F1CFF00444D5E /* PBMTouchDownRecognizer.m in Sources */, 5BC378ED271F1CFF00444D5E /* PBMORTBAppExtPrebid.m in Sources */, @@ -4270,7 +4263,6 @@ 537B6518283372FD008AE9D1 /* PathBuilder.swift in Sources */, FAEE4D1A262DC2B200AD9966 /* NativeAd.swift in Sources */, 5BC37A1B271F1D0000444D5E /* Prebid.swift in Sources */, - F95DA2072C87567D0068A2BB /* SampleCustomRenderer.swift in Sources */, 5BC379A8271F1D0000444D5E /* PBMModalViewController.m in Sources */, 5BC37AC3271F1D0100444D5E /* PBMURLComponents.m in Sources */, 5BC378D3271F1CFF00444D5E /* PBMORTBAbstract.m in Sources */, @@ -4348,7 +4340,7 @@ 5BC37A8B271F1D0000444D5E /* BannerEventInteractionDelegate.swift in Sources */, FAEE4D0B262DC2B200AD9966 /* Dispatcher.swift in Sources */, 5BC37A10271F1D0000444D5E /* AdUnitConfig.swift in Sources */, - A908694629E05F7900B37479 /* PrebidRenderer.swift in Sources */, + A908694629E05F7900B37479 /* PrebidDisplayViewRenderer.swift in Sources */, 5BC37926271F1CFF00444D5E /* PBMDeepLinkPlusHelper+Testing.m in Sources */, 5BC37A90271F1D0000444D5E /* InterstitialAdUnitDelegate.swift in Sources */, 5BC37A88271F1D0000444D5E /* RewardedAdUnitDelegate.swift in Sources */, diff --git a/PrebidMobile/ConfigurationAndTargeting/Prebid.swift b/PrebidMobile/ConfigurationAndTargeting/Prebid.swift index db6438197..f93c18202 100644 --- a/PrebidMobile/ConfigurationAndTargeting/Prebid.swift +++ b/PrebidMobile/ConfigurationAndTargeting/Prebid.swift @@ -258,15 +258,15 @@ public class Prebid: NSObject { timeoutMillis = defaultTimeoutMillis } - public static func registerPluginRenderer(_ prebidMobilePluginRenderer: PrebidMobilePluginRenderer) { - PrebidMobilePluginRegister.shared.registerPlugin(prebidMobilePluginRenderer); + public static func registerPluginRenderer(_ pluginRenderer: PrebidMobilePluginRenderer) { + PrebidMobilePluginRegister.shared.registerPlugin(pluginRenderer) } - public static func unregisterPluginRenderer(_ prebidMobilePluginRenderer: PrebidMobilePluginRenderer) { - PrebidMobilePluginRegister.shared.unregisterPlugin(prebidMobilePluginRenderer); + public static func unregisterPluginRenderer(_ pluginRenderer: PrebidMobilePluginRenderer) { + PrebidMobilePluginRegister.shared.unregisterPlugin(pluginRenderer) } - public static func containsPluginRenderer(_ prebidMobilePluginRenderer: PrebidMobilePluginRenderer) { - PrebidMobilePluginRegister.shared.containsPlugin(prebidMobilePluginRenderer); + public static func containsPluginRenderer(_ pluginRenderer: PrebidMobilePluginRenderer) -> Bool { + PrebidMobilePluginRegister.shared.containsPlugin(pluginRenderer) } } diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PBMAdViewDelegate.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PBMAdViewDelegate.swift deleted file mode 100644 index 93ccf278f..000000000 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PBMAdViewDelegate.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// PBMAdViewDelegate.swift -// PrebidMobile -// -// Created by Paul NICOLAS on 28/09/2023. -// Copyright © 2023 AppNexus. All rights reserved. -// - -import UIKit - -@objc public protocol PBMThirdPartyAdViewLoader: NSObjectProtocol { -} - -public typealias PBMAdViewDelegate = PBMThirdPartyAdViewLoader & PBMAdViewManagerDelegate & PBMModalManagerDelegate diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift index ef41871b1..a0294150e 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift @@ -1,35 +1,41 @@ /*   Copyright 2018-2021 Prebid.org, Inc. - - 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. - */ + +  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 Foundation /// Global singleton responsible to store plugin renderer instances -@objc public class PrebidMobilePluginRegister: NSObject { - @objc public static let shared = PrebidMobilePluginRegister() +@objcMembers +public class PrebidMobilePluginRegister: NSObject { + + public static let shared = PrebidMobilePluginRegister() + + private let queue = DispatchQueue( + label: "PrebidMobilePluginRegisterQueue", + attributes: .concurrent + ) - private let queue = DispatchQueue(label: "PrebidMobilePluginRegisterQueue", attributes: .concurrent) private var plugins = [String: PrebidMobilePluginRenderer]() - private let defaultRenderer = PrebidRenderer() + private let defaultRenderer = PrebidDisplayViewRenderer() private override init() { super.init() } /// Register plugin as renderer - @objc public func registerPlugin(_ renderer: PrebidMobilePluginRenderer) { + public func registerPlugin(_ renderer: PrebidMobilePluginRenderer) { let rendererName = renderer.name queue.async(flags: .barrier) { [weak self] in @@ -41,49 +47,59 @@ import Foundation } } - @objc public func unregisterPlugin(_ renderer: PrebidMobilePluginRenderer) { + public func unregisterPlugin(_ renderer: PrebidMobilePluginRenderer) { queue.async(flags: .barrier) { [weak self] in self?.plugins.removeValue(forKey: renderer.name) } } /// Contains plugin - @objc public func containsPlugin(_ renderer: PrebidMobilePluginRenderer) -> Bool { + public func containsPlugin(_ renderer: PrebidMobilePluginRenderer) -> Bool { queue.sync { plugins.contains { $0.value === renderer } } } private func getPluginRenderer(for key: String) -> PrebidMobilePluginRenderer? { - queue.sync { - plugins[key] - } + queue.sync { plugins[key] } } /// Register event delegate - @objc public func registerEventDelegate(_ pluginEventDelegate: PluginEventDelegate, adUnitConfigFingerprint: String) { + public func registerEventDelegate( + _ pluginEventDelegate: PluginEventDelegate, + adUnitConfigFingerprint: String + ) { queue.async(flags: .barrier) { [plugins] in plugins .values .forEach { - $0.registerEventDelegate?(pluginEventDelegate: pluginEventDelegate, adUnitConfigFingerprint: adUnitConfigFingerprint) + $0.registerEventDelegate?( + pluginEventDelegate: pluginEventDelegate, + adUnitConfigFingerprint: adUnitConfigFingerprint + ) } } } /// Unregister event delegate - @objc public func unregisterEventDelegate(_ pluginEventDelegate: PluginEventDelegate, adUnitConfigFingerprint: String) { + public func unregisterEventDelegate( + _ pluginEventDelegate: PluginEventDelegate, + adUnitConfigFingerprint: String + ) { queue.async(flags: .barrier) { [plugins] in plugins .values .forEach { - $0.unregisterEventDelegate?(pluginEventDelegate: pluginEventDelegate, adUnitConfigFingerprint: adUnitConfigFingerprint) + $0.unregisterEventDelegate?( + pluginEventDelegate: pluginEventDelegate, + adUnitConfigFingerprint: adUnitConfigFingerprint + ) } } } /// Returns the list of available renderers for the given ad unit for RTB request - @objc public func getRTBListOfRenderersFor(for adUnit: AdUnitConfig) -> [PrebidMobilePluginRenderer] { + public func getRTBListOfRenderersFor(for adUnit: AdUnitConfig) -> [PrebidMobilePluginRenderer] { queue.sync { plugins .values @@ -98,10 +114,10 @@ import Foundation /// Returns the registered renderer according to the preferred renderer name in the bid response /// If no preferred renderer is found, it returns PrebidRenderer to perform default behavior /// Once bid is win we want to resolve the best PluginRenderer candidate to render the ad - @objc public func getPluginForPreferredRenderer(bid: Bid) -> PrebidMobilePluginRenderer { - if let preferredRendererName = bid.getPreferredPluginRendererName(), + public func getPluginForPreferredRenderer(bid: Bid) -> PrebidMobilePluginRenderer { + if let preferredRendererName = bid.pluginRendererName, let preferredPlugin = getPluginRenderer(for: preferredRendererName), - preferredPlugin.version == bid.getPreferredPluginRendererVersion(), + preferredPlugin.version == bid.pluginRendererVersion, preferredPlugin.isSupportRendering(for: bid.adFormat) { return preferredPlugin } else { @@ -109,13 +125,9 @@ import Foundation } } - @objc public func getAllPlugins() -> [PrebidMobilePluginRenderer] { + public func getAllPlugins() -> [PrebidMobilePluginRenderer] { queue.sync { - if plugins.isEmpty { - return [] - } - let allPlugins = Array(plugins.values) - return allPlugins + return plugins.isEmpty ? [] : Array(plugins.values) } } } diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift index 4f9377fb7..e36ca4374 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift @@ -13,41 +13,70 @@  limitations under the License.  */ -import Foundation +import UIKit -@objc public protocol PrebidMobilePluginRenderer: AnyObject { +@objc +public protocol PrebidMobilePluginRenderer: AnyObject { - @objc var name: String { get } - @objc var version: String { get } - @objc var data: [AnyHashable: Any]? { get } + @objc + var name: String { get } - /// Creates and returns Banner View for a given Bid Response - /// Returns nil in the case of an internal error - @objc func createBannerAdView(with frame: CGRect, bid: Bid, adConfiguration: AdUnitConfig, - connection: PrebidServerConnectionProtocol, adViewDelegate: (any PBMAdViewDelegate)?) + @objc + var version: String { get } - /// Creates and returns an implementation of PrebidMobileInterstitialControllerInterface for a given bid response - /// Returns nil in the case of an internal error - @objc optional func createInterstitialController( bid: Bid, adConfiguration: AdUnitConfig, - connection: PrebidServerConnectionProtocol, - adViewManagerDelegate: InterstitialController?, - videoControlsConfig: VideoControlsConfiguration?) + // TODO: send in ORTB + @objc + var data: [AnyHashable: Any]? { get } /// Returns true only if the given ad unit could be renderer by the plugin - @objc func isSupportRendering(for format: AdFormat?) -> Bool + @objc + func isSupportRendering(for format: AdFormat?) -> Bool + + + // TODO: Determine the purpose /// Register a listener related to a specific ad unit config fingerprint in order to dispatch specific ad events - @objc optional func registerEventDelegate(pluginEventDelegate: PluginEventDelegate, - adUnitConfigFingerprint: String) + @objc + optional func registerEventDelegate( + pluginEventDelegate: PluginEventDelegate, + adUnitConfigFingerprint: String + ) /// Unregister a listener related to a specific ad unit config fingerprint in order to dispatch specific ad events - @objc optional func unregisterEventDelegate(pluginEventDelegate: PluginEventDelegate, - adUnitConfigFingerprint: String) - - /// Setup a bid for a given ad unit configuration - @objc func setupBid(_ bid: PrebidMobile.Bid, adConfiguration: PrebidMobile.AdUnitConfig, - connection: PrebidServerConnectionProtocol) + @objc + optional func unregisterEventDelegate( + pluginEventDelegate: PluginEventDelegate, + adUnitConfigFingerprint: String + ) +} +@objc +public protocol PrebidMobileAdViewPluginRenderer: PrebidMobilePluginRenderer { + /// Creates and returns an ad view for a given bid response + /// Returns nil in the case of an internal error + @objc + func createAdView( + with frame: CGRect, + bid: Bid, + adConfiguration: AdUnitConfig, + loadingDelegate: DisplayViewLoadingDelegate?, + interactionDelegate: DisplayViewInteractionDelegate? + ) -> UIView + + // TODO: add display method (?) +} + +@objc +public protocol PrebidMobileInterstitialPluginRenderer: PrebidMobilePluginRenderer { + /// Creates and returns an implementation of PrebidMobileInterstitialControllerInterface for a given bid response + /// Returns nil in the case of an internal error + @objc + func createInterstitialController( + bid: Bid, + adConfiguration: AdUnitConfig, + adViewManagerDelegate: InterstitialController?, + videoControlsConfig: VideoControlsConfiguration? + ) } diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/SampleCustomRenderer.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/SampleCustomRenderer.swift deleted file mode 100644 index 8ff5a684e..000000000 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/SampleCustomRenderer.swift +++ /dev/null @@ -1,83 +0,0 @@ -/*   Copyright 2018-2021 Prebid.org, Inc. - - 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 Foundation -import UIKit - -public class SampleCustomRenderer: NSObject, PrebidMobilePluginRenderer { - - public let name = "SampleCustomRenderer" - - public let version = "1.0.0" - - public var data: [AnyHashable: Any]? = nil - - private var adViewManager: PBMAdViewManager? - - public func isSupportRendering(for format: AdFormat?) -> Bool { - AdFormat.allCases.contains(where: { $0 == format }) - } - - public func setupBid(_ bid: Bid, adConfiguration: AdUnitConfig, connection: PrebidServerConnectionProtocol) { - - } - - public func createBannerAdView(with frame: CGRect, bid: Bid, adConfiguration: AdUnitConfig, - connection: PrebidServerConnectionProtocol, adViewDelegate: (any PBMAdViewDelegate)?) { - DispatchQueue.main.async { - if let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }), - let rootView = window.rootViewController?.view { - if let prebidBannerView = self.findPrebidBannerView(in: rootView) { - print("Found PrebidBannerView: \(prebidBannerView)") - - let label = UILabel() - label.text = "Prebid SDK - Custom Renderer" - label.textAlignment = .center - label.textColor = .black - label.backgroundColor = .yellow - label.translatesAutoresizingMaskIntoConstraints = false - - prebidBannerView.addSubview(label) - - NSLayoutConstraint.activate([ - label.centerXAnchor.constraint(equalTo: prebidBannerView.centerXAnchor), - label.centerYAnchor.constraint(equalTo: prebidBannerView.centerYAnchor), - label.widthAnchor.constraint(equalTo: prebidBannerView.widthAnchor), - label.heightAnchor.constraint(equalTo: prebidBannerView.heightAnchor) - ]) - - } else { - print("PrebidBannerView not found.") - } - } - } - } - - private func findPrebidBannerView(in view: UIView) -> UIView? { - if view.accessibilityIdentifier == "PrebidBannerView" { - return view - } - for subview in view.subviews { - if let foundView = findPrebidBannerView(in: subview) { - return foundView - } - } - return nil - } - - public func createInterstitialController(bid: Bid, adConfiguration: AdUnitConfig, connection: PrebidServerConnectionProtocol, - adViewManagerDelegate adViewDelegate: InterstitialController?, videoControlsConfig: VideoControlsConfiguration?) { - } -} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/BannerAdLoaderDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/BannerAdLoaderDelegate.swift index 42042fd37..73a262a94 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/BannerAdLoaderDelegate.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/BannerAdLoaderDelegate.swift @@ -24,9 +24,4 @@ import UIKit @objc func bannerAdLoader(_ bannerAdLoader: PBMBannerAdLoader, loadedAdView adView: UIView, adSize: CGSize) - - // Hook to insert interaction delegate - @objc func bannerAdLoader(_ bannerAdLoader: PBMBannerAdLoader, - createdDisplayView displayView: PBMDisplayView) - } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMAdLoadFlowController.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMAdLoadFlowController.m index 92bbcbb4e..b03c7fbcd 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMAdLoadFlowController.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMAdLoadFlowController.m @@ -275,6 +275,7 @@ - (void)loadPrebidDisplayView { self.flowState = PBMAdLoadFlowState_LoadingDisplayView; AdUnitConfig * const adUnitConfig = self.savedAdUnitConfig; + adUnitConfig.adConfiguration.winningBidAdFormat = bid.adFormat; @weakify(self); dispatch_sync(dispatch_get_main_queue(), ^{ diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m index 9d33cce63..2b0000333 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m @@ -32,10 +32,11 @@ @interface PBMBannerAdLoader () -@property (nonatomic, weak, nullable, readonly) id delegate; -@end +@property (nonatomic, weak, nullable, readonly) id delegate; +@property (nonatomic, strong, nullable) id renderer; +@end @implementation PBMBannerAdLoader @@ -43,11 +44,13 @@ @implementation PBMBannerAdLoader // MARK: - Lifecycle -- (instancetype)initWithDelegate:(id)delegate { +- (instancetype)initWithDelegate:(id)delegate { if (!(self = [super init])) { return nil; } + _delegate = delegate; + return self; } @@ -62,21 +65,34 @@ - (instancetype)initWithDelegate:(id)delegate { - (void)createPrebidAdWithBid:(Bid *)bid adUnitConfig:(AdUnitConfig *)adUnitConfig adObjectSaver:(void (^)(id))adObjectSaver - loadMethodInvoker:(void (^)(dispatch_block_t))loadMethodInvoker -{ + loadMethodInvoker:(void (^)(dispatch_block_t))loadMethodInvoker { + + [self setRendererWithBid:bid]; + + if (!self.renderer) { + return; + } + + PBMLogInfo(@"Renderer: %@", self.renderer); + CGRect const displayFrame = CGRectMake(0, 0, bid.size.width, bid.size.height); - PBMDisplayView * const newDisplayView = [[PBMDisplayView alloc] initWithFrame:displayFrame - bid:bid - adConfiguration:adUnitConfig]; - adObjectSaver(newDisplayView); - @weakify(self); - loadMethodInvoker(^{ - @strongify(self); - if (!self) { return; } + + dispatch_async(dispatch_get_main_queue(), ^{ + UIView * newDisplayView = [self.renderer createAdViewWith:displayFrame + bid:bid + adConfiguration:adUnitConfig + loadingDelegate:self + interactionDelegate:self.delegate + ]; + + adObjectSaver(newDisplayView); - newDisplayView.loadingDelegate = self; - [self.delegate bannerAdLoader:self createdDisplayView:newDisplayView]; - [newDisplayView displayAd]; + loadMethodInvoker(^{ + // TODO: looks awful, add display method to renderer (?) + if ([newDisplayView isKindOfClass:[PBMDisplayView class]]) { + [(PBMDisplayView *)newDisplayView loadAd]; + } + }); }); } @@ -108,4 +124,14 @@ - (void)failedWithError:(nullable NSError *)error { [self.flowDelegate adLoader:self failedWithPrimarySDKError:error]; } +// MARK: - Helpers + +- (void)setRendererWithBid:(Bid *)bid { + id render = [[PrebidMobilePluginRegister shared] getPluginForPreferredRendererWithBid:bid]; + + if ([render conformsToProtocol:@protocol(PrebidMobileAdViewPluginRenderer)]) { + self.renderer = render; + } +} + @end diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BannerView.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BannerView.swift index 499acd271..c18417e13 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BannerView.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BannerView.swift @@ -18,11 +18,13 @@ import UIKit fileprivate let assertionMessageMainThread = "Expected to only be called on the main thread" /// The view that will display the particular banner ad. Built for rendering type of integration. -public class BannerView: UIView, - BannerAdLoaderDelegate, - AdLoadFlowControllerDelegate, - BannerEventInteractionDelegate, - DisplayViewInteractionDelegate { +@objcMembers +public class BannerView: + UIView, + BannerAdLoaderDelegate, + AdLoadFlowControllerDelegate, + BannerEventInteractionDelegate, + DisplayViewInteractionDelegate { /// The ad unit configuration. public let adUnitConfig: AdUnitConfig @@ -33,45 +35,45 @@ public class BannerView: UIView, // MARK: - Public Properties /// Banner-specific parameters. - @objc public var bannerParameters: BannerParameters { + public var bannerParameters: BannerParameters { get { adUnitConfig.adConfiguration.bannerParameters } } /// Video-specific parameters. - @objc public var videoParameters: VideoParameters { + public var videoParameters: VideoParameters { get { adUnitConfig.adConfiguration.videoParameters } } /// The last bid response received. - @objc public var lastBidResponse: BidResponse? { + public var lastBidResponse: BidResponse? { adLoadFlowController?.bidResponse } /// ID of Stored Impression on the Prebid server - @objc public var configID: String { + public var configID: String { adUnitConfig.configId } /// The interval for refreshing the ad. - @objc public var refreshInterval: TimeInterval { + public var refreshInterval: TimeInterval { get { adUnitConfig.refreshInterval } set { adUnitConfig.refreshInterval = newValue } } /// Additional sizes for the ad. - @objc public var additionalSizes: [CGSize]? { + public var additionalSizes: [CGSize]? { get { adUnitConfig.additionalSizes } set { adUnitConfig.additionalSizes = newValue } } /// The ad format (e.g., banner, video). - @objc public var adFormat: AdFormat { + public var adFormat: AdFormat { get { adUnitConfig.adFormats.first ?? .banner } set { adUnitConfig.adFormats = [newValue] } } /// The position of the ad on the screen. - @objc public var adPosition: AdPosition { + public var adPosition: AdPosition { get { adUnitConfig.adPosition } set { adUnitConfig.adPosition = newValue } } @@ -83,12 +85,7 @@ public class BannerView: UIView, } /// ORTB configuration string. - @objc public weak var delegate: BannerViewDelegate? - - /// Subscribe to plugin renderer events - @objc public func setPluginEventDelegate(_ pluginEventDelegate: PluginEventDelegate) { - PrebidMobilePluginRegister.shared.registerEventDelegate(pluginEventDelegate, adUnitConfigFingerprint: adUnitConfig.fingerprint) - } + public weak var delegate: BannerViewDelegate? // MARK: Readonly storage @@ -135,11 +132,12 @@ public class BannerView: UIView, /// - configID: The configuration ID for the ad unit. /// - adSize: The size of the ad. /// - eventHandler: The event handler for the banner view. - @objc public init(frame: CGRect, - configID: String, - adSize: CGSize, - eventHandler: BannerEventHandler) { - + public init( + frame: CGRect, + configID: String, + adSize: CGSize, + eventHandler: BannerEventHandler + ) { adUnitConfig = AdUnitConfig(configId: configID, size: adSize) adUnitConfig.adConfiguration.bannerParameters.api = PrebidConstants.supportedRenderingBannerAPISignals @@ -151,10 +149,12 @@ public class BannerView: UIView, adLoadFlowController = PBMAdLoadFlowController( bidRequesterFactory: { [adUnitConfig] config in - PBMBidRequester(connection: PrebidServerConnection.shared, - sdkConfiguration: Prebid.shared, - targeting: Targeting.shared, - adUnitConfiguration: adUnitConfig) + PBMBidRequester( + connection: PrebidServerConnection.shared, + sdkConfiguration: Prebid.shared, + targeting: Targeting.shared, + adUnitConfiguration: adUnitConfig + ) }, adLoader: bannerAdLoader, adUnitConfig: adUnitConfig, @@ -187,16 +187,19 @@ public class BannerView: UIView, /// - Parameters: /// - configID: The configuration ID for the ad unit. /// - eventHandler: The event handler for the banner view. - @objc public convenience init(configID: String, - eventHandler: BannerEventHandler) { - + public convenience init( + configID: String, + eventHandler: BannerEventHandler + ) { let size = eventHandler.adSizes.first ?? CGSize() let frame = CGRect(origin: CGPoint.zero, size: size) - self.init(frame: frame, - configID: configID, - adSize: size, - eventHandler: eventHandler) + self.init( + frame: frame, + configID: configID, + adSize: size, + eventHandler: eventHandler + ) if eventHandler.adSizes.count > 1 { self.additionalSizes = Array(eventHandler.adSizes.suffix(from: 1)) @@ -208,13 +211,17 @@ public class BannerView: UIView, /// - frame: The frame rectangle for the view. /// - configID: The configuration ID for the ad unit. /// - adSize: The size of the ad. - @objc public convenience init(frame: CGRect, - configID: String, - adSize: CGSize) { - self.init(frame: frame, - configID: configID, - adSize: adSize, - eventHandler: BannerEventHandlerStandalone()) + public convenience init( + frame: CGRect, + configID: String, + adSize: CGSize + ) { + self.init( + frame: frame, + configID: configID, + adSize: adSize, + eventHandler: BannerEventHandlerStandalone() + ) } deinit { @@ -226,13 +233,13 @@ public class BannerView: UIView, } /// Loads the ad for the banner view. - @objc public func loadAd() { + public func loadAd() { adLoadFlowController?.refresh() } /// Sets the stored auction response. /// - Parameter storedAuction: The stored auction response string. - @objc public func setStoredAuctionResponse(storedAuction:String){ + public func setStoredAuctionResponse(storedAuction:String){ Prebid.shared.storedAuctionResponse = storedAuction } @@ -251,12 +258,22 @@ public class BannerView: UIView, } /// Stops the auto-refresh of the ad. - @objc public func stopRefresh() { + public func stopRefresh() { adLoadFlowController?.enqueueGatedBlock { [weak self] in self?.isRefreshStopped = true } } + // MARK: Custom Renderer + + /// Subscribe to plugin renderer events + public func setPluginEventDelegate(_ pluginEventDelegate: PluginEventDelegate) { + PrebidMobilePluginRegister.shared.registerEventDelegate( + pluginEventDelegate, + adUnitConfigFingerprint: adUnitConfig.fingerprint + ) + } + // MARK: - Ext Data (imp[].ext.data) /// Adds context data for a specified key. @@ -264,7 +281,7 @@ public class BannerView: UIView, /// - data: The data to add. /// - key: The key associated with the data. @available(*, deprecated, message: "This method is deprecated. Please, use addExtData method instead.") - @objc public func addContextData(_ data: String, forKey key: String) { + public func addContextData(_ data: String, forKey key: String) { addExtData(key: key, value: data) } @@ -273,20 +290,20 @@ public class BannerView: UIView, /// - data: A set of data to update. /// - key: The key associated with the data. @available(*, deprecated, message: "This method is deprecated. Please, use updateExtData method instead.") - @objc public func updateContextData(_ data: Set, forKey key: String) { + public func updateContextData(_ data: Set, forKey key: String) { updateExtData(key: key, value: data) } /// Removes context data for a specified key. /// - Parameter key: The key associated with the data to remove. @available(*, deprecated, message: "This method is deprecated. Please, use removeExtData method instead.") - @objc public func removeContextDate(forKey key: String) { + public func removeContextDate(forKey key: String) { removeExtData(forKey: key) } /// Clears all context data. @available(*, deprecated, message: "This method is deprecated. Please, use clearExtData method instead.") - @objc public func clearContextData() { + public func clearContextData() { clearExtData() } @@ -294,7 +311,7 @@ public class BannerView: UIView, /// - Parameters: /// - key: The key for the data. /// - value: The value for the data. - @objc public func addExtData(key: String, value: String) { + public func addExtData(key: String, value: String) { adUnitConfig.addExtData(key: key, value: value) } @@ -302,19 +319,19 @@ public class BannerView: UIView, /// - Parameters: /// - key: The key for the data. /// - value: The value for the data. - @objc public func updateExtData(key: String, value: Set) { + public func updateExtData(key: String, value: Set) { adUnitConfig.updateExtData(key: key, value: value) } /// Removes ext data. /// - Parameters: /// - key: The key for the data. - @objc public func removeExtData(forKey: String) { + public func removeExtData(forKey: String) { adUnitConfig.removeExtData(for: forKey) } /// Clears ext data. - @objc public func clearExtData() { + public func clearExtData() { adUnitConfig.clearExtData() } @@ -323,50 +340,50 @@ public class BannerView: UIView, /// Adds a context keyword. /// - Parameter newElement: The keyword to add. @available(*, deprecated, message: "This method is deprecated. Please, use addExtKeyword method instead.") - @objc public func addContextKeyword(_ newElement: String) { + public func addContextKeyword(_ newElement: String) { addExtKeyword(newElement) } /// Adds a set of context keywords. /// - Parameter newElements: A set of keywords to add. @available(*, deprecated, message: "This method is deprecated. Please, use addExtKeywords method instead.") - @objc public func addContextKeywords(_ newElements: Set) { + public func addContextKeywords(_ newElements: Set) { addExtKeywords(newElements) } /// Removes a context keyword. /// - Parameter element: The keyword to remove. @available(*, deprecated, message: "This method is deprecated. Please, use removeExtKeyword method instead.") - @objc public func removeContextKeyword(_ element: String) { + public func removeContextKeyword(_ element: String) { removeExtKeyword(element) } /// Clears all context keywords. @available(*, deprecated, message: "This method is deprecated. Please, use clearExtKeywords method instead.") - @objc public func clearContextKeywords() { + public func clearContextKeywords() { clearExtKeywords() } /// Adds an extended keyword. /// - Parameter newElement: The keyword to be added. - @objc public func addExtKeyword(_ newElement: String) { + public func addExtKeyword(_ newElement: String) { adUnitConfig.addExtKeyword(newElement) } /// Adds multiple extended keywords. /// - Parameter newElements: A set of keywords to be added. - @objc public func addExtKeywords(_ newElements: Set) { + public func addExtKeywords(_ newElements: Set) { adUnitConfig.addExtKeywords(newElements) } /// Removes an extended keyword. /// - Parameter element: The keyword to be removed. - @objc public func removeExtKeyword(_ element: String) { + public func removeExtKeyword(_ element: String) { adUnitConfig.removeExtKeyword(element) } /// Clears all extended keywords. - @objc public func clearExtKeywords() { + public func clearExtKeywords() { adUnitConfig.clearExtKeywords() } @@ -374,29 +391,29 @@ public class BannerView: UIView, /// Sets the app content data. /// - Parameter appContent: The app content data. - @objc public func setAppContent(_ appContent: PBMORTBAppContent) { + public func setAppContent(_ appContent: PBMORTBAppContent) { adUnitConfig.setAppContent(appContent) } /// Clears the app content data. - @objc public func clearAppContent() { + public func clearAppContent() { adUnitConfig.clearAppContent() } /// Adds app content data objects. /// - Parameter dataObjects: The data objects to be added. - @objc public func addAppContentData(_ dataObjects: [PBMORTBContentData]) { + public func addAppContentData(_ dataObjects: [PBMORTBContentData]) { adUnitConfig.addAppContentData(dataObjects) } /// Removes an app content data object. /// - Parameter dataObject: The data object to be removed. - @objc public func removeAppContentDataObject(_ dataObject: PBMORTBContentData) { + public func removeAppContentDataObject(_ dataObject: PBMORTBContentData) { adUnitConfig.removeAppContentData(dataObject) } /// Clears all app content data objects. - @objc public func clearAppContentDataObjects() { + public func clearAppContentDataObjects() { adUnitConfig.clearAppContentData() } @@ -404,25 +421,25 @@ public class BannerView: UIView, /// Adds user data objects. /// - Parameter userDataObjects: The user data objects to be added. - @objc public func addUserData(_ userDataObjects: [PBMORTBContentData]) { + public func addUserData(_ userDataObjects: [PBMORTBContentData]) { adUnitConfig.addUserData(userDataObjects) } /// Removes a user data object. /// - Parameter userDataObject: The user data object to be removed. - @objc public func removeUserData(_ userDataObject: PBMORTBContentData) { + public func removeUserData(_ userDataObject: PBMORTBContentData) { adUnitConfig.removeUserData(userDataObject) } /// Clears all user data objects. - @objc public func clearUserData() { + public func clearUserData() { adUnitConfig.clearUserData() } // MARK: - DisplayViewInteractionDelegate - public func trackImpression(forDisplayView: PBMDisplayView) { + public func trackImpression(for displayView: UIView) { guard let eventHandler = self.eventHandler, eventHandler.responds(to: #selector(BannerEventHandler.trackImpression)) else { return @@ -431,36 +448,39 @@ public class BannerView: UIView, eventHandler.trackImpression() } - public func viewControllerForModalPresentation(fromDisplayView: PBMDisplayView) -> UIViewController? { + public func viewControllerForModalPresentation(from displayView: UIView) -> UIViewController? { return viewControllerForPresentingModal } - public func didLeaveApp(from displayView: PBMDisplayView) { + public func didLeaveApp(from displayView: UIView) { willLeaveApp() } - public func willPresentModal(from displayView: PBMDisplayView) { + public func willPresentModal(from displayView: UIView) { willPresentModal() } - public func didDismissModal(from displayView: PBMDisplayView) { + public func didDismissModal(from displayView: UIView) { didDismissModal() } // MARK: - BannerAdLoaderDelegate - public func bannerAdLoader(_ bannerAdLoader: PBMBannerAdLoader, loadedAdView adView: UIView, adSize: CGSize) { + public func bannerAdLoader( + _ bannerAdLoader: PBMBannerAdLoader, + loadedAdView adView: UIView, + adSize: CGSize + ) { deployView(adView) reportLoadingSuccess(with: adSize) } - public func bannerAdLoader(_ bannerAdLoader: PBMBannerAdLoader, createdDisplayView displayView: PBMDisplayView) { - displayView.interactionDelegate = self - } - // MARK: - PBMAdLoadFlowControllerDelegate - public func adLoadFlowController(_ adLoadFlowController: PBMAdLoadFlowController, failedWithError error: Error?) { + public func adLoadFlowController( + _ adLoadFlowController: PBMAdLoadFlowController, + failedWithError error: Error? + ) { reportLoadingFailed(with: error) } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/PBMStandaloneSDK/EventHandlers/BannerEventHandlerStandalone.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/PBMStandaloneSDK/EventHandlers/BannerEventHandlerStandalone.swift index 2122404c6..302e61637 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/PBMStandaloneSDK/EventHandlers/BannerEventHandlerStandalone.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/PBMStandaloneSDK/EventHandlers/BannerEventHandlerStandalone.swift @@ -28,5 +28,6 @@ public class BannerEventHandlerStandalone: NSObject, BannerEventHandler { } public func trackImpression() { + } } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewInteractionDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewInteractionDelegate.swift index f5edeb030..65072430b 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewInteractionDelegate.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewInteractionDelegate.swift @@ -13,19 +13,18 @@  limitations under the License.  */ -import Foundation import UIKit +@objc +public protocol DisplayViewInteractionDelegate: NSObjectProtocol { -@objc public protocol DisplayViewInteractionDelegate: NSObjectProtocol { - - func trackImpression(forDisplayView:PBMDisplayView) + func trackImpression(for displayView: UIView) - func viewControllerForModalPresentation(fromDisplayView: PBMDisplayView) -> UIViewController? + func viewControllerForModalPresentation(from displayView: UIView) -> UIViewController? - func didLeaveApp(from displayView: PBMDisplayView) + func didLeaveApp(from displayView: UIView) - func willPresentModal(from displayView: PBMDisplayView) + func willPresentModal(from displayView: UIView) - func didDismissModal(from displayView: PBMDisplayView) + func didDismissModal(from displayView: UIView) } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewLoadingDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewLoadingDelegate.swift index 1a6e418ee..6a9cdf32a 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewLoadingDelegate.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewLoadingDelegate.swift @@ -13,12 +13,10 @@  limitations under the License.  */ -import Foundation +import UIKit -@objc public protocol DisplayViewLoadingDelegate: NSObjectProtocol { - - func displayViewDidLoadAd(_ displayView: PBMDisplayView) - - func displayView(_ displayView: PBMDisplayView, - didFailWithError error: Error) +@objc +public protocol DisplayViewLoadingDelegate: NSObjectProtocol { + func displayViewDidLoadAd(_ displayView: UIView) + func displayView(_ displayView: UIView, didFailWithError error: Error) } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController.swift index b5b49e46b..e89d6a8f9 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController.swift @@ -17,7 +17,7 @@ import UIKit public class InterstitialController: NSObject, PBMAdViewManagerDelegate { - private var renderer: PrebidMobilePluginRenderer? + private var renderer: PrebidMobileInterstitialPluginRenderer? @objc public var adFormats: Set { get { adConfiguration.adFormats } @@ -66,15 +66,10 @@ public class InterstitialController: NSObject, PBMAdViewManagerDelegate { // TODO: provide a more relevant name for this function. @objc public func loadAd() { - - self.renderer = PrebidMobilePluginRegister.shared.getPluginForPreferredRenderer(bid: bid) - - let connection: PrebidServerConnectionProtocol = PrebidServerConnection.shared - - self.renderer?.createInterstitialController?( + renderer = PrebidMobilePluginRegister.shared.getPluginForPreferredRenderer(bid: bid) as? PrebidMobileInterstitialPluginRenderer + renderer?.createInterstitialController( bid: bid, adConfiguration: adConfiguration, - connection: connection, adViewManagerDelegate: self, videoControlsConfig: videoControlsConfig ) diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView+InternalState.h b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView+InternalState.h index e33b5b49c..3457bca3f 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView+InternalState.h +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView+InternalState.h @@ -27,7 +27,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong, readonly, nullable) id connection; -- (instancetype)initWithFrame:(CGRect)frame bid:(Bid *)bid adConfiguration:(AdUnitConfig *)adConfiguration; +- (instancetype)initWithFrame:(CGRect)frame + bid:(Bid *)bid + adConfiguration:(AdUnitConfig *)adConfiguration; @end diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.h b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.h index e3beb7b29..94a30db81 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.h +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.h @@ -15,21 +15,27 @@ #import -@class Bid; +#import "PBMAdViewManagerDelegate.h" +#import "PBMModalManagerDelegate.h" + @protocol DisplayViewLoadingDelegate; @protocol DisplayViewInteractionDelegate; +@class AdUnitConfig; +@class Bid; + NS_ASSUME_NONNULL_BEGIN -@interface PBMDisplayView : UIView +@interface PBMDisplayView : UIView @property (atomic, weak, nullable) NSObject *loadingDelegate; @property (atomic, weak, nullable) NSObject *interactionDelegate; @property (nonatomic, readonly) BOOL isCreativeOpened; - (instancetype)initWithFrame:(CGRect)frame bid:(Bid *)bid configId:(NSString *)configId; +- (instancetype)initWithFrame:(CGRect)frame bid:(Bid *)bid adConfiguration:(AdUnitConfig *)adConfiguration; -- (void)displayAd; +- (void)loadAd; @end diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.m b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.m index d8a66fc2a..ab5e1438a 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.m @@ -34,45 +34,72 @@ #import "PBMMacros.h" -@interface PBMDisplayView () +@interface PBMDisplayView () @property (nonatomic, strong, readonly, nonnull) Bid *bid; @property (nonatomic, strong, readonly, nonnull) AdUnitConfig *adConfiguration; +@property (nonatomic, strong, nullable) PBMTransactionFactory *transactionFactory; @property (nonatomic, strong, nullable) PBMAdViewManager *adViewManager; @property (nonatomic, strong, readonly, nonnull) PBMInterstitialDisplayProperties *interstitialDisplayProperties; -@property (nonatomic, strong, nullable) id renderer; - @end @implementation PBMDisplayView // MARK: - Public API - (instancetype)initWithFrame:(CGRect)frame bid:(Bid *)bid configId:(NSString *)configId { - return self = [self initWithFrame:frame bid:bid adConfiguration:[[AdUnitConfig alloc] initWithConfigId:configId size:bid.size]]; + return self = [self initWithFrame:frame + bid:bid + adConfiguration:[[AdUnitConfig alloc] initWithConfigId:configId + size:bid.size]]; } -- (instancetype)initWithFrame:(CGRect)frame bid:(Bid *)bid adConfiguration:(AdUnitConfig *)adConfiguration { +- (instancetype)initWithFrame:(CGRect)frame + bid:(Bid *)bid + adConfiguration:(AdUnitConfig *)adConfiguration { + if (!(self = [super initWithFrame:frame])) { return nil; } + _bid = bid; _adConfiguration = adConfiguration; _interstitialDisplayProperties = [[PBMInterstitialDisplayProperties alloc] init]; + return self; } -- (void)displayAd { - self.renderer = [[PrebidMobilePluginRegister shared] getPluginForPreferredRendererWithBid:self.bid]; - - NSLog(@"Renderer: %@", self.renderer); - self.adConfiguration.adConfiguration.winningBidAdFormat = self.bid.adFormat; - id const connection = self.connection ?: PrebidServerConnection.shared; - dispatch_async(dispatch_get_main_queue(), ^{ - [self.renderer createBannerAdViewWith:self.frame bid:self.bid adConfiguration:self.adConfiguration connection:connection adViewDelegate:self]; - }); +- (void)loadAd { + if (self.transactionFactory) { + return; + } + + @weakify(self); + self.transactionFactory = [[PBMTransactionFactory alloc] initWithBid:self.bid + adConfiguration:self.adConfiguration + connection:self.connection ?: PrebidServerConnection.shared + callback:^(PBMTransaction * _Nullable transaction, + NSError * _Nullable error) { + @strongify(self); + if (!self) { return; } + + if (error) { + [self reportFailureWithError:error]; + } else { + [self displayTransaction:transaction]; + } + }]; + + [PBMWinNotifier notifyThroughConnection:PrebidServerConnection.shared + winningBid:self.bid + callback:^(NSString *adMarkup) { + @strongify(self); + if (!self) { return; } + + [self.transactionFactory loadWithAdMarkup:adMarkup]; + }]; } - (BOOL)isCreativeOpened { @@ -82,7 +109,7 @@ - (BOOL)isCreativeOpened { // MARK: - PBMAdViewManagerDelegate protocol - (UIViewController *)viewControllerForModalPresentation { - return [self.interactionDelegate viewControllerForModalPresentationFromDisplayView:self]; + return [self.interactionDelegate viewControllerForModalPresentationFrom:self]; } - (void)adLoaded:(PBMAdDetails *)pbmAdDetails { @@ -99,7 +126,7 @@ - (void)adDidComplete { } - (void)adDidDisplay { - [self.interactionDelegate trackImpressionForDisplayView:self]; + [self.interactionDelegate trackImpressionFor:self]; } - (void)adWasClicked { @@ -158,6 +185,17 @@ - (void)reportSuccess { [self.loadingDelegate displayViewDidLoadAd:self]; } +- (void)displayTransaction:(PBMTransaction *)transaction { + id const connection = self.connection ?: PrebidServerConnection.shared; + self.adViewManager = [[PBMAdViewManager alloc] initWithConnection:connection modalManagerDelegate:self]; + self.adViewManager.adViewManagerDelegate = self; + self.adViewManager.adConfiguration = self.adConfiguration.adConfiguration; + if (self.adConfiguration.adConfiguration.winningBidAdFormat == AdFormat.video) { + self.adConfiguration.adConfiguration.isBuiltInVideo = YES; + } + [self.adViewManager handleExternalTransaction:transaction]; +} + - (void)interactionDelegateWillPresentModal { NSObject const *delegate = self.interactionDelegate; if ([delegate respondsToSelector:@selector(willPresentModalFrom:)]) { diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerRenderer.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerRenderer.swift new file mode 100644 index 000000000..bde360f9b --- /dev/null +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerRenderer.swift @@ -0,0 +1,150 @@ +/*   Copyright 2018-2021 Prebid.org, Inc. + +  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 UIKit + +public class PrebidAdViewRenderer: NSObject, PrebidMobilePluginRenderer { + + public let name = "PrebidBannerRenderer" + public let version = Prebid.shared.version + public var data: [AnyHashable: Any]? = nil + + public func isSupportRendering(for format: AdFormat?) -> Bool { + AdFormat.allCases.contains(where: { $0 == format }) + } + + private var transactionFactory: PBMTransactionFactory? + private var adViewManager: PBMAdViewManager? + + public func createBannerAdView( + with frame: CGRect, + bid: Bid, + adConfiguration: AdUnitConfig, + connection: PrebidServerConnectionProtocol, + adViewDelegate: (any PBMAdViewDelegate)? + ) -> UIView { + let displayView = PBMDisplayView( + frame: frame, + bid: bid, + adConfiguration: adConfiguration + ) + + transactionFactory = PBMTransactionFactory( + bid: bid, + adConfiguration: adConfiguration, + connection: connection + ) { [weak self] transaction, error in + self?.transactionFactory = nil + + guard let transaction else { +// adViewDelegate?.failed(toLoad: NSError(domain: "", code: 0)) + return + } + + if let error { + // adViewDelegate?.failed(toLoad: error) + return + } + + self?.displayTransaction( + transaction, + adConfiguration: adConfiguration, + connection: connection, + adViewDelegate: adViewDelegate + ) + } + + PBMWinNotifier.notifyThroughConnection( + PrebidServerConnection.shared, + winning: bid + ) { [weak self] adMarkup in + if let adMarkup { + self?.transactionFactory?.load(withAdMarkup: adMarkup) + } + } + + // TODO: Run display + + return displayView + } + + public func createInterstitialController( + bid: Bid, + adConfiguration: AdUnitConfig, + connection: PrebidServerConnectionProtocol, + adViewManagerDelegate adViewDelegate: InterstitialController?, + videoControlsConfig: VideoControlsConfiguration? + ) { + // guard transactionFactory == nil else { + // return + // } + // + // adConfiguration.adConfiguration.winningBidAdFormat = bid.adFormat + // videoControlsConfig?.initialize(with: bid.videoAdConfiguration) + // + // // This part is dedicating to test server-side ad configurations. + // // Need to be removed when ext.prebid.passthrough will be available. + // #if DEBUG + // adConfiguration.adConfiguration.videoControlsConfig.initialize(with: bid.testVideoAdConfiguration) + // #endif + // transactionFactory = PBMTransactionFactory(bid: bid, + // adConfiguration: adConfiguration, + // connection: PrebidServerConnection.shared, + // callback: { [weak adViewDelegate] transaction, error in + // + // if let transaction = transaction { + // adViewDelegate?.display(transaction: transaction) + // } else { + // self.transactionFactory = nil + // adViewDelegate?.reportFailureWithError(error) + // } + // }) + // + // PBMWinNotifier.notifyThroughConnection( + // PrebidServerConnection.shared, + // winning: bid, + // callback: { [weak self] adMarkup in + // + // if let self = self, let adMarkup = adMarkup { + // self.transactionFactory?.load(withAdMarkup: adMarkup) + // } else { + // Log.debug("Ad markup is empty") + // } + // }) + } + + public func setupBid( + _ bid: Bid, + adConfiguration: AdUnitConfig, + connection: PrebidServerConnectionProtocol + ) {} + + private func displayTransaction( + _ transaction: PBMTransaction, + adConfiguration: AdUnitConfig, + connection: PrebidServerConnectionProtocol, + adViewDelegate: (any PBMAdViewDelegate)? + ) { + adViewManager = PBMAdViewManager(connection: connection, modalManagerDelegate: adViewDelegate) + adViewManager?.adViewManagerDelegate = adViewDelegate + adViewManager?.adConfiguration = adConfiguration.adConfiguration + + if adConfiguration.adConfiguration.winningBidAdFormat == .video { + adConfiguration.adConfiguration.isBuiltInVideo = true + } + + adViewManager?.handleExternalTransaction(transaction) + } +} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerViewRenderer.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerViewRenderer.swift new file mode 100644 index 000000000..09dadcda0 --- /dev/null +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerViewRenderer.swift @@ -0,0 +1,51 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 UIKit + +public class PrebidDisplayViewRenderer: NSObject, PrebidMobileBannerViewPluginRenderer { + + public let name = "PrebidDisplayViewRenderer" + public let version = Prebid.shared.version + public var data: [AnyHashable: Any]? + + public func isSupportRendering(for format: AdFormat?) -> Bool { + AdFormat.allCases.contains(where: { $0 == format }) + } + + private var transactionFactory: PBMTransactionFactory? + private var adViewManager: PBMAdViewManager? + private var connection = PrebidServerConnection.shared + + public func createBannerAdView( + with frame: CGRect, + bid: Bid, + adConfiguration: AdUnitConfig, + loadingDelegate: DisplayViewLoadingDelegate?, + interactionDelegate: DisplayViewInteractionDelegate? + ) -> UIView { + + let displayView = PBMDisplayView( + frame: frame, + bid: bid, + adConfiguration: adConfiguration + ) + + displayView.interactionDelegate = interactionDelegate + displayView.loadingDelegate = loadingDelegate + + return displayView + } +} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidDisplayViewRenderer.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidDisplayViewRenderer.swift new file mode 100644 index 000000000..94701807d --- /dev/null +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidDisplayViewRenderer.swift @@ -0,0 +1,50 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 UIKit + +public class PrebidDisplayViewRenderer: NSObject, PrebidMobileAdViewPluginRenderer { + + public let name = "PrebidDisplayViewRenderer" + public let version = Prebid.shared.version + public var data: [AnyHashable: Any]? + + public func isSupportRendering(for format: AdFormat?) -> Bool { + AdFormat.allCases.contains(where: { $0 == format }) + } + + private var transactionFactory: PBMTransactionFactory? + private var adViewManager: PBMAdViewManager? + private var connection = PrebidServerConnection.shared + + public func createAdView( + with frame: CGRect, + bid: Bid, + adConfiguration: AdUnitConfig, + loadingDelegate: DisplayViewLoadingDelegate?, + interactionDelegate: DisplayViewInteractionDelegate? + ) -> UIView { + let displayView = PBMDisplayView( + frame: frame, + bid: bid, + adConfiguration: adConfiguration + ) + + displayView.interactionDelegate = interactionDelegate + displayView.loadingDelegate = loadingDelegate + + return displayView + } +} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift deleted file mode 100644 index 12576bcf7..000000000 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift +++ /dev/null @@ -1,119 +0,0 @@ -/*   Copyright 2018-2021 Prebid.org, Inc. - - 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 Foundation - -public class PrebidRenderer: NSObject, PrebidMobilePluginRenderer { - - public let name = "PrebidRenderer" - - public let version = Prebid.shared.version - - public var data: [AnyHashable: Any]? = nil - - private var adViewManager: PBMAdViewManager? - - public var transactionFactory: PBMTransactionFactory? - - public func isSupportRendering(for format: AdFormat?) -> Bool { - AdFormat.allCases.contains(where: { $0 == format }) - } - - public func setupBid(_ bid: Bid, adConfiguration: AdUnitConfig, connection: PrebidServerConnectionProtocol) { - - } - - public func createBannerAdView(with frame: CGRect, bid: Bid, adConfiguration: AdUnitConfig, - connection: PrebidServerConnectionProtocol, - adViewDelegate: (any PBMAdViewDelegate)?) { - - self.transactionFactory = PBMTransactionFactory(bid: bid, adConfiguration: adConfiguration, connection: connection) { [weak self] transaction, error in - self?.transactionFactory = nil - guard let transaction else { - adViewDelegate?.failed(toLoad: NSError(domain: "", code: 0)) - return - } - if let error { - adViewDelegate?.failed(toLoad: error) - return - } - self?.displayTransaction(transaction, adConfiguration: adConfiguration, connection: connection, adViewDelegate: adViewDelegate) - } - - PBMWinNotifier.notifyThroughConnection(PrebidServerConnection.shared, - winning: bid) { [weak self] adMarkup in - - self?.transactionFactory?.load(withAdMarkup: adMarkup!) - } - - } - - - private func displayTransaction(_ transaction: PBMTransaction, adConfiguration: AdUnitConfig, - connection: PrebidServerConnectionProtocol, - adViewDelegate: (any PBMAdViewDelegate)?) { - adViewManager = PBMAdViewManager(connection: connection, modalManagerDelegate: adViewDelegate) - adViewManager?.adViewManagerDelegate = adViewDelegate - adViewManager?.adConfiguration = adConfiguration.adConfiguration - - if adConfiguration.adConfiguration.winningBidAdFormat == .video { - adConfiguration.adConfiguration.isBuiltInVideo = true - } - - adViewManager?.handleExternalTransaction(transaction) - } - - public func createInterstitialController(bid: Bid, adConfiguration: AdUnitConfig, - connection: PrebidServerConnectionProtocol, - adViewManagerDelegate adViewDelegate: InterstitialController?, - videoControlsConfig: VideoControlsConfiguration?) { - guard transactionFactory == nil else { - return - } - - adConfiguration.adConfiguration.winningBidAdFormat = bid.adFormat - videoControlsConfig?.initialize(with: bid.videoAdConfiguration) - - adConfiguration.adConfiguration.rewardedConfig = RewardedConfig(ortbRewarded: bid.rewardedConfig) - - // This part is dedicating to test server-side ad configurations. - // Need to be removed when ext.prebid.passthrough will be available. - #if DEBUG - adConfiguration.adConfiguration.videoControlsConfig.initialize(with: bid.testVideoAdConfiguration) - #endif - transactionFactory = PBMTransactionFactory(bid: bid, - adConfiguration: adConfiguration, - connection: PrebidServerConnection.shared, - callback: { [weak adViewDelegate] transaction, error in - - if let transaction = transaction { - adViewDelegate?.display(transaction: transaction) - } else { - self.transactionFactory = nil - adViewDelegate?.reportFailureWithError(error) - } - }) - - PBMWinNotifier.notifyThroughConnection(PrebidServerConnection.shared, - winning: bid, - callback: { [weak self] adMarkup in - if let self = self, let adMarkup = adMarkup { - self.transactionFactory?.load(withAdMarkup: adMarkup) - } else { - Log.debug("Ad markup is empty") - } - }) - } - -} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/Bid.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/Bid.swift index 98f75cfe3..6fe4e509d 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/Bid.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/Bid.swift @@ -18,6 +18,7 @@ import Foundation import StoreKit import UIKit +@objcMembers public class Bid: NSObject { public static let KEY_RENDERER_NAME = "rendererName"; @@ -27,7 +28,7 @@ public class Bid: NSObject { /// Bid price expressed as CPM although the actual transaction is for a unit impression only. /// Note that while the type indicates float, integer math is highly recommended /// when handling currencies (e.g., BigDecimal in Java). - @objc public var price: Float { + public var price: Float { bid.price.floatValue } @@ -35,15 +36,15 @@ public class Bid: NSObject { /// Win notice URL called by the exchange if the bid wins (not necessarily indicative of a delivered, /// viewed, or billable ad); optional means of serving ad markup. /// Substitution macros (Section 4.4) may be included in both the URL and optionally returned markup. - @objc public private(set) var nurl: String? + public private(set) var nurl: String? /// Optional means of conveying ad markup in case the bid wins; supersedes the win notice /// if markup is included in both. /// Substitution macros (Section 4.4) may be included. - @objc public private(set) var adm: String? + public private(set) var adm: String? /// Ad size - @objc public var size: CGSize { + public var size: CGSize { guard let w = bid.w, let h = bid.h else { return CGSize.zero } @@ -52,12 +53,12 @@ public class Bid: NSObject { } /// Targeting information that needs to be passed to the ad server SDK. - @objc public var targetingInfo: [String : String]? { + public var targetingInfo: [String : String]? { bid.ext.prebid?.targeting } /// Targeting information that needs to be passed to the ad server SDK. - @objc public var meta: [String : String]? { + public var meta: [String : String]? { bid.ext.prebid?.meta } @@ -65,24 +66,34 @@ public class Bid: NSObject { SKAdNetwork parameters about an App Store product. Used in the StoreKit */ - @objc public var skadn: PBMORTBBidExtSkadn? { + public var skadn: PBMORTBBidExtSkadn? { return bid.ext.skadn } /// Prebid ad format - @objc public var adFormat: AdFormat? { + public var adFormat: AdFormat? { AdFormat.allCases.filter { $0.stringEquivalent == bid.ext.prebid?.type }.first } /// Prebid video ad configuration - @objc public var videoAdConfiguration: PBMORTBAdConfiguration? { + public var videoAdConfiguration: PBMORTBAdConfiguration? { bid.ext.prebid?.passthrough?.filter { $0.type == "prebidmobilesdk" }.first?.adConfiguration } + /// Preffered plugin renderer name + public var pluginRendererName: String? { + meta?[Bid.KEY_RENDERER_NAME] + } + + /// Preffered plugin renderer version + public var pluginRendererVersion: String? { + meta?[Bid.KEY_RENDERER_VERSION] + } + // This part is dedicating to test server-side ad configurations. // Need to be removed when ext.prebid.passthrough will be available. #if DEBUG - @objc public var testVideoAdConfiguration: PBMORTBAdConfiguration? { + public var testVideoAdConfiguration: PBMORTBAdConfiguration? { bid.ext.passthrough?.filter { $0.type == "prebidmobilesdk" }.first?.adConfiguration } #endif @@ -92,7 +103,7 @@ public class Bid: NSObject { } /// Returns YES if this bid is intented for display. - @objc public var isWinning: Bool { + public var isWinning: Bool { guard let targetingInfo = self.targetingInfo else { return false } @@ -111,24 +122,16 @@ public class Bid: NSObject { return true } - @objc public var events: PBMORTBExtPrebidEvents? { + public var events: PBMORTBExtPrebidEvents? { bid.ext.prebid?.events } - @objc public private(set) var bid: PBMORTBBid + public private(set) var bid: PBMORTBBid - @objc public init(bid: PBMORTBBid) { + public init(bid: PBMORTBBid) { self.bid = bid let macrosHelper = PBMORTBMacrosHelper(bid: bid) adm = macrosHelper.replaceMacros(in: bid.adm) nurl = macrosHelper.replaceMacros(in: bid.nurl) } - - public func getPreferredPluginRendererName() -> String? { - return meta?[Bid.KEY_RENDERER_NAME] - } - - public func getPreferredPluginRendererVersion() -> String? { - return meta?[Bid.KEY_RENDERER_VERSION] - } } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/BidResponse.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/BidResponse.swift index 342a7d97e..de99bde79 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/BidResponse.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/BidResponse.swift @@ -101,12 +101,4 @@ public class BidResponse: NSObject { targetingInfo?[key] = value } - - public func getPreferredPluginRendererName() -> String? { - winningBid?.getPreferredPluginRendererName() - } - - public func getPreferredPluginRendererVersion() -> String? { - winningBid?.getPreferredPluginRendererVersion() - } } From 4aad71f81f67ccab2d585136ecd448bdab736479 Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Fri, 29 Nov 2024 11:30:30 +0200 Subject: [PATCH 02/18] feat: interstitial custom renderer prototype --- .../Sources/PrebidAdMobBannerAdapter.swift | 4 +- .../PrebidAdMobInterstitialAdapter.swift | 24 +-- .../PrebidAdMobVideoInterstitialAdapter.swift | 26 +-- ...dMAXMediationAdapter+MAAdViewAdapter.swift | 4 +- ...nterstitialAdapter+MARewardedAdapter.swift | 34 ++-- .../InternalTestApp.xcodeproj/project.pbxproj | 24 ++- .../Model/TestCasesManager.swift | 21 ++- ...CustomRendererInterstitialController.swift | 2 +- .../{ => Renderers}/SampleAdView.swift | 0 .../SampleCustomAdViewRenderer.swift | 4 +- .../SampleCustomInterstitialRenderer.swift | 46 +++++ .../SampleInterstitialController.swift | 98 +++++++++++ PrebidMobile.xcodeproj/project.pbxproj | 8 + .../PrebidMobilePluginRegister.swift | 10 +- .../PrebidMobilePluginRenderer.swift | 6 +- .../GAM/AdLoading/PBMBannerAdLoader.m | 3 +- .../GAM/AdLoading/PBMInterstitialAdLoader.h | 1 + .../GAM/AdLoading/PBMInterstitialAdLoader.m | 55 +++--- .../Prebid/Integrations/GAM/BannerView.swift | 4 +- .../GAM/BaseInterstitialAdUnit.swift | 30 +++- .../GAM/BaseInterstitialAdUnitProtocol.swift | 6 +- .../Integrations/GAM/RewardedAdUnit.swift | 34 +--- .../DisplayViewInteractionDelegate.swift | 4 +- .../DisplayViewLoadingDelegate.swift | 1 + .../InterstitialController.swift | 158 +++++++++++------- ...stitialControllerInteractionDelegate.swift | 19 ++- ...nterstitialControllerLoadingDelegate.swift | 7 +- .../InterstitialControllerProtocol.swift | 23 +++ .../Prebid/PBMCacheRenderers/PBMDisplayView.m | 4 +- .../PrebidDisplayViewRenderer.swift | 6 +- ...PrebidInterstitialControllerRenderer.swift | 46 +++++ 31 files changed, 508 insertions(+), 204 deletions(-) rename InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/{ => Renderers}/SampleAdView.swift (100%) rename InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/{ => Renderers}/SampleCustomAdViewRenderer.swift (92%) create mode 100644 InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomInterstitialRenderer.swift create mode 100644 InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialController.swift create mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerProtocol.swift create mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidInterstitialControllerRenderer.swift diff --git a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobBannerAdapter.swift b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobBannerAdapter.swift index 836724534..30019a1d6 100644 --- a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobBannerAdapter.swift +++ b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobBannerAdapter.swift @@ -102,11 +102,11 @@ public class PrebidAdMobBannerAdapter: // MARK: - PBMDisplayViewInteractionDelegate - public func trackImpression(for displayView: UIView) { + public func trackImpression(forDisplayView: UIView) { delegate?.reportImpression() } - public func viewControllerForModalPresentation(from displayView: UIView) -> UIViewController? { + public func viewControllerForModalPresentation(fromDisplayView: UIView) -> UIViewController? { return adConfiguration?.topViewController ?? UIApplication.shared.windows.first?.rootViewController } diff --git a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobInterstitialAdapter.swift b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobInterstitialAdapter.swift index d7c796d05..e82195d2c 100644 --- a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobInterstitialAdapter.swift +++ b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobInterstitialAdapter.swift @@ -95,7 +95,7 @@ public class PrebidAdMobInterstitialAdapter: // MARK: - InterstitialControllerLoadingDelegate - public func interstitialControllerDidLoadAd(_ interstitialController: InterstitialController) { + public func interstitialControllerDidLoadAd(_ interstitialController: InterstitialControllerProtocol) { adAvailable = true if let handler = completionHandler { @@ -103,7 +103,10 @@ public class PrebidAdMobInterstitialAdapter: } } - public func interstitialController(_ interstitialController: InterstitialController, didFailWithError error: Error) { + public func interstitialController( + _ interstitialController: InterstitialControllerProtocol, + didFailWithError error: Error + ) { adAvailable = false if let handler = completionHandler { @@ -113,28 +116,29 @@ public class PrebidAdMobInterstitialAdapter: // MARK: - InterstitialControllerInteractionDelegate - public func trackImpression(forInterstitialController: InterstitialController) { + public func trackImpression(forInterstitialController: InterstitialControllerProtocol) { delegate?.reportImpression() } - public func viewControllerForModalPresentation(fromInterstitialController: InterstitialController) -> UIViewController? { + public func viewControllerForModalPresentation( + fromInterstitialController: InterstitialControllerProtocol + ) -> UIViewController? { rootViewController } - public func interstitialControllerDidClickAd(_ interstitialController: InterstitialController) { + public func interstitialControllerDidClickAd(_ interstitialController: InterstitialControllerProtocol) { delegate?.reportClick() } - public func interstitialControllerDidCloseAd(_ interstitialController: InterstitialController) { + public func interstitialControllerDidCloseAd(_ interstitialController: InterstitialControllerProtocol) { delegate?.willDismissFullScreenView() delegate?.didDismissFullScreenView() } - public func interstitialControllerDidDisplay(_ interstitialController: InterstitialController) { + public func interstitialControllerDidDisplay(_ interstitialController: InterstitialControllerProtocol) { delegate?.willPresentFullScreenView() } - public func interstitialControllerDidComplete(_ interstitialController: InterstitialController) {} - - public func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialController) {} + public func interstitialControllerDidComplete(_ interstitialController: InterstitialControllerProtocol) {} + public func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialControllerProtocol) {} } diff --git a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobVideoInterstitialAdapter.swift b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobVideoInterstitialAdapter.swift index 0613cc6b7..a8cebe079 100644 --- a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobVideoInterstitialAdapter.swift +++ b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobVideoInterstitialAdapter.swift @@ -103,7 +103,9 @@ public class PrebidAdMobVideoInterstitialAdapter: // MARK: - InterstitialControllerLoadingDelegate - public func interstitialControllerDidLoadAd(_ interstitialController: InterstitialController) { + public func interstitialControllerDidLoadAd( + _ interstitialController: InterstitialControllerProtocol + ) { adAvailable = true if let handler = completionHandler { @@ -111,7 +113,10 @@ public class PrebidAdMobVideoInterstitialAdapter: } } - public func interstitialController(_ interstitialController: InterstitialController, didFailWithError error: Error) { + public func interstitialController( + _ interstitialController: InterstitialControllerProtocol, + didFailWithError error: Error + ) { adAvailable = false if let handler = completionHandler { @@ -121,28 +126,29 @@ public class PrebidAdMobVideoInterstitialAdapter: // MARK: - InterstitialControllerInteractionDelegate - public func trackImpression(forInterstitialController: InterstitialController) { + public func trackImpression(forInterstitialController: InterstitialControllerProtocol) { delegate?.reportImpression() } - public func viewControllerForModalPresentation(fromInterstitialController: InterstitialController) -> UIViewController? { + public func viewControllerForModalPresentation( + fromInterstitialController: InterstitialControllerProtocol + ) -> UIViewController? { rootViewController } - public func interstitialControllerDidClickAd(_ interstitialController: InterstitialController) { + public func interstitialControllerDidClickAd(_ interstitialController: InterstitialControllerProtocol) { delegate?.reportClick() } - public func interstitialControllerDidCloseAd(_ interstitialController: InterstitialController) { + public func interstitialControllerDidCloseAd(_ interstitialController: InterstitialControllerProtocol) { delegate?.willDismissFullScreenView() delegate?.didDismissFullScreenView() } - public func interstitialControllerDidDisplay(_ interstitialController: InterstitialController) { + public func interstitialControllerDidDisplay(_ interstitialController: InterstitialControllerProtocol) { delegate?.willPresentFullScreenView() } - public func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialController) {} - - public func interstitialControllerDidComplete(_ interstitialController: InterstitialController) {} + public func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialControllerProtocol) {} + public func interstitialControllerDidComplete(_ interstitialController: InterstitialControllerProtocol) {} } diff --git a/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAAdViewAdapter.swift b/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAAdViewAdapter.swift index 0e06c6efc..a0e7cc908 100644 --- a/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAAdViewAdapter.swift +++ b/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAAdViewAdapter.swift @@ -78,7 +78,7 @@ extension PrebidMAXMediationAdapter: // MARK: DisplayViewInteractionDelegate - public func viewControllerForModalPresentation(from displayView: UIView) -> UIViewController? { + public func viewControllerForModalPresentation(fromDisplayView: UIView) -> UIViewController? { return UIApplication.shared.windows.first?.rootViewController } @@ -92,6 +92,6 @@ extension PrebidMAXMediationAdapter: bannerDelegate?.didCollapseAdViewAd() } - public func trackImpression(for displayView: UIView) {} + public func trackImpression(forDisplayView: UIView) {} public func didLeaveApp(from displayView: UIView) {} } diff --git a/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAInterstitialAdapter+MARewardedAdapter.swift b/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAInterstitialAdapter+MARewardedAdapter.swift index 3dd04e14b..3c3c18a0b 100644 --- a/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAInterstitialAdapter+MARewardedAdapter.swift +++ b/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAInterstitialAdapter+MARewardedAdapter.swift @@ -121,13 +121,16 @@ extension PrebidMAXMediationAdapter: MAInterstitialAdapter, // MARK: - InterstitialControllerLoadingDelegate - public func interstitialControllerDidLoadAd(_ interstitialController: InterstitialController) { + public func interstitialControllerDidLoadAd(_ interstitialController: InterstitialControllerProtocol) { interstitialAdAvailable = true interstitialDelegate?.didLoadInterstitialAd() rewardedDelegate?.didLoadRewardedAd() } - public func interstitialController(_ interstitialController: InterstitialController, didFailWithError error: Error) { + public func interstitialController( + _ interstitialController: InterstitialControllerProtocol, + didFailWithError error: Error + ) { interstitialAdAvailable = false let maError = MAAdapterError(nsError: error) interstitialDelegate?.didFailToLoadInterstitialAdWithError(maError) @@ -136,45 +139,32 @@ extension PrebidMAXMediationAdapter: MAInterstitialAdapter, // MARK: - InterstitialControllerInteractionDelegate - public func trackImpression(forInterstitialController: InterstitialController) {} - - public func interstitialControllerDidClickAd(_ interstitialController: InterstitialController) { + public func interstitialControllerDidClickAd(_ interstitialController: InterstitialControllerProtocol) { interstitialDelegate?.didClickInterstitialAd() rewardedDelegate?.didClickRewardedAd() } - public func interstitialControllerDidCloseAd(_ interstitialController: InterstitialController) { + public func interstitialControllerDidCloseAd(_ interstitialController: InterstitialControllerProtocol) { interstitialDelegate?.didHideInterstitialAd() rewardedDelegate?.didHideRewardedAd() } - public func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialController) {} - - public func interstitialControllerDidDisplay(_ interstitialController: InterstitialController) { + public func interstitialControllerDidDisplay(_ interstitialController: InterstitialControllerProtocol) { interstitialDelegate?.didDisplayInterstitialAd() rewardedDelegate?.didDisplayRewardedAd() } - public func interstitialControllerDidComplete(_ interstitialController: InterstitialController) { + public func interstitialControllerDidComplete(_ interstitialController: InterstitialControllerProtocol) { interstitialAdAvailable = false rewardedDelegate?.didRewardUser(with: MAReward()) } public func viewControllerForModalPresentation( - fromInterstitialController: InterstitialController + fromInterstitialController: InterstitialControllerProtocol ) -> UIViewController? { return UIApplication.shared.windows.first?.rootViewController } - public func trackUserReward( - _ interstitialController: InterstitialController, - _ reward: PrebidReward - ) { - let reward = MAReward( - amount: reward.count?.intValue ?? 0, - label: reward.type ?? "" - ) - - rewardedDelegate?.didRewardUser(with: reward) - } + public func trackImpression(forInterstitialController: InterstitialControllerProtocol) {} + public func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialControllerProtocol) {} } diff --git a/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj b/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj index 704df261d..84ea9ddd5 100644 --- a/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj +++ b/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj @@ -55,6 +55,10 @@ 53BFCD042CF792FB00A3287A /* SampleCustomAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD022CF792FB00A3287A /* SampleCustomAdViewRenderer.swift */; }; 53BFCD0C2CF8F56300A3287A /* SampleAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */; }; 53BFCD0D2CF8F56300A3287A /* SampleAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */; }; + 53BFCD132CF9C67400A3287A /* SampleInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD122CF9C67400A3287A /* SampleInterstitialController.swift */; }; + 53BFCD142CF9C67400A3287A /* SampleInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD122CF9C67400A3287A /* SampleInterstitialController.swift */; }; + 53BFCD172CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD162CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift */; }; + 53BFCD182CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD162CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift */; }; 53ED2FD329798104007D13EE /* LogInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D70F6A24E546DD0048CC78 /* LogInfo.swift */; }; 53ED2FD429798104007D13EE /* PrebidOriginalAPINativeController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5397BD2D2937821D00ABDA22 /* PrebidOriginalAPINativeController.swift */; }; 53ED2FD529798104007D13EE /* AdapterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6EB3CC211336D300317ED9 /* AdapterViewController.swift */; }; @@ -400,6 +404,8 @@ 53A651832AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidOriginalAPIMultiformatNativeStylesController.swift; sourceTree = ""; }; 53BFCD022CF792FB00A3287A /* SampleCustomAdViewRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleCustomAdViewRenderer.swift; sourceTree = ""; }; 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAdView.swift; sourceTree = ""; }; + 53BFCD122CF9C67400A3287A /* SampleInterstitialController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleInterstitialController.swift; sourceTree = ""; }; + 53BFCD162CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleCustomInterstitialRenderer.swift; sourceTree = ""; }; 53ED304329798104007D13EE /* InternalTestApp-Skadn.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "InternalTestApp-Skadn.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 53ED305129798DBC007D13EE /* Info-Skadn.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Skadn.plist"; sourceTree = ""; }; 5B03D44524F5455F002F2B35 /* PBMGAMBannerEventHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PBMGAMBannerEventHandlerTests.swift; sourceTree = ""; }; @@ -708,8 +714,7 @@ 3CC4A3E72C11F93A00B97128 /* CustomRenderer */ = { isa = PBXGroup; children = ( - 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */, - 53BFCD022CF792FB00A3287A /* SampleCustomAdViewRenderer.swift */, + 53BFCD152CF9C68000A3287A /* Renderers */, 3CC4A3E82C11F96800B97128 /* CustomRendererBannerController.swift */, 3C28C9D72C35713B00D0A7DB /* CustomRendererInterstitialController.swift */, ); @@ -735,6 +740,17 @@ path = OriginalAPI; sourceTree = ""; }; + 53BFCD152CF9C68000A3287A /* Renderers */ = { + isa = PBXGroup; + children = ( + 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */, + 53BFCD022CF792FB00A3287A /* SampleCustomAdViewRenderer.swift */, + 53BFCD122CF9C67400A3287A /* SampleInterstitialController.swift */, + 53BFCD162CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift */, + ); + path = Renderers; + sourceTree = ""; + }; 5B1BDB782100D59000B46B43 /* Resources */ = { isa = PBXGroup; children = ( @@ -1565,6 +1581,7 @@ 53ED2FD929798104007D13EE /* PrebidGAMInterstitialController.swift in Sources */, 53ED2FDA29798104007D13EE /* PrebidMAXRewardedController.swift in Sources */, 53ED2FDB29798104007D13EE /* PrebidMAXNativeController.swift in Sources */, + 53BFCD142CF9C67400A3287A /* SampleInterstitialController.swift in Sources */, 53ED2FDC29798104007D13EE /* PrebidMAXBannerController.swift in Sources */, 53ED2FDD29798104007D13EE /* IABConsentHelper.swift in Sources */, 53ED2FDE29798104007D13EE /* PrebidNativeAdController.swift in Sources */, @@ -1614,6 +1631,7 @@ 53ED300729798104007D13EE /* PrebidFeedTableViewController.swift in Sources */, 53ED300829798104007D13EE /* TestCasesViewController.swift in Sources */, 53ED300929798104007D13EE /* NativeAdViewBoxLinks.swift in Sources */, + 53BFCD172CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift in Sources */, 53ED300A29798104007D13EE /* PrebidGAMRewardedController.swift in Sources */, 539F961529DEF2670061E7A5 /* PrebidOriginalAPIVideoInterstitialController.swift in Sources */, 53A369092AB996EF00A03B3E /* PrebidMultiformatConfigurationController.swift in Sources */, @@ -1663,6 +1681,7 @@ 34BA95FE249CBF05006AE372 /* PrebidGAMInterstitialController.swift in Sources */, 92221CE52804BBB6005DF671 /* PrebidMAXRewardedController.swift in Sources */, 92986537280604E4007A2F34 /* PrebidMAXNativeController.swift in Sources */, + 53BFCD132CF9C67400A3287A /* SampleInterstitialController.swift in Sources */, 9289873F28003C250062BFAA /* PrebidMAXBannerController.swift in Sources */, 34BAD451239547420042DB33 /* IABConsentHelper.swift in Sources */, 92102C7227B11B67003F12B2 /* PrebidNativeAdController.swift in Sources */, @@ -1712,6 +1731,7 @@ ACAF055724D8384B0089DFB1 /* PrebidFeedTableViewController.swift in Sources */, 5B3EEDDF2101EA9200BAA0C4 /* TestCasesViewController.swift in Sources */, 92F9A5D227A15D04007B0B17 /* NativeAdViewBoxLinks.swift in Sources */, + 53BFCD182CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift in Sources */, 34FC0CF624ADD5640045553E /* PrebidGAMRewardedController.swift in Sources */, 539F961429DEF2670061E7A5 /* PrebidOriginalAPIVideoInterstitialController.swift in Sources */, 53A369082AB996EF00A03B3E /* PrebidMultiformatConfigurationController.swift in Sources */, diff --git a/InternalTestApp/PrebidMobileDemoRendering/Model/TestCasesManager.swift b/InternalTestApp/PrebidMobileDemoRendering/Model/TestCasesManager.swift index 58b485eb2..781ad0c1a 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/Model/TestCasesManager.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/Model/TestCasesManager.swift @@ -583,7 +583,7 @@ struct TestCaseManager { setupCustomParams(for: bannerController.prebidConfigId) }), - TestCase(title: "Banner 320x50 (CustomRenderer)", + TestCase(title: "Banner 320x50 (In-App, Custom Renderer)", tags: [.banner, .inapp, .server], exampleVCStoryboardID: "AdapterViewController", configurationClosure: { vc in @@ -593,7 +593,7 @@ struct TestCaseManager { let bannerController = CustomRendererBannerController(rootController: adapterVC) bannerController.adSizes = [CGSize(width: 320, height: 50)] - bannerController.prebidConfigId = "prebid-ita-banner-320-50-meta-custom-banner-view-renderer" + bannerController.prebidConfigId = "prebid-demo-display-banner-320-50-custom-ad-view-renderer" adapterVC.setup(adapter: bannerController) setupCustomParams(for: bannerController.prebidConfigId) @@ -1028,6 +1028,23 @@ struct TestCaseManager { setupCustomParams(for: interstitialController.prebidConfigId) }), + TestCase(title: "Display Interstitial 320x480 (In-App, Custom Renderer)", + tags: [.interstitial, .inapp, .server], + exampleVCStoryboardID: "AdapterViewController", + configurationClosure: { vc in + guard let adapterVC = vc as? AdapterViewController else { + return + } + + let interstitialController = CustomRendererInterstitialController(rootController: adapterVC) + interstitialController.adFormats = [.banner] + interstitialController.prebidConfigId = "prebid-demo-display-interstitial-320-480-custom-interstitial-renderer" + + adapterVC.setup(adapter: interstitialController) + + setupCustomParams(for: interstitialController.prebidConfigId) + }), + TestCase(title: "Display Interstitial 320x480 (In-App) [noBids]", tags: [.interstitial, .inapp, .server], exampleVCStoryboardID: "AdapterViewController", diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererInterstitialController.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererInterstitialController.swift index dd6b83da4..ca351d64b 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererInterstitialController.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererInterstitialController.swift @@ -29,7 +29,7 @@ class CustomRendererInterstitialController: var adFormats: Set? private var interstitialController : InterstitialRenderingAdUnit? - private let sampleCustomRenderer = SampleCustomAdViewRenderer() + private let sampleCustomRenderer = SampleCustomInterstitialRenderer() private weak var adapterViewController: AdapterViewController? diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/SampleAdView.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdView.swift similarity index 100% rename from InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/SampleAdView.swift rename to InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdView.swift diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/SampleCustomAdViewRenderer.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomAdViewRenderer.swift similarity index 92% rename from InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/SampleCustomAdViewRenderer.swift rename to InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomAdViewRenderer.swift index ef293f6be..1b752702c 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/SampleCustomAdViewRenderer.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomAdViewRenderer.swift @@ -1,4 +1,4 @@ -/*   Copyright 2018-2021 Prebid.org, Inc. +/*   Copyright 2018-2024 Prebid.org, Inc.  Licensed under the Apache License, Version 2.0 (the "License");  you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ public class SampleCustomAdViewRenderer: NSObject, PrebidMobileAdViewPluginRende public var data: [AnyHashable: Any]? public func isSupportRendering(for format: AdFormat?) -> Bool { - AdFormat.allCases.contains(where: { $0 == format }) + [AdFormat.banner, AdFormat.video].contains(format) } public func createAdView( diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomInterstitialRenderer.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomInterstitialRenderer.swift new file mode 100644 index 000000000..4f5888e9c --- /dev/null +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomInterstitialRenderer.swift @@ -0,0 +1,46 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + + 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 UIKit +import PrebidMobile + +class SampleCustomInterstitialRenderer: PrebidMobileInterstitialPluginRenderer { + + var name = "SampleCustomInterstitialRenderer" + var version = "1.0.0" + var data: [AnyHashable : Any]? + + func isSupportRendering(for format: PrebidMobile.AdFormat?) -> Bool { + [AdFormat.banner, AdFormat.video].contains(format) + } + + func createInterstitialController( + bid: Bid, + adConfiguration: AdUnitConfig, + loadingDelegate: (any InterstitialControllerLoadingDelegate)?, + interactionDelegate: (any InterstitialControllerInteractionDelegate)? + ) -> any InterstitialControllerProtocol { + + let interstitialController = SampleInterstitialController() + interstitialController.loadingDelegate = loadingDelegate + interstitialController.interactionDelegate = interactionDelegate + + if let adm = bid.adm { + interstitialController.htmlContent = adm + } + + return interstitialController + } +} diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialController.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialController.swift new file mode 100644 index 000000000..ae3a5d948 --- /dev/null +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialController.swift @@ -0,0 +1,98 @@ +/*   Copyright 2018-2021 Prebid.org, Inc. + +  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 UIKit +import WebKit + +import PrebidMobile + +class SampleInterstitialController: NSObject, InterstitialControllerProtocol { + + weak var loadingDelegate: InterstitialControllerLoadingDelegate? + weak var interactionDelegate: InterstitialControllerInteractionDelegate? + + var htmlContent: String? + + private var webView: WKWebView = { + let webView = WKWebView(frame: CGRect(origin: .zero, size: CGSize(width: 300, height: 250))) + webView.translatesAutoresizingMaskIntoConstraints = false + webView.backgroundColor = .blue + return webView + }() + + private var customRendererLabel: UILabel = { + let label = UILabel() + label.text = "Custom Renderer" + label.textAlignment = .center + label.font = UIFont.boldSystemFont(ofSize: 18) + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + private lazy var interstitialViewController: UIViewController? = { + let viewController = UIViewController() + viewController.view.backgroundColor = .white + + viewController.view.addSubview(customRendererLabel) + viewController.view.addSubview(webView) + + NSLayoutConstraint.activate([ + customRendererLabel.topAnchor.constraint(equalTo: viewController.view.safeAreaLayoutGuide.topAnchor, constant: 20), + customRendererLabel.centerXAnchor.constraint(equalTo: viewController.view.centerXAnchor), + webView.centerXAnchor.constraint(equalTo: viewController.view.centerXAnchor), + webView.centerYAnchor.constraint(equalTo: viewController.view.centerYAnchor), + webView.widthAnchor.constraint(equalToConstant: 300), + webView.heightAnchor.constraint(equalToConstant: 250), + ]) + + return viewController + }() + + private var topViewController: UIViewController? { + var topController = UIApplication.shared.keyWindow?.rootViewController + while let presentedController = topController?.presentedViewController { + topController = presentedController + } + return topController + } + + func loadAd() { + guard let htmlContent else { + print("Error: HTML content is not set.") + return + } + + DispatchQueue.main.async { + self.webView.loadHTMLString(htmlContent, baseURL: nil) + self.loadingDelegate?.interstitialControllerDidLoadAd(self) + } + } + + func show() { + DispatchQueue.main.async { + guard let presentingController = self.topViewController else { + print("Error: Unable to find a top view controller.") + return + } + + guard let viewController = self.interstitialViewController else { + print("Error: Failed to create interstitial view controller. Make sure HTML content is set and loadAd is called.") + return + } + + presentingController.present(viewController, animated: true, completion: nil) + } + } +} diff --git a/PrebidMobile.xcodeproj/project.pbxproj b/PrebidMobile.xcodeproj/project.pbxproj index 133361aa3..7dcd342a8 100644 --- a/PrebidMobile.xcodeproj/project.pbxproj +++ b/PrebidMobile.xcodeproj/project.pbxproj @@ -144,6 +144,8 @@ 53BDBF89293F5EFF004B6DE8 /* InternalUserConsentDataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 53BDBF88293F5EFF004B6DE8 /* InternalUserConsentDataManager.m */; }; 53BDBF8A293F605B004B6DE8 /* InternalUserConsentDataManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 53BDBF87293F5EF6004B6DE8 /* InternalUserConsentDataManager.h */; }; 53BDBF8C293F6573004B6DE8 /* InternalUserConsentDataManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BDBF8B293F6573004B6DE8 /* InternalUserConsentDataManagerTests.swift */; }; + 53BFCD0F2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD0E2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift */; }; + 53BFCD112CF9156000A3287A /* InterstitialControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD102CF9155E00A3287A /* InterstitialControllerProtocol.swift */; }; 53C8FE1729C0851300ED9230 /* ClickbrowserType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C8FE1629C0851300ED9230 /* ClickbrowserType.swift */; }; 53C925022990FB30009E6F94 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C925012990FB30009E6F94 /* String+Extensions.swift */; }; 53C925052990FBFB009E6F94 /* PrebidServerStatusRequester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C925042990FBFB009E6F94 /* PrebidServerStatusRequester.swift */; }; @@ -1033,6 +1035,8 @@ 53BDBF87293F5EF6004B6DE8 /* InternalUserConsentDataManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InternalUserConsentDataManager.h; sourceTree = ""; }; 53BDBF88293F5EFF004B6DE8 /* InternalUserConsentDataManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InternalUserConsentDataManager.m; sourceTree = ""; }; 53BDBF8B293F6573004B6DE8 /* InternalUserConsentDataManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalUserConsentDataManagerTests.swift; sourceTree = ""; }; + 53BFCD0E2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidInterstitialControllerRenderer.swift; sourceTree = ""; }; + 53BFCD102CF9155E00A3287A /* InterstitialControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterstitialControllerProtocol.swift; sourceTree = ""; }; 53C8FE1629C0851300ED9230 /* ClickbrowserType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClickbrowserType.swift; sourceTree = ""; }; 53C925012990FB30009E6F94 /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = ""; }; 53C925042990FBFB009E6F94 /* PrebidServerStatusRequester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidServerStatusRequester.swift; sourceTree = ""; }; @@ -2437,10 +2441,12 @@ 5BC37788271F1CFE00444D5E /* PBMDisplayView+InternalState.h */, 5BC3778B271F1CFE00444D5E /* InterstitialControllerLoadingDelegate.swift */, 5BC3778D271F1CFE00444D5E /* InterstitialControllerInteractionDelegate.swift */, + 53BFCD102CF9155E00A3287A /* InterstitialControllerProtocol.swift */, 5BC3778E271F1CFE00444D5E /* InterstitialController.swift */, 5BC3778F271F1CFE00444D5E /* DisplayViewLoadingDelegate.swift */, 5BC37790271F1CFE00444D5E /* DisplayViewInteractionDelegate.swift */, A908694529E05F7900B37479 /* PrebidDisplayViewRenderer.swift */, + 53BFCD0E2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift */, ); path = PBMCacheRenderers; sourceTree = ""; @@ -4184,6 +4190,7 @@ 5BC37AC8271F1D0100444D5E /* PBMBasicParameterBuilder.m in Sources */, 9298652528058CEB007A2F34 /* MediationNativeUtils.swift in Sources */, 5BC3798F271F1D0000444D5E /* PBMCreativeModel.m in Sources */, + 53BFCD0F2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift in Sources */, 5BC37A6F271F1D0000444D5E /* PBMORTBAbstractResponse.m in Sources */, 5BC378AD271F1CFF00444D5E /* Targeting.swift in Sources */, 923B55002744F19600E00C88 /* PrebidMediationDelegate.swift in Sources */, @@ -4400,6 +4407,7 @@ 5BC37ABD271F1D0000444D5E /* PBMOpenMeasurementEventTracker.m in Sources */, 5BC37927271F1CFF00444D5E /* PBMFunctions.m in Sources */, 53842BB829E561750069A4B7 /* PrebidImagesRepository.swift in Sources */, + 53BFCD112CF9156000A3287A /* InterstitialControllerProtocol.swift in Sources */, 92C85D5A27A96AC50080BAC5 /* NativeTitle.swift in Sources */, 5BC37AA4271F1D0000444D5E /* PBMAdLoadFlowController.m in Sources */, 5BC378C0271F1CFF00444D5E /* NSDictionary+PBMExtensions.m in Sources */, diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift index a0294150e..03fd4b185 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift @@ -28,7 +28,8 @@ public class PrebidMobilePluginRegister: NSObject { private var plugins = [String: PrebidMobilePluginRenderer]() - private let defaultRenderer = PrebidDisplayViewRenderer() + private let defaultAdViewRenderer = PrebidDisplayViewRenderer() + private let defaultInterstitialRenderer = PrebidInterstitialControllerRenderer() private override init() { super.init() @@ -114,14 +115,17 @@ public class PrebidMobilePluginRegister: NSObject { /// Returns the registered renderer according to the preferred renderer name in the bid response /// If no preferred renderer is found, it returns PrebidRenderer to perform default behavior /// Once bid is win we want to resolve the best PluginRenderer candidate to render the ad - public func getPluginForPreferredRenderer(bid: Bid) -> PrebidMobilePluginRenderer { + public func getPluginForPreferredRenderer( + bid: Bid, + isInterstitial: Bool + ) -> PrebidMobilePluginRenderer { if let preferredRendererName = bid.pluginRendererName, let preferredPlugin = getPluginRenderer(for: preferredRendererName), preferredPlugin.version == bid.pluginRendererVersion, preferredPlugin.isSupportRendering(for: bid.adFormat) { return preferredPlugin } else { - return defaultRenderer + return isInterstitial ? defaultInterstitialRenderer : defaultAdViewRenderer } } diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift index e36ca4374..cffa24e05 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift @@ -76,7 +76,7 @@ public protocol PrebidMobileInterstitialPluginRenderer: PrebidMobilePluginRender func createInterstitialController( bid: Bid, adConfiguration: AdUnitConfig, - adViewManagerDelegate: InterstitialController?, - videoControlsConfig: VideoControlsConfiguration? - ) + loadingDelegate: InterstitialControllerLoadingDelegate?, + interactionDelegate: InterstitialControllerInteractionDelegate? + ) -> InterstitialControllerProtocol } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m index 2b0000333..eecb1512a 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m @@ -127,7 +127,8 @@ - (void)failedWithError:(nullable NSError *)error { // MARK: - Helpers - (void)setRendererWithBid:(Bid *)bid { - id render = [[PrebidMobilePluginRegister shared] getPluginForPreferredRendererWithBid:bid]; + id render = [[PrebidMobilePluginRegister shared] getPluginForPreferredRendererWithBid:bid + isInterstitial:false]; if ([render conformsToProtocol:@protocol(PrebidMobileAdViewPluginRenderer)]) { self.renderer = render; diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.h b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.h index 761d76898..5f261f58c 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.h +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.h @@ -18,6 +18,7 @@ #import "PBMAdLoaderProtocol.h" @protocol PBMInterstitialAdLoaderDelegate; +@protocol InterstitialControllerProtocol; NS_ASSUME_NONNULL_BEGIN diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m index 730ce78f3..671e90301 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m @@ -30,8 +30,8 @@ @interface PBMInterstitialAdLoader () -@property (nonatomic, weak, nullable, readonly) id delegate; -@property (nonatomic, weak, nullable, readonly) id eventHandler; +@property (nonatomic, weak, nullable, readonly) id delegate; +@property (nonatomic, strong, nullable) id renderer; @end @@ -41,9 +41,7 @@ @implementation PBMInterstitialAdLoader // MARK: - Lifecycle -- (instancetype)initWithDelegate:(id)delegate - eventHandler:(nonnull id)eventHandler { - +- (instancetype)initWithDelegate:(id)delegate { if (!(self = [super init])) { return nil; } @@ -63,25 +61,32 @@ - (instancetype)initWithDelegate:(id)delegate - (void)createPrebidAdWithBid:(Bid *)bid adUnitConfig:(AdUnitConfig *)adUnitConfig adObjectSaver:(void (^)(id))adObjectSaver - loadMethodInvoker:(void (^)(dispatch_block_t))loadMethodInvoker -{ - InterstitialController * const controller = [[InterstitialController alloc] initWithBid:bid - adConfiguration:adUnitConfig]; + loadMethodInvoker:(void (^)(dispatch_block_t))loadMethodInvoker { + + [self setRendererWithBid:bid]; + + if (!self.renderer) { + return; + } + + PBMLogInfo(@"Renderer: %@", self.renderer); + + id controller = [self.renderer + createInterstitialControllerWithBid:bid + adConfiguration:adUnitConfig + loadingDelegate:self + interactionDelegate:self.delegate]; + adObjectSaver(controller); - @weakify(self); + loadMethodInvoker(^{ - @strongify(self); - if (!self) { return; } - - controller.loadingDelegate = self; - [self.delegate interstitialAdLoader:self createdInterstitialController:controller]; [controller loadAd]; }); } - (void)reportSuccessWithAdObject:(id)adObject adSize:(nullable NSValue *)adSize { - if ([adObject isKindOfClass:[InterstitialController class]]) { - InterstitialController * const controller = (InterstitialController *)adObject; + if ([adObject conformsToProtocol:@protocol(InterstitialControllerProtocol)]) { + id controller = (id)adObject; [self.delegate interstitialAdLoader:self loadedAd:^(UIViewController *targetController) { [controller show]; @@ -110,11 +115,12 @@ - (void)reportSuccessWithAdObject:(id)adObject adSize:(nullable NSValue *)adSize // MARK: - InterstitialControllerLoadingDelegate -- (void)interstitialControllerDidLoadAd:(InterstitialController *)interstitialController { +- (void)interstitialControllerDidLoadAd:(id)interstitialController { [self.flowDelegate adLoaderLoadedPrebidAd:self]; } -- (void)interstitialController:(InterstitialController *)interstitialController didFailWithError:(NSError *)error { +- (void)interstitialController:(id)interstitialController + didFailWithError:(NSError *)error { [self.flowDelegate adLoader:self failedWithPrebidError:error]; } @@ -132,4 +138,15 @@ - (void)failedWithError:(nullable NSError *)error { [self.flowDelegate adLoader:self failedWithPrimarySDKError:error]; } +// MARK: - Helpers + +- (void)setRendererWithBid:(Bid *)bid { + id render = [[PrebidMobilePluginRegister shared] getPluginForPreferredRendererWithBid:bid + isInterstitial:true]; + + if ([render conformsToProtocol:@protocol(PrebidMobileInterstitialPluginRenderer)]) { + self.renderer = render; + } +} + @end diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BannerView.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BannerView.swift index c18417e13..277761187 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BannerView.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BannerView.swift @@ -439,7 +439,7 @@ public class BannerView: // MARK: - DisplayViewInteractionDelegate - public func trackImpression(for displayView: UIView) { + public func trackImpression(forDisplayView: UIView) { guard let eventHandler = self.eventHandler, eventHandler.responds(to: #selector(BannerEventHandler.trackImpression)) else { return @@ -448,7 +448,7 @@ public class BannerView: eventHandler.trackImpression() } - public func viewControllerForModalPresentation(from displayView: UIView) -> UIViewController? { + public func viewControllerForModalPresentation(fromDisplayView: UIView) -> UIViewController? { return viewControllerForPresentingModal } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnit.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnit.swift index d56b10cfd..e80429585 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnit.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnit.swift @@ -189,40 +189,54 @@ class BaseInterstitialAdUnit: // MARK: - InterstitialControllerInteractionDelegate /// Tracks an impression for the given interstitial controller. - public func trackImpression(forInterstitialController: InterstitialController) { + public func trackImpression(forInterstitialController: InterstitialControllerProtocol) { DispatchQueue.main.async { self.delegate?.callEventHandler_trackImpression() } } /// Called when the ad in the interstitial controller is clicked. - public func interstitialControllerDidClickAd(_ interstitialController: InterstitialController) { + public func interstitialControllerDidClickAd(_ interstitialController: InterstitialControllerProtocol) { assert(Thread.isMainThread, "Expected to only be called on the main thread") delegate?.callDelegate_didClickAd() } /// Called when the ad in the interstitial controller is closed. - public func interstitialControllerDidCloseAd(_ interstitialController: InterstitialController) { + public func interstitialControllerDidCloseAd(_ interstitialController: InterstitialControllerProtocol) { assert(Thread.isMainThread, "Expected to only be called on the main thread") delegate?.callDelegate_didDismissAd() } /// Called when the ad in the interstitial controller causes the app to leave. - public func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialController) { + public func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialControllerProtocol) { assert(Thread.isMainThread, "Expected to only be called on the main thread") delegate?.callDelegate_willLeaveApplication() } - public func interstitialControllerDidDisplay(_ interstitialController: InterstitialController) {} - public func interstitialControllerDidComplete(_ interstitialController: InterstitialController) {} - public func trackUserReward(_ interstitialController: InterstitialController, _ reward: PrebidReward) {} + public func interstitialControllerDidDisplay(_ interstitialController: InterstitialControllerProtocol) {} + public func interstitialControllerDidComplete(_ interstitialController: InterstitialControllerProtocol) {} + public func trackUserReward(_ interstitialController: InterstitialControllerProtocol, _ reward: PrebidReward) {} public func viewControllerForModalPresentation( - fromInterstitialController: InterstitialController + fromInterstitialController: InterstitialControllerProtocol ) -> UIViewController? { return targetController } + // MARK: - Private methods + + private func reportLoadingSuccess() { + DispatchQueue.main.async { + self.callDelegate_didReceiveAd() + } + } + + private func reportLoadingFailed(with error: Error?) { + DispatchQueue.main.async { + self.callDelegate_didFailToReceiveAd(with: error) + } + } + // MARK: - InterstitialEventInteractionDelegate /// Called when an ad is about to be presented. diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnitProtocol.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnitProtocol.swift index 308bdc29f..66db775d5 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnitProtocol.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnitProtocol.swift @@ -13,12 +13,12 @@  limitations under the License.  */ -import Foundation import UIKit -@objc protocol BaseInterstitialAdUnitProtocol: NSObjectProtocol { +@objc +public protocol BaseInterstitialAdUnitProtocol: NSObjectProtocol { - @objc func interstitialControllerDidCloseAd(_ interstitialController: InterstitialController) + @objc func interstitialControllerDidCloseAd(_ interstitialController: InterstitialControllerProtocol) @objc func callDelegate_didReceiveAd() @objc func callDelegate_didFailToReceiveAd(with error: Error?) diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedAdUnit.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedAdUnit.swift index 6f7cc158b..62f4bc88d 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedAdUnit.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedAdUnit.swift @@ -203,34 +203,14 @@ public class RewardedAdUnit: NSObject, BaseInterstitialAdUnitProtocol { addExtData(key: key, value: data) } - /// Updates context data for a specified key. - /// - Parameters: - /// - data: A set of data to update. - /// - key: The key associated with the data. - @available(*, deprecated, message: "This method is deprecated. Please, use updateExtData method instead.") - public func updateContextData(_ data: Set, forKey key: String) { - updateExtData(key: key, value: data) - } + // MARK: - BaseInterstitialAdUnitProtocol protocol - /// Removes context data for a specified key. - /// - Parameter key: The key associated with the data to remove. - @available(*, deprecated, message: "This method is deprecated. Please, use removeExtData method instead.") - public func removeContextDate(forKey key: String) { - removeExtData(forKey: key) - } - - /// Clears all context data. - @available(*, deprecated, message: "This method is deprecated. Please, use clearExtData method instead.") - public func clearContextData() { - clearExtData() - } - - /// Adds ext data. - /// - Parameters: - /// - key: The key for the data. - /// - value: The value for the data. - public func addExtData(key: String, value: String) { - adUnitConfig.addExtData(key: key, value: value) + /// Called when the interstitial ad is closed. + /// + /// - Parameter interstitialController: The controller managing the interstitial ad. + @objc public override func interstitialControllerDidCloseAd(_ interstitialController: InterstitialControllerProtocol) { + callDelegate_rewardedAdUserDidEarnReward() + super.interstitialControllerDidCloseAd(interstitialController) } /// Updates ext data. diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewInteractionDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewInteractionDelegate.swift index 65072430b..fc8f7e5c7 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewInteractionDelegate.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewInteractionDelegate.swift @@ -18,9 +18,9 @@ import UIKit @objc public protocol DisplayViewInteractionDelegate: NSObjectProtocol { - func trackImpression(for displayView: UIView) + func trackImpression(forDisplayView: UIView) - func viewControllerForModalPresentation(from displayView: UIView) -> UIViewController? + func viewControllerForModalPresentation(fromDisplayView: UIView) -> UIViewController? func didLeaveApp(from displayView: UIView) diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewLoadingDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewLoadingDelegate.swift index 6a9cdf32a..317ba48cd 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewLoadingDelegate.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewLoadingDelegate.swift @@ -17,6 +17,7 @@ import UIKit @objc public protocol DisplayViewLoadingDelegate: NSObjectProtocol { + func displayViewDidLoadAd(_ displayView: UIView) func displayView(_ displayView: UIView, didFailWithError error: Error) } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController.swift index e89d6a8f9..582ae37c8 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController.swift @@ -1,25 +1,27 @@ /*   Copyright 2018-2021 Prebid.org, Inc. - - 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. - */ + +  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 UIKit -public class InterstitialController: NSObject, PBMAdViewManagerDelegate { - - private var renderer: PrebidMobileInterstitialPluginRenderer? +@objcMembers +public class InterstitialController: + NSObject, + InterstitialControllerProtocol, + PBMAdViewManagerDelegate { - @objc public var adFormats: Set { + public var adFormats: Set { get { adConfiguration.adFormats } set { adConfiguration.adFormats = newValue } } @@ -30,52 +32,81 @@ public class InterstitialController: NSObject, PBMAdViewManagerDelegate { set { adConfiguration.adConfiguration.isRewarded = newValue } } - @objc public var videoControlsConfig: VideoControlsConfiguration { + public var videoControlsConfig: VideoControlsConfiguration { get { adConfiguration.adConfiguration.videoControlsConfig } set { adConfiguration.adConfiguration.videoControlsConfig = newValue } } - @objc public var videoParameters: VideoParameters { + public var videoParameters: VideoParameters { get { adConfiguration.adConfiguration.videoParameters } set { adConfiguration.adConfiguration.videoParameters = newValue } } - @objc public weak var loadingDelegate: InterstitialControllerLoadingDelegate? - @objc public weak var interactionDelegate: InterstitialControllerInteractionDelegate? + public weak var loadingDelegate: InterstitialControllerLoadingDelegate? + public weak var interactionDelegate: InterstitialControllerInteractionDelegate? var bid: Bid var adConfiguration: AdUnitConfig var displayProperties: PBMInterstitialDisplayProperties + var transactionFactory: PBMTransactionFactory? var adViewManager: PBMAdViewManager? // MARK: - Life cycle - @objc public init(bid: Bid, adConfiguration: AdUnitConfig) { + public init(bid: Bid, adConfiguration: AdUnitConfig) { self.bid = bid self.adConfiguration = adConfiguration displayProperties = PBMInterstitialDisplayProperties() } - @objc public convenience init(bid: Bid, configId: String) { + public convenience init(bid: Bid, configId: String) { let adConfig = AdUnitConfig(configId: configId) adConfig.adConfiguration.isInterstitialAd = true adConfig.adConfiguration.isRewarded = bid.rewardedConfig != nil self.init(bid: bid, adConfiguration: adConfig) } - // TODO: provide a more relevant name for this function. - @objc public func loadAd() { - renderer = PrebidMobilePluginRegister.shared.getPluginForPreferredRenderer(bid: bid) as? PrebidMobileInterstitialPluginRenderer - renderer?.createInterstitialController( + public func loadAd() { + guard transactionFactory == nil else { + return + } + + adConfiguration.adConfiguration.winningBidAdFormat = bid.adFormat + videoControlsConfig.initialize(with: bid.videoAdConfiguration) + + // This part is dedicating to test server-side ad configurations. + // Need to be removed when ext.prebid.passthrough will be available. + #if DEBUG + adConfiguration.adConfiguration.videoControlsConfig.initialize(with: bid.testVideoAdConfiguration) + #endif + + transactionFactory = PBMTransactionFactory( bid: bid, adConfiguration: adConfiguration, - adViewManagerDelegate: self, - videoControlsConfig: videoControlsConfig - ) - } - - @objc public func show() { + connection: PrebidServerConnection.shared, + callback: { [weak self] transaction, error in + + if let transaction = transaction { + self?.display(transaction: transaction) + } else { + self?.reportFailureWithError(error) + } + }) + + PBMWinNotifier.notifyThroughConnection( + PrebidServerConnection.shared, + winning: bid, + callback: { [weak self] adMarkup in + if let adMarkup = adMarkup { + self?.transactionFactory?.load(withAdMarkup: adMarkup) + } else { + Log.error("No ad markup received from server.") + } + }) + } + + public func show() { if let adViewManager = adViewManager { adViewManager.show() } @@ -83,62 +114,49 @@ public class InterstitialController: NSObject, PBMAdViewManagerDelegate { // MARK: - PBMAdViewManagerDelegate protocol - @objc public func viewControllerForModalPresentation() -> UIViewController? { - if let interactionDelegate = interactionDelegate { - return interactionDelegate.viewControllerForModalPresentation(fromInterstitialController: self) - } else { - return nil - } + public func viewControllerForModalPresentation() -> UIViewController? { + interactionDelegate?.viewControllerForModalPresentation(fromInterstitialController: self) } - - @objc public func adLoaded(_ pbmAdDetails: PBMAdDetails) { + + public func adLoaded(_ pbmAdDetails: PBMAdDetails) { reportSuccess() } - - @objc public func failed(toLoad error: Error) { + + public func failed(toLoad error: Error) { reportFailureWithError(error) } - - @objc public func adDidComplete() { + + public func adDidComplete() { if let delegate = interactionDelegate { delegate.interstitialControllerDidComplete(self) } } - @objc public func adDidDisplay() { + public func adDidDisplay() { if let delegate = interactionDelegate { delegate.interstitialControllerDidDisplay(self) } } - @objc public func adWasClicked() { + public func adWasClicked() { if let delegate = interactionDelegate { delegate.interstitialControllerDidClickAd(self) } } - @objc public func adViewWasClicked() { + public func adViewWasClicked() { if let delegate = interactionDelegate { delegate.interstitialControllerDidClickAd(self) } } - @objc public func adDidExpand() { - } - - @objc public func adDidCollapse() { - } - - @objc public func adDidLeaveApp() { + public func adDidLeaveApp() { if let delegate = interactionDelegate { delegate.interstitialControllerDidLeaveApp(self) } } - @objc public func adClickthroughDidClose() { - } - - @objc public func adDidClose() { + public func adDidClose() { adViewManager = nil if let delegate = interactionDelegate { delegate.interstitialControllerDidCloseAd(self) @@ -151,10 +169,20 @@ public class InterstitialController: NSObject, PBMAdViewManagerDelegate { } } + @objc public func adDidSendRewardedEvent() { + if let delegate = interactionDelegate { + delegate.trackUserReward?(self, PrebidReward(with: bid.rewardedConfig?.reward)) + } + } + @objc public func interstitialDisplayProperties() -> PBMInterstitialDisplayProperties { displayProperties } + public func adClickthroughDidClose() {} + public func adDidExpand() {} + public func adDidCollapse() {} + // MARK: - Private Helpers @available(*, unavailable) @@ -168,16 +196,18 @@ public class InterstitialController: NSObject, PBMAdViewManagerDelegate { loadingDelegate.interstitialController(self, didFailWithError: error) } } - + func reportSuccess() { if let loadingDelegate = loadingDelegate { loadingDelegate.interstitialControllerDidLoadAd(self) } } - - public func display(transaction: PBMTransaction) { - adViewManager = PBMAdViewManager(connection: PrebidServerConnection.shared, - modalManagerDelegate: nil) + + private func display(transaction: PBMTransaction) { + adViewManager = PBMAdViewManager( + connection: PrebidServerConnection.shared, + modalManagerDelegate: nil + ) adViewManager?.adViewManagerDelegate = self adViewManager?.adConfiguration.isInterstitialAd = true adViewManager?.adConfiguration.isRewarded = adConfiguration.adConfiguration.isRewarded diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerInteractionDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerInteractionDelegate.swift index 12655b8b3..e81477881 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerInteractionDelegate.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerInteractionDelegate.swift @@ -15,17 +15,18 @@ import UIKit -@objc public protocol InterstitialControllerInteractionDelegate: NSObjectProtocol { +@objc +public protocol InterstitialControllerInteractionDelegate: NSObjectProtocol { - func trackImpression(forInterstitialController: InterstitialController) + @objc func trackImpression(forInterstitialController: InterstitialControllerProtocol) - func interstitialControllerDidClickAd(_ interstitialController: InterstitialController) - func interstitialControllerDidCloseAd(_ interstitialController: InterstitialController) - func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialController) - func interstitialControllerDidDisplay(_ interstitialController: InterstitialController) - func interstitialControllerDidComplete(_ interstitialController: InterstitialController) + @objc func interstitialControllerDidClickAd(_ interstitialController: InterstitialControllerProtocol) + @objc func interstitialControllerDidCloseAd(_ interstitialController: InterstitialControllerProtocol) + @objc func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialControllerProtocol) + @objc func interstitialControllerDidDisplay(_ interstitialController: InterstitialControllerProtocol) + @objc func interstitialControllerDidComplete(_ interstitialController: InterstitialControllerProtocol) - func viewControllerForModalPresentation(fromInterstitialController: InterstitialController) -> UIViewController? + @objc func viewControllerForModalPresentation(fromInterstitialController: InterstitialControllerProtocol) -> UIViewController? - @objc optional func trackUserReward(_ interstitialController: InterstitialController, _ reward: PrebidReward) + @objc optional func trackUserReward(_ interstitialController: InterstitialControllerProtocol, _ reward: PrebidReward) } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerLoadingDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerLoadingDelegate.swift index 6b6c55213..722966e8a 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerLoadingDelegate.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerLoadingDelegate.swift @@ -15,9 +15,10 @@ import Foundation -@objc public protocol InterstitialControllerLoadingDelegate: NSObjectProtocol { +@objc +public protocol InterstitialControllerLoadingDelegate: NSObjectProtocol { - func interstitialControllerDidLoadAd(_ interstitialController: InterstitialController) - func interstitialController(_ interstitialController: InterstitialController, + func interstitialControllerDidLoadAd(_ interstitialController: InterstitialControllerProtocol) + func interstitialController(_ interstitialController: InterstitialControllerProtocol, didFailWithError error: Error) } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerProtocol.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerProtocol.swift new file mode 100644 index 000000000..5bdce08d1 --- /dev/null +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerProtocol.swift @@ -0,0 +1,23 @@ +/*   Copyright 2018-2021 Prebid.org, Inc. + + 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 Foundation + +@objc +public protocol InterstitialControllerProtocol: NSObjectProtocol { + + func loadAd() + func show() +} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.m b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.m index ab5e1438a..c77626768 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.m @@ -109,7 +109,7 @@ - (BOOL)isCreativeOpened { // MARK: - PBMAdViewManagerDelegate protocol - (UIViewController *)viewControllerForModalPresentation { - return [self.interactionDelegate viewControllerForModalPresentationFrom:self]; + return [self.interactionDelegate viewControllerForModalPresentationFromDisplayView:self]; } - (void)adLoaded:(PBMAdDetails *)pbmAdDetails { @@ -126,7 +126,7 @@ - (void)adDidComplete { } - (void)adDidDisplay { - [self.interactionDelegate trackImpressionFor:self]; + [self.interactionDelegate trackImpressionForDisplayView:self]; } - (void)adWasClicked { diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidDisplayViewRenderer.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidDisplayViewRenderer.swift index 94701807d..fb2513ba5 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidDisplayViewRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidDisplayViewRenderer.swift @@ -22,13 +22,9 @@ public class PrebidDisplayViewRenderer: NSObject, PrebidMobileAdViewPluginRender public var data: [AnyHashable: Any]? public func isSupportRendering(for format: AdFormat?) -> Bool { - AdFormat.allCases.contains(where: { $0 == format }) + [AdFormat.banner, AdFormat.video].contains(format) } - private var transactionFactory: PBMTransactionFactory? - private var adViewManager: PBMAdViewManager? - private var connection = PrebidServerConnection.shared - public func createAdView( with frame: CGRect, bid: Bid, diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidInterstitialControllerRenderer.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidInterstitialControllerRenderer.swift new file mode 100644 index 000000000..af13cb2e7 --- /dev/null +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidInterstitialControllerRenderer.swift @@ -0,0 +1,46 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 Foundation + +public class PrebidInterstitialControllerRenderer: + NSObject, + PrebidMobileInterstitialPluginRenderer { + + public var name = "PrebidInterstitialControllerRenderer" + public var version = "1.0.0" + public var data: [AnyHashable: Any]? + + public func isSupportRendering(for format: AdFormat?) -> Bool { + [AdFormat.banner, AdFormat.video].contains(format) + } + + public func createInterstitialController( + bid: Bid, + adConfiguration: AdUnitConfig, + loadingDelegate: InterstitialControllerLoadingDelegate?, + interactionDelegate: InterstitialControllerInteractionDelegate? + ) -> InterstitialControllerProtocol { + let interstitialController = InterstitialController( + bid: bid, + adConfiguration: adConfiguration + ) + + interstitialController.loadingDelegate = loadingDelegate + interstitialController.interactionDelegate = interactionDelegate + + return interstitialController + } +} From c1278ee54149f2570602b48885965a78121b29ac Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Mon, 2 Dec 2024 18:13:32 +0200 Subject: [PATCH 03/18] feat: introduce PrebidMobileDisplayViewProtocol and PrebidMobileInterstitialControllerProtocol --- .../Sources/PrebidAdMobBannerAdapter.swift | 4 +- .../PrebidAdMobInterstitialAdapter.swift | 18 +-- .../PrebidAdMobVideoInterstitialAdapter.swift | 18 +-- ...nterstitialAdapter+MARewardedAdapter.swift | 18 +-- .../Renderers/SampleAdView.swift | 29 +++-- .../SampleCustomAdViewRenderer.swift | 10 +- .../SampleCustomInterstitialRenderer.swift | 13 +-- .../SampleInterstitialController.swift | 41 +++++-- PrebidMobile.xcodeproj/project.pbxproj | 48 +++++--- .../BuildFiles/PrebidMobile.modulemap | 2 + .../BuildFiles/PrebidMobileSwiftHeaders.h | 2 + .../PrebidMobilePluginRenderer.swift | 103 ++++++++++-------- .../GAM/AdLoading/PBMBannerAdLoader.m | 21 ++-- .../GAM/AdLoading/PBMInterstitialAdLoader.h | 2 +- .../GAM/AdLoading/PBMInterstitialAdLoader.m | 23 ++-- .../Prebid/Integrations/GAM/BannerView.swift | 4 +- .../GAM/BaseInterstitialAdUnit.swift | 16 ++- .../GAM/BaseInterstitialAdUnitProtocol.swift | 2 +- .../Integrations/GAM/RewardedAdUnit.swift | 2 +- .../DisplayViewInteractionDelegate.swift | 53 +++++++++ .../DisplayViewLoadingDelegate.swift | 35 ++++++ .../PBMDisplayView+InternalState.h | 0 .../{ => DisplayView}/PBMDisplayView.h | 3 +- .../{ => DisplayView}/PBMDisplayView.m | 8 +- .../PrebidDisplayViewRenderer.swift | 6 +- .../PrebidMobileDisplayViewProtocol.h | 26 +++++ .../DisplayViewInteractionDelegate.swift | 30 ----- .../DisplayViewLoadingDelegate.swift | 23 ---- .../InterstitialController.swift | 2 +- ...stitialControllerInteractionDelegate.swift | 77 +++++++++++++ ...nterstitialControllerLoadingDelegate.swift | 39 +++++++ ...PrebidInterstitialControllerRenderer.swift | 6 +- ...MobileInterstitialControllerProtocol.swift | 29 +++++ ...nterstitialControllerLoadingDelegate.swift | 24 ---- .../InterstitialControllerProtocol.swift | 23 ---- 35 files changed, 503 insertions(+), 257 deletions(-) create mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewInteractionDelegate.swift create mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewLoadingDelegate.swift rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{ => DisplayView}/PBMDisplayView+InternalState.h (100%) rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{ => DisplayView}/PBMDisplayView.h (88%) rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{ => DisplayView}/PBMDisplayView.m (97%) rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{ => DisplayView}/PrebidDisplayViewRenderer.swift (89%) create mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PrebidMobileDisplayViewProtocol.h delete mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewInteractionDelegate.swift delete mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewLoadingDelegate.swift rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{ => InterstitialController}/InterstitialController.swift (99%) create mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerInteractionDelegate.swift create mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerLoadingDelegate.swift rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{ => InterstitialController}/PrebidInterstitialControllerRenderer.swift (92%) create mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/PrebidMobileInterstitialControllerProtocol.swift delete mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerLoadingDelegate.swift delete mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerProtocol.swift diff --git a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobBannerAdapter.swift b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobBannerAdapter.swift index 30019a1d6..f2b08544b 100644 --- a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobBannerAdapter.swift +++ b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobBannerAdapter.swift @@ -88,13 +88,13 @@ public class PrebidAdMobBannerAdapter: // MARK: - DisplayViewLoadingDelegate - public func displayViewDidLoadAd(_ displayView: UIView) { + public func displayViewDidLoadAd(_ displayViewManager: UIView) { if let handler = completionHandler { delegate = handler(self, nil) } } - public func displayView(_ displayView: UIView, didFailWithError error: Error) { + public func displayView(_ displayViewManager: UIView, didFailWithError error: Error) { if let handler = completionHandler { delegate = handler(nil, error) } diff --git a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobInterstitialAdapter.swift b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobInterstitialAdapter.swift index e82195d2c..22cc31250 100644 --- a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobInterstitialAdapter.swift +++ b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobInterstitialAdapter.swift @@ -95,7 +95,7 @@ public class PrebidAdMobInterstitialAdapter: // MARK: - InterstitialControllerLoadingDelegate - public func interstitialControllerDidLoadAd(_ interstitialController: InterstitialControllerProtocol) { + public func interstitialControllerDidLoadAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { adAvailable = true if let handler = completionHandler { @@ -104,7 +104,7 @@ public class PrebidAdMobInterstitialAdapter: } public func interstitialController( - _ interstitialController: InterstitialControllerProtocol, + _ interstitialController: PrebidMobileInterstitialControllerProtocol, didFailWithError error: Error ) { adAvailable = false @@ -116,29 +116,29 @@ public class PrebidAdMobInterstitialAdapter: // MARK: - InterstitialControllerInteractionDelegate - public func trackImpression(forInterstitialController: InterstitialControllerProtocol) { + public func trackImpression(forInterstitialController: PrebidMobileInterstitialControllerProtocol) { delegate?.reportImpression() } public func viewControllerForModalPresentation( - fromInterstitialController: InterstitialControllerProtocol + fromInterstitialController: PrebidMobileInterstitialControllerProtocol ) -> UIViewController? { rootViewController } - public func interstitialControllerDidClickAd(_ interstitialController: InterstitialControllerProtocol) { + public func interstitialControllerDidClickAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { delegate?.reportClick() } - public func interstitialControllerDidCloseAd(_ interstitialController: InterstitialControllerProtocol) { + public func interstitialControllerDidCloseAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { delegate?.willDismissFullScreenView() delegate?.didDismissFullScreenView() } - public func interstitialControllerDidDisplay(_ interstitialController: InterstitialControllerProtocol) { + public func interstitialControllerDidDisplay(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { delegate?.willPresentFullScreenView() } - public func interstitialControllerDidComplete(_ interstitialController: InterstitialControllerProtocol) {} - public func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialControllerProtocol) {} + public func interstitialControllerDidComplete(_ interstitialController: PrebidMobileInterstitialControllerProtocol) {} + public func interstitialControllerDidLeaveApp(_ interstitialController: PrebidMobileInterstitialControllerProtocol) {} } diff --git a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobVideoInterstitialAdapter.swift b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobVideoInterstitialAdapter.swift index a8cebe079..e7affda19 100644 --- a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobVideoInterstitialAdapter.swift +++ b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobVideoInterstitialAdapter.swift @@ -104,7 +104,7 @@ public class PrebidAdMobVideoInterstitialAdapter: // MARK: - InterstitialControllerLoadingDelegate public func interstitialControllerDidLoadAd( - _ interstitialController: InterstitialControllerProtocol + _ interstitialController: PrebidMobileInterstitialControllerProtocol ) { adAvailable = true @@ -114,7 +114,7 @@ public class PrebidAdMobVideoInterstitialAdapter: } public func interstitialController( - _ interstitialController: InterstitialControllerProtocol, + _ interstitialController: PrebidMobileInterstitialControllerProtocol, didFailWithError error: Error ) { adAvailable = false @@ -126,29 +126,29 @@ public class PrebidAdMobVideoInterstitialAdapter: // MARK: - InterstitialControllerInteractionDelegate - public func trackImpression(forInterstitialController: InterstitialControllerProtocol) { + public func trackImpression(forInterstitialController: PrebidMobileInterstitialControllerProtocol) { delegate?.reportImpression() } public func viewControllerForModalPresentation( - fromInterstitialController: InterstitialControllerProtocol + fromInterstitialController: PrebidMobileInterstitialControllerProtocol ) -> UIViewController? { rootViewController } - public func interstitialControllerDidClickAd(_ interstitialController: InterstitialControllerProtocol) { + public func interstitialControllerDidClickAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { delegate?.reportClick() } - public func interstitialControllerDidCloseAd(_ interstitialController: InterstitialControllerProtocol) { + public func interstitialControllerDidCloseAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { delegate?.willDismissFullScreenView() delegate?.didDismissFullScreenView() } - public func interstitialControllerDidDisplay(_ interstitialController: InterstitialControllerProtocol) { + public func interstitialControllerDidDisplay(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { delegate?.willPresentFullScreenView() } - public func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialControllerProtocol) {} - public func interstitialControllerDidComplete(_ interstitialController: InterstitialControllerProtocol) {} + public func interstitialControllerDidLeaveApp(_ interstitialController: PrebidMobileInterstitialControllerProtocol) {} + public func interstitialControllerDidComplete(_ interstitialController: PrebidMobileInterstitialControllerProtocol) {} } diff --git a/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAInterstitialAdapter+MARewardedAdapter.swift b/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAInterstitialAdapter+MARewardedAdapter.swift index 3c3c18a0b..749a1ea3b 100644 --- a/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAInterstitialAdapter+MARewardedAdapter.swift +++ b/EventHandlers/PrebidMobileMAXAdapters/Sources/PrebidMAXMediationAdapter+MAInterstitialAdapter+MARewardedAdapter.swift @@ -121,14 +121,14 @@ extension PrebidMAXMediationAdapter: MAInterstitialAdapter, // MARK: - InterstitialControllerLoadingDelegate - public func interstitialControllerDidLoadAd(_ interstitialController: InterstitialControllerProtocol) { + public func interstitialControllerDidLoadAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { interstitialAdAvailable = true interstitialDelegate?.didLoadInterstitialAd() rewardedDelegate?.didLoadRewardedAd() } public func interstitialController( - _ interstitialController: InterstitialControllerProtocol, + _ interstitialController: PrebidMobileInterstitialControllerProtocol, didFailWithError error: Error ) { interstitialAdAvailable = false @@ -139,32 +139,32 @@ extension PrebidMAXMediationAdapter: MAInterstitialAdapter, // MARK: - InterstitialControllerInteractionDelegate - public func interstitialControllerDidClickAd(_ interstitialController: InterstitialControllerProtocol) { + public func interstitialControllerDidClickAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { interstitialDelegate?.didClickInterstitialAd() rewardedDelegate?.didClickRewardedAd() } - public func interstitialControllerDidCloseAd(_ interstitialController: InterstitialControllerProtocol) { + public func interstitialControllerDidCloseAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { interstitialDelegate?.didHideInterstitialAd() rewardedDelegate?.didHideRewardedAd() } - public func interstitialControllerDidDisplay(_ interstitialController: InterstitialControllerProtocol) { + public func interstitialControllerDidDisplay(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { interstitialDelegate?.didDisplayInterstitialAd() rewardedDelegate?.didDisplayRewardedAd() } - public func interstitialControllerDidComplete(_ interstitialController: InterstitialControllerProtocol) { + public func interstitialControllerDidComplete(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { interstitialAdAvailable = false rewardedDelegate?.didRewardUser(with: MAReward()) } public func viewControllerForModalPresentation( - fromInterstitialController: InterstitialControllerProtocol + fromInterstitialController: PrebidMobileInterstitialControllerProtocol ) -> UIViewController? { return UIApplication.shared.windows.first?.rootViewController } - public func trackImpression(forInterstitialController: InterstitialControllerProtocol) {} - public func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialControllerProtocol) {} + public func trackImpression(forInterstitialController: PrebidMobileInterstitialControllerProtocol) {} + public func interstitialControllerDidLeaveApp(_ interstitialController: PrebidMobileInterstitialControllerProtocol) {} } diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdView.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdView.swift index 873204418..a4a222b43 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdView.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdView.swift @@ -17,11 +17,24 @@ import UIKit import WebKit import PrebidMobile -class SampleAdView: UIView { +class SampleAdView: UIView, PrebidMobileDisplayViewProtocol { + + enum SampleError: LocalizedError { + case noAdm + + var errorDescription: String? { + switch self { + case .noAdm: + return "Renderer did fail - there is no ADM in the response." + } + } + } weak var interactionDelegate: DisplayViewInteractionDelegate? weak var loadingDelegate: DisplayViewLoadingDelegate? + var bid: Bid? + private let webView: WKWebView = { let webView = WKWebView() webView.translatesAutoresizingMaskIntoConstraints = false @@ -52,12 +65,14 @@ class SampleAdView: UIView { setupView() } - func displayAd(_ bid: Bid) { - if let adm = bid.adm { - webView.loadHTMLString(adm, baseURL: nil) - loadingDelegate?.displayViewDidLoadAd(self) - } else { - print("Error displaying an ad: No ADM data found in bid response.") + func loadAd() { + DispatchQueue.main.async { + if let adm = self.bid?.adm { + self.webView.loadHTMLString(adm, baseURL: nil) + self.loadingDelegate?.displayViewDidLoadAd(self) + } else { + self.loadingDelegate?.displayView(self, didFailWithError: SampleError.noAdm) + } } } diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomAdViewRenderer.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomAdViewRenderer.swift index 1b752702c..61bb957fb 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomAdViewRenderer.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomAdViewRenderer.swift @@ -30,13 +30,15 @@ public class SampleCustomAdViewRenderer: NSObject, PrebidMobileAdViewPluginRende with frame: CGRect, bid: Bid, adConfiguration: AdUnitConfig, - loadingDelegate: DisplayViewLoadingDelegate?, - interactionDelegate: DisplayViewInteractionDelegate? - ) -> UIView { + loadingDelegate: DisplayViewLoadingDelegate, + interactionDelegate: DisplayViewInteractionDelegate + ) -> (UIView & PrebidMobileDisplayViewProtocol)? { let bannerView = SampleAdView(frame: frame) + bannerView.interactionDelegate = interactionDelegate bannerView.loadingDelegate = loadingDelegate - bannerView.displayAd(bid) + bannerView.bid = bid + return bannerView } } diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomInterstitialRenderer.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomInterstitialRenderer.swift index 4f5888e9c..5b96b8a1b 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomInterstitialRenderer.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomInterstitialRenderer.swift @@ -29,17 +29,14 @@ class SampleCustomInterstitialRenderer: PrebidMobileInterstitialPluginRenderer { func createInterstitialController( bid: Bid, adConfiguration: AdUnitConfig, - loadingDelegate: (any InterstitialControllerLoadingDelegate)?, - interactionDelegate: (any InterstitialControllerInteractionDelegate)? - ) -> any InterstitialControllerProtocol { - + loadingDelegate: InterstitialControllerLoadingDelegate, + interactionDelegate: InterstitialControllerInteractionDelegate + ) -> PrebidMobileInterstitialControllerProtocol? { let interstitialController = SampleInterstitialController() + interstitialController.loadingDelegate = loadingDelegate interstitialController.interactionDelegate = interactionDelegate - - if let adm = bid.adm { - interstitialController.htmlContent = adm - } + interstitialController.bid = bid return interstitialController } diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialController.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialController.swift index ae3a5d948..e0216cad0 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialController.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialController.swift @@ -18,12 +18,27 @@ import WebKit import PrebidMobile -class SampleInterstitialController: NSObject, InterstitialControllerProtocol { +class SampleInterstitialController: NSObject, PrebidMobileInterstitialControllerProtocol { + + enum SampleError: LocalizedError { + case noAdm + case noAvailableController + + var errorDescription: String? { + switch self { + case .noAdm: + return "Renderer did fail - there is no ADM in the response." + case .noAvailableController: + return "Coudn't find a controller to present from." + } + } + } + weak var loadingDelegate: InterstitialControllerLoadingDelegate? weak var interactionDelegate: InterstitialControllerInteractionDelegate? - var htmlContent: String? + var bid: Bid? private var webView: WKWebView = { let webView = WKWebView(frame: CGRect(origin: .zero, size: CGSize(width: 300, height: 250))) @@ -41,7 +56,7 @@ class SampleInterstitialController: NSObject, InterstitialControllerProtocol { return label }() - private lazy var interstitialViewController: UIViewController? = { + private lazy var interstitialViewController: UIViewController = { let viewController = UIViewController() viewController.view.backgroundColor = .white @@ -69,13 +84,13 @@ class SampleInterstitialController: NSObject, InterstitialControllerProtocol { } func loadAd() { - guard let htmlContent else { - print("Error: HTML content is not set.") + guard let adm = bid?.adm else { + loadingDelegate?.interstitialController(self, didFailWithError: SampleError.noAdm) return } DispatchQueue.main.async { - self.webView.loadHTMLString(htmlContent, baseURL: nil) + self.webView.loadHTMLString(adm, baseURL: nil) self.loadingDelegate?.interstitialControllerDidLoadAd(self) } } @@ -83,16 +98,18 @@ class SampleInterstitialController: NSObject, InterstitialControllerProtocol { func show() { DispatchQueue.main.async { guard let presentingController = self.topViewController else { - print("Error: Unable to find a top view controller.") + self.loadingDelegate?.interstitialController(self, didFailWithError: SampleError.noAvailableController) return } - guard let viewController = self.interstitialViewController else { - print("Error: Failed to create interstitial view controller. Make sure HTML content is set and loadAd is called.") - return + presentingController.present( + self.interstitialViewController, + animated: true + ) { [weak self] in + guard let self = self else { return } + self.interactionDelegate?.interstitialControllerDidCloseAd(self) + self.interactionDelegate?.interstitialControllerDidComplete(self) } - - presentingController.present(viewController, animated: true, completion: nil) } } } diff --git a/PrebidMobile.xcodeproj/project.pbxproj b/PrebidMobile.xcodeproj/project.pbxproj index 7dcd342a8..ac4778e6b 100644 --- a/PrebidMobile.xcodeproj/project.pbxproj +++ b/PrebidMobile.xcodeproj/project.pbxproj @@ -145,7 +145,8 @@ 53BDBF8A293F605B004B6DE8 /* InternalUserConsentDataManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 53BDBF87293F5EF6004B6DE8 /* InternalUserConsentDataManager.h */; }; 53BDBF8C293F6573004B6DE8 /* InternalUserConsentDataManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BDBF8B293F6573004B6DE8 /* InternalUserConsentDataManagerTests.swift */; }; 53BFCD0F2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD0E2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift */; }; - 53BFCD112CF9156000A3287A /* InterstitialControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD102CF9155E00A3287A /* InterstitialControllerProtocol.swift */; }; + 53BFCD112CF9156000A3287A /* PrebidMobileInterstitialControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD102CF9155E00A3287A /* PrebidMobileInterstitialControllerProtocol.swift */; }; + 53BFCD1F2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 53BFCD1E2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 53C8FE1729C0851300ED9230 /* ClickbrowserType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C8FE1629C0851300ED9230 /* ClickbrowserType.swift */; }; 53C925022990FB30009E6F94 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C925012990FB30009E6F94 /* String+Extensions.swift */; }; 53C925052990FBFB009E6F94 /* PrebidServerStatusRequester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C925042990FBFB009E6F94 /* PrebidServerStatusRequester.swift */; }; @@ -1036,7 +1037,8 @@ 53BDBF88293F5EFF004B6DE8 /* InternalUserConsentDataManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InternalUserConsentDataManager.m; sourceTree = ""; }; 53BDBF8B293F6573004B6DE8 /* InternalUserConsentDataManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalUserConsentDataManagerTests.swift; sourceTree = ""; }; 53BFCD0E2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidInterstitialControllerRenderer.swift; sourceTree = ""; }; - 53BFCD102CF9155E00A3287A /* InterstitialControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterstitialControllerProtocol.swift; sourceTree = ""; }; + 53BFCD102CF9155E00A3287A /* PrebidMobileInterstitialControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidMobileInterstitialControllerProtocol.swift; sourceTree = ""; }; + 53BFCD1E2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrebidMobileDisplayViewProtocol.h; sourceTree = ""; }; 53C8FE1629C0851300ED9230 /* ClickbrowserType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClickbrowserType.swift; sourceTree = ""; }; 53C925012990FB30009E6F94 /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = ""; }; 53C925042990FBFB009E6F94 /* PrebidServerStatusRequester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidServerStatusRequester.swift; sourceTree = ""; }; @@ -1995,6 +1997,32 @@ path = CacheManagement; sourceTree = ""; }; + 53BFCD2B2CFE39A700A3287A /* DisplayView */ = { + isa = PBXGroup; + children = ( + 53BFCD1E2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h */, + 5BC3778C271F1CFE00444D5E /* PBMDisplayView.h */, + 5BC37787271F1CFE00444D5E /* PBMDisplayView.m */, + 5BC37788271F1CFE00444D5E /* PBMDisplayView+InternalState.h */, + 5BC3778F271F1CFE00444D5E /* DisplayViewLoadingDelegate.swift */, + 5BC37790271F1CFE00444D5E /* DisplayViewInteractionDelegate.swift */, + A908694529E05F7900B37479 /* PrebidDisplayViewRenderer.swift */, + ); + path = DisplayView; + sourceTree = ""; + }; + 53BFCD2C2CFE39B200A3287A /* InterstitialController */ = { + isa = PBXGroup; + children = ( + 53BFCD102CF9155E00A3287A /* PrebidMobileInterstitialControllerProtocol.swift */, + 5BC3778E271F1CFE00444D5E /* InterstitialController.swift */, + 5BC3778B271F1CFE00444D5E /* InterstitialControllerLoadingDelegate.swift */, + 5BC3778D271F1CFE00444D5E /* InterstitialControllerInteractionDelegate.swift */, + 53BFCD0E2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift */, + ); + path = InterstitialController; + sourceTree = ""; + }; 53CE08FF2AD672980018CB75 /* ORTB-samples */ = { isa = PBXGroup; children = ( @@ -2436,17 +2464,8 @@ 5BC37786271F1CFE00444D5E /* PBMCacheRenderers */ = { isa = PBXGroup; children = ( - 5BC3778C271F1CFE00444D5E /* PBMDisplayView.h */, - 5BC37787271F1CFE00444D5E /* PBMDisplayView.m */, - 5BC37788271F1CFE00444D5E /* PBMDisplayView+InternalState.h */, - 5BC3778B271F1CFE00444D5E /* InterstitialControllerLoadingDelegate.swift */, - 5BC3778D271F1CFE00444D5E /* InterstitialControllerInteractionDelegate.swift */, - 53BFCD102CF9155E00A3287A /* InterstitialControllerProtocol.swift */, - 5BC3778E271F1CFE00444D5E /* InterstitialController.swift */, - 5BC3778F271F1CFE00444D5E /* DisplayViewLoadingDelegate.swift */, - 5BC37790271F1CFE00444D5E /* DisplayViewInteractionDelegate.swift */, - A908694529E05F7900B37479 /* PrebidDisplayViewRenderer.swift */, - 53BFCD0E2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift */, + 53BFCD2B2CFE39A700A3287A /* DisplayView */, + 53BFCD2C2CFE39B200A3287A /* InterstitialController */, ); path = PBMCacheRenderers; sourceTree = ""; @@ -3573,6 +3592,7 @@ 5BC37929271F1CFF00444D5E /* PBMLocationManagerProtocol.h in Headers */, 5BC37A9E271F1D0000444D5E /* PBMAdLoadFlowState.h in Headers */, 5BC379BD271F1D0000444D5E /* PBMAdRefreshOptions.h in Headers */, + 53BFCD1F2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h in Headers */, 5BC378F8271F1CFF00444D5E /* PBMORTBPmp.h in Headers */, 534C612D2CB527F80026119A /* PBMORTBRewardedCompletionVideo.h in Headers */, 92664565272AB5BB0064F7BD /* PBMORTBSkadnFidelity.h in Headers */, @@ -4407,7 +4427,7 @@ 5BC37ABD271F1D0000444D5E /* PBMOpenMeasurementEventTracker.m in Sources */, 5BC37927271F1CFF00444D5E /* PBMFunctions.m in Sources */, 53842BB829E561750069A4B7 /* PrebidImagesRepository.swift in Sources */, - 53BFCD112CF9156000A3287A /* InterstitialControllerProtocol.swift in Sources */, + 53BFCD112CF9156000A3287A /* PrebidMobileInterstitialControllerProtocol.swift in Sources */, 92C85D5A27A96AC50080BAC5 /* NativeTitle.swift in Sources */, 5BC37AA4271F1D0000444D5E /* PBMAdLoadFlowController.m in Sources */, 5BC378C0271F1CFF00444D5E /* NSDictionary+PBMExtensions.m in Sources */, diff --git a/PrebidMobile/BuildFiles/PrebidMobile.modulemap b/PrebidMobile/BuildFiles/PrebidMobile.modulemap index 24d74803c..8a2dce061 100644 --- a/PrebidMobile/BuildFiles/PrebidMobile.modulemap +++ b/PrebidMobile/BuildFiles/PrebidMobile.modulemap @@ -173,6 +173,8 @@ framework module PrebidMobile { header "PBMInterstitialAdLoader.h" header "PBMInterstitialAdLoaderDelegate.h" + header "PrebidMobileDisplayViewProtocol.h" + header "OMSDKVersionProvider.h" header "NSObject+PBMExtensions.h" } diff --git a/PrebidMobile/BuildFiles/PrebidMobileSwiftHeaders.h b/PrebidMobile/BuildFiles/PrebidMobileSwiftHeaders.h index be5a45fcb..4a0198640 100644 --- a/PrebidMobile/BuildFiles/PrebidMobileSwiftHeaders.h +++ b/PrebidMobile/BuildFiles/PrebidMobileSwiftHeaders.h @@ -27,6 +27,8 @@ #import "PBMAdLoaderProtocol.h" #import "PBMBannerAdLoader.h" +#import "PrebidMobileDisplayViewProtocol.h" + // Bid #import "PBMORTBBid.h" #import "PBMORTBBidExt.h" diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift index cffa24e05..a10d84352 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift @@ -1,82 +1,93 @@ /*   Copyright 2018-2021 Prebid.org, Inc. - - 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. - */ + +  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 UIKit +/// A protocol for the plugin renderer, defining the basic interface that any renderer should implement. +/// This protocol provides the ability to retrieve plugin details, support rendering formats, and manage event delegates. @objc public protocol PrebidMobilePluginRenderer: AnyObject { - @objc - var name: String { get } + /// The name of the plugin renderer. This is used to identify the plugin. + @objc var name: String { get } - @objc - var version: String { get } + /// The version of the plugin renderer. + @objc var version: String { get } // TODO: send in ORTB - @objc - var data: [AnyHashable: Any]? { get } - - /// Returns true only if the given ad unit could be renderer by the plugin - @objc - func isSupportRendering(for format: AdFormat?) -> Bool + /// The version of the plugin renderer. + @objc var data: [AnyHashable: Any]? { get } + /// Returns true only if the given ad unit could be renderer by the plugin. + @objc func isSupportRendering(for format: AdFormat?) -> Bool // TODO: Determine the purpose - /// Register a listener related to a specific ad unit config fingerprint in order to dispatch specific ad events - @objc - optional func registerEventDelegate( + /// Register a listener related to a specific ad unit config fingerprint in order to dispatch specific ad events. + @objc optional func registerEventDelegate( pluginEventDelegate: PluginEventDelegate, adUnitConfigFingerprint: String ) - - /// Unregister a listener related to a specific ad unit config fingerprint in order to dispatch specific ad events - @objc - optional func unregisterEventDelegate( + + /// Unregister a listener related to a specific ad unit config fingerprint in order to dispatch specific ad events. + @objc optional func unregisterEventDelegate( pluginEventDelegate: PluginEventDelegate, adUnitConfigFingerprint: String ) } +/// A protocol for the ad view plugin renderer, extending the base plugin renderer functionality. +/// This protocol is used specifically for the ad views. @objc public protocol PrebidMobileAdViewPluginRenderer: PrebidMobilePluginRenderer { - /// Creates and returns an ad view for a given bid response - /// Returns nil in the case of an internal error - @objc - func createAdView( + /// Creates and returns an ad view conforming to `PrebidMobileDisplayViewManagerProtocol` for a given bid response. + /// Returns nil in the case of an internal error. + /// + /// - Parameters: + /// - frame: The frame specifying the initial size and position of the ad view. + /// - bid: The `Bid` object containing the bid response used for rendering the ad. + /// - adConfiguration: The `AdUnitConfig` instance providing configuration details for the ad unit. + /// - loadingDelegate: The delegate conforming to `DisplayViewLoadingDelegate` for handling ad loading events. + /// - interactionDelegate: The delegate conforming to `DisplayViewInteractionDelegate` for handling ad interaction events. + @objc func createAdView( with frame: CGRect, bid: Bid, adConfiguration: AdUnitConfig, - loadingDelegate: DisplayViewLoadingDelegate?, - interactionDelegate: DisplayViewInteractionDelegate? - ) -> UIView - - // TODO: add display method (?) + loadingDelegate: DisplayViewLoadingDelegate, + interactionDelegate: DisplayViewInteractionDelegate + ) -> (UIView & PrebidMobileDisplayViewProtocol)? } +/// A protocol for a Prebid Mobile interstitial plugin renderer, extending the base plugin renderer functionality. +/// This protocol is used specifically for the interstitials. @objc public protocol PrebidMobileInterstitialPluginRenderer: PrebidMobilePluginRenderer { - /// Creates and returns an implementation of PrebidMobileInterstitialControllerInterface for a given bid response - /// Returns nil in the case of an internal error - @objc - func createInterstitialController( + /// Creates and returns an implementation of `PrebidMobileInterstitialControllerProtocol` for a given bid response. + /// Returns nil in the case of an internal error. + /// + /// - Parameters: + /// - bid: The `Bid` object containing the bid response used for rendering the interstitial ad. + /// - adConfiguration: The `AdUnitConfig` instance providing configuration details for the ad unit. + /// - loadingDelegate: The delegate for handling interstitial ad loading events. + /// - interactionDelegate: The delegate for handling user interactions with the interstitial ad. + @objc func createInterstitialController( bid: Bid, adConfiguration: AdUnitConfig, - loadingDelegate: InterstitialControllerLoadingDelegate?, - interactionDelegate: InterstitialControllerInteractionDelegate? - ) -> InterstitialControllerProtocol + loadingDelegate: InterstitialControllerLoadingDelegate, + interactionDelegate: InterstitialControllerInteractionDelegate + ) -> PrebidMobileInterstitialControllerProtocol? } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m index eecb1512a..6c6d74fc8 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m @@ -30,7 +30,6 @@ #import #endif - @interface PBMBannerAdLoader () @property (nonatomic, weak, nullable, readonly) id delegate; @@ -78,20 +77,22 @@ - (void)createPrebidAdWithBid:(Bid *)bid CGRect const displayFrame = CGRectMake(0, 0, bid.size.width, bid.size.height); dispatch_async(dispatch_get_main_queue(), ^{ - UIView * newDisplayView = [self.renderer createAdViewWith:displayFrame - bid:bid - adConfiguration:adUnitConfig - loadingDelegate:self - interactionDelegate:self.delegate + UIView * newDisplayView = [self.renderer createAdViewWith:displayFrame + bid:bid + adConfiguration:adUnitConfig + loadingDelegate:self + interactionDelegate:self.delegate ]; + if (!newDisplayView) { + PBMLogError(@"SDK couldn't retrieve an implementation of PrebidMobileDisplayViewManagerProtocol."); + return; + } + adObjectSaver(newDisplayView); loadMethodInvoker(^{ - // TODO: looks awful, add display method to renderer (?) - if ([newDisplayView isKindOfClass:[PBMDisplayView class]]) { - [(PBMDisplayView *)newDisplayView loadAd]; - } + [newDisplayView loadAd]; }); }); } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.h b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.h index 5f261f58c..2233df880 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.h +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.h @@ -18,7 +18,7 @@ #import "PBMAdLoaderProtocol.h" @protocol PBMInterstitialAdLoaderDelegate; -@protocol InterstitialControllerProtocol; +@protocol PrebidMobileInterstitialControllerProtocol; NS_ASSUME_NONNULL_BEGIN diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m index 671e90301..aa4001ffa 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m @@ -71,11 +71,16 @@ - (void)createPrebidAdWithBid:(Bid *)bid PBMLogInfo(@"Renderer: %@", self.renderer); - id controller = [self.renderer - createInterstitialControllerWithBid:bid - adConfiguration:adUnitConfig - loadingDelegate:self - interactionDelegate:self.delegate]; + id controller = [self.renderer + createInterstitialControllerWithBid:bid + adConfiguration:adUnitConfig + loadingDelegate:self + interactionDelegate:self.delegate]; + + if (!controller) { + PBMLogError(@"SDK couldn't retrieve an implementation of PrebidMobileInterstitialControllerProtocol."); + return; + } adObjectSaver(controller); @@ -85,8 +90,8 @@ - (void)createPrebidAdWithBid:(Bid *)bid } - (void)reportSuccessWithAdObject:(id)adObject adSize:(nullable NSValue *)adSize { - if ([adObject conformsToProtocol:@protocol(InterstitialControllerProtocol)]) { - id controller = (id)adObject; + if ([adObject conformsToProtocol:@protocol(PrebidMobileInterstitialControllerProtocol)]) { + id controller = (id)adObject; [self.delegate interstitialAdLoader:self loadedAd:^(UIViewController *targetController) { [controller show]; @@ -115,11 +120,11 @@ - (void)reportSuccessWithAdObject:(id)adObject adSize:(nullable NSValue *)adSize // MARK: - InterstitialControllerLoadingDelegate -- (void)interstitialControllerDidLoadAd:(id)interstitialController { +- (void)interstitialControllerDidLoadAd:(id)interstitialController { [self.flowDelegate adLoaderLoadedPrebidAd:self]; } -- (void)interstitialController:(id)interstitialController +- (void)interstitialController:(id)interstitialController didFailWithError:(NSError *)error { [self.flowDelegate adLoader:self failedWithPrebidError:error]; } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BannerView.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BannerView.swift index 277761187..2bea8a461 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BannerView.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BannerView.swift @@ -448,7 +448,9 @@ public class BannerView: eventHandler.trackImpression() } - public func viewControllerForModalPresentation(fromDisplayView: UIView) -> UIViewController? { + public func viewControllerForModalPresentation( + fromDisplayView: UIView + ) -> UIViewController? { return viewControllerForPresentingModal } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnit.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnit.swift index e80429585..03e78c8cd 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnit.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnit.swift @@ -189,26 +189,26 @@ class BaseInterstitialAdUnit: // MARK: - InterstitialControllerInteractionDelegate /// Tracks an impression for the given interstitial controller. - public func trackImpression(forInterstitialController: InterstitialControllerProtocol) { + public func trackImpression(forInterstitialController: PrebidMobileInterstitialControllerProtocol) { DispatchQueue.main.async { self.delegate?.callEventHandler_trackImpression() } } /// Called when the ad in the interstitial controller is clicked. - public func interstitialControllerDidClickAd(_ interstitialController: InterstitialControllerProtocol) { + public func interstitialControllerDidClickAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { assert(Thread.isMainThread, "Expected to only be called on the main thread") delegate?.callDelegate_didClickAd() } /// Called when the ad in the interstitial controller is closed. - public func interstitialControllerDidCloseAd(_ interstitialController: InterstitialControllerProtocol) { + public func interstitialControllerDidCloseAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { assert(Thread.isMainThread, "Expected to only be called on the main thread") delegate?.callDelegate_didDismissAd() } /// Called when the ad in the interstitial controller causes the app to leave. - public func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialControllerProtocol) { + public func interstitialControllerDidLeaveApp(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { assert(Thread.isMainThread, "Expected to only be called on the main thread") delegate?.callDelegate_willLeaveApplication() } @@ -218,11 +218,17 @@ class BaseInterstitialAdUnit: public func trackUserReward(_ interstitialController: InterstitialControllerProtocol, _ reward: PrebidReward) {} public func viewControllerForModalPresentation( - fromInterstitialController: InterstitialControllerProtocol + fromInterstitialController: PrebidMobileInterstitialControllerProtocol ) -> UIViewController? { return targetController } + /// Called when the interstitial controller displays an ad. + public func interstitialControllerDidDisplay(_ interstitialController: PrebidMobileInterstitialControllerProtocol) {} + + /// Called when the interstitial controller completes the ad display. + public func interstitialControllerDidComplete(_ interstitialController: PrebidMobileInterstitialControllerProtocol) {} + // MARK: - Private methods private func reportLoadingSuccess() { diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnitProtocol.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnitProtocol.swift index 66db775d5..b59adab0d 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnitProtocol.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnitProtocol.swift @@ -18,7 +18,7 @@ import UIKit @objc public protocol BaseInterstitialAdUnitProtocol: NSObjectProtocol { - @objc func interstitialControllerDidCloseAd(_ interstitialController: InterstitialControllerProtocol) + @objc func interstitialControllerDidCloseAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) @objc func callDelegate_didReceiveAd() @objc func callDelegate_didFailToReceiveAd(with error: Error?) diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedAdUnit.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedAdUnit.swift index 62f4bc88d..d9b020d4a 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedAdUnit.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedAdUnit.swift @@ -208,7 +208,7 @@ public class RewardedAdUnit: NSObject, BaseInterstitialAdUnitProtocol { /// Called when the interstitial ad is closed. /// /// - Parameter interstitialController: The controller managing the interstitial ad. - @objc public override func interstitialControllerDidCloseAd(_ interstitialController: InterstitialControllerProtocol) { + @objc public override func interstitialControllerDidCloseAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { callDelegate_rewardedAdUserDidEarnReward() super.interstitialControllerDidCloseAd(interstitialController) } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewInteractionDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewInteractionDelegate.swift new file mode 100644 index 000000000..7fc3f3d48 --- /dev/null +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewInteractionDelegate.swift @@ -0,0 +1,53 @@ +/*   Copyright 2018-2021 Prebid.org, Inc. + + 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 UIKit + +/// A protocol that defines methods for handling user interactions and lifecycle events related to ad display views. +@objc +public protocol DisplayViewInteractionDelegate: NSObjectProtocol { + + /// Tracks an impression for the specified display view. + /// + /// - Parameters: + /// - forDisplayView: The `UIView` instance associated with the ad impression. + @objc func trackImpression(forDisplayView: UIView) + + /// Notifies that the user has left the app after interacting with the ad. + /// + /// - Parameters: + /// - displayView: The `UIView` instance associated with the ad interaction. + @objc func didLeaveApp(from displayView: UIView) + + /// Notifies that a modal view is about to be presented from the specified display view. + /// + /// - Parameters: + /// - displayView: The `UIView` instance associated with the modal presentation. + @objc func willPresentModal(from displayView: UIView) + + /// Notifies the delegate that a modal view has been dismissed and control has returned to the app. + /// + /// - Parameters: + /// - displayView: The `UIView` instance associated with the dismissed modal. + @objc func didDismissModal(from displayView: UIView) + + /// Requests the `UIViewController` to be used for presenting modals from the specified display view. + /// + /// - Parameters: + /// - fromDisplayView: The `UIView` instance from which the modal is to be presented. + @objc func viewControllerForModalPresentation( + fromDisplayView: UIView + ) -> UIViewController? +} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewLoadingDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewLoadingDelegate.swift new file mode 100644 index 000000000..2788e5c70 --- /dev/null +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewLoadingDelegate.swift @@ -0,0 +1,35 @@ +/*   Copyright 2018-2021 Prebid.org, Inc. + + 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 UIKit + +/// A protocol that defines methods for receiving loading events related to ad display views. +/// This protocol is used to notify the delegate when an ad has successfully loaded or if an error occurs during loading. +@objc +public protocol DisplayViewLoadingDelegate: NSObjectProtocol { + + /// Notifies that the ad has successfully loaded in the display view. + /// + /// - Parameters: + /// - displayView: The `UIView` instance in which the ad has been loaded. + @objc func displayViewDidLoadAd(_ displayView: UIView) + + /// Notifies that an error occurred during the ad loading process. + /// + /// - Parameters: + /// - displayView: The `UIView` instance where the ad was intended to load. + /// - error: An `Error` instance describing the issue that occurred during the ad loading. + @objc func displayView(_ displayView: UIView, didFailWithError error: Error) +} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView+InternalState.h b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView+InternalState.h similarity index 100% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView+InternalState.h rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView+InternalState.h diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.h b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.h similarity index 88% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.h rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.h index 94a30db81..8bdafef44 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.h +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.h @@ -17,6 +17,7 @@ #import "PBMAdViewManagerDelegate.h" #import "PBMModalManagerDelegate.h" +#import "PrebidMobileDisplayViewProtocol.h" @protocol DisplayViewLoadingDelegate; @protocol DisplayViewInteractionDelegate; @@ -26,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface PBMDisplayView : UIView +@interface PBMDisplayView : UIView @property (atomic, weak, nullable) NSObject *loadingDelegate; @property (atomic, weak, nullable) NSObject *interactionDelegate; diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.m b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m similarity index 97% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.m rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m index c77626768..563f8588e 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m @@ -34,7 +34,7 @@ #import "PBMMacros.h" -@interface PBMDisplayView () +@interface PBMDisplayView () @property (nonatomic, strong, readonly, nonnull) Bid *bid; @property (nonatomic, strong, readonly, nonnull) AdUnitConfig *adConfiguration; @@ -48,6 +48,10 @@ @interface PBMDisplayView () @implementation PBMDisplayView +- (UIView *)adContentView { + return self; +} + // MARK: - Public API - (instancetype)initWithFrame:(CGRect)frame bid:(Bid *)bid configId:(NSString *)configId { return self = [self initWithFrame:frame @@ -71,6 +75,8 @@ - (instancetype)initWithFrame:(CGRect)frame return self; } +// TODO: Extract into another class (?) + - (void)loadAd { if (self.transactionFactory) { return; diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidDisplayViewRenderer.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PrebidDisplayViewRenderer.swift similarity index 89% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidDisplayViewRenderer.swift rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PrebidDisplayViewRenderer.swift index fb2513ba5..9ea0efa05 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidDisplayViewRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PrebidDisplayViewRenderer.swift @@ -29,9 +29,9 @@ public class PrebidDisplayViewRenderer: NSObject, PrebidMobileAdViewPluginRender with frame: CGRect, bid: Bid, adConfiguration: AdUnitConfig, - loadingDelegate: DisplayViewLoadingDelegate?, - interactionDelegate: DisplayViewInteractionDelegate? - ) -> UIView { + loadingDelegate: DisplayViewLoadingDelegate, + interactionDelegate: DisplayViewInteractionDelegate + ) -> (UIView & PrebidMobileDisplayViewProtocol)? { let displayView = PBMDisplayView( frame: frame, bid: bid, diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PrebidMobileDisplayViewProtocol.h b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PrebidMobileDisplayViewProtocol.h new file mode 100644 index 000000000..b847c7e0f --- /dev/null +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PrebidMobileDisplayViewProtocol.h @@ -0,0 +1,26 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 + +/// This protocol is used to load and display the ad content in a view. +@protocol PrebidMobileDisplayViewProtocol + +/// Loads the ad content into the display view. +/// - Important: This method is expected to call the `loadingDelegate` once the +/// ad is successfully loaded or if any error occurred. +- (void)loadAd; + +@end diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewInteractionDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewInteractionDelegate.swift deleted file mode 100644 index fc8f7e5c7..000000000 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewInteractionDelegate.swift +++ /dev/null @@ -1,30 +0,0 @@ -/*   Copyright 2018-2021 Prebid.org, Inc. - - 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 UIKit - -@objc -public protocol DisplayViewInteractionDelegate: NSObjectProtocol { - - func trackImpression(forDisplayView: UIView) - - func viewControllerForModalPresentation(fromDisplayView: UIView) -> UIViewController? - - func didLeaveApp(from displayView: UIView) - - func willPresentModal(from displayView: UIView) - - func didDismissModal(from displayView: UIView) -} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewLoadingDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewLoadingDelegate.swift deleted file mode 100644 index 317ba48cd..000000000 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewLoadingDelegate.swift +++ /dev/null @@ -1,23 +0,0 @@ -/*   Copyright 2018-2021 Prebid.org, Inc. - - 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 UIKit - -@objc -public protocol DisplayViewLoadingDelegate: NSObjectProtocol { - - func displayViewDidLoadAd(_ displayView: UIView) - func displayView(_ displayView: UIView, didFailWithError error: Error) -} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialController.swift similarity index 99% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController.swift rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialController.swift index 582ae37c8..ba2b8307d 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialController.swift @@ -18,7 +18,7 @@ import UIKit @objcMembers public class InterstitialController: NSObject, - InterstitialControllerProtocol, + PrebidMobileInterstitialControllerProtocol, PBMAdViewManagerDelegate { public var adFormats: Set { diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerInteractionDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerInteractionDelegate.swift new file mode 100644 index 000000000..25d7fab60 --- /dev/null +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerInteractionDelegate.swift @@ -0,0 +1,77 @@ +/*   Copyright 2018-2021 Prebid.org, Inc. + + 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 UIKit + +/// A protocol that defines methods for handling user interactions and lifecycle events related to interstitial ads. +@objc +public protocol InterstitialControllerInteractionDelegate: NSObjectProtocol { + + /// Tracks an impression for the specified interstitial ad controller. + /// + /// - Parameters: + /// - forInterstitialController: The interstitial ad controller associated with the impression. + @objc func trackImpression( + forInterstitialController: PrebidMobileInterstitialControllerProtocol + ) + + /// Notifies that the interstitial ad was clicked by the user. + /// + /// - Parameters: + /// - interstitialController: The interstitial ad controller associated with the click. + @objc func interstitialControllerDidClickAd( + _ interstitialController: PrebidMobileInterstitialControllerProtocol + ) + + /// Notifies the delegate that the interstitial ad has been closed by the user. + /// + /// - Parameters: + /// - interstitialController: The interstitial ad controller that was closed. + @objc func interstitialControllerDidCloseAd( + _ interstitialController: PrebidMobileInterstitialControllerProtocol + ) + + /// Notifies the delegate that the user has left the app after interacting with the interstitial ad. + /// + /// - Parameters: + /// - interstitialController: The interstitial ad controller that was displayed when the user left the app. + @objc func interstitialControllerDidLeaveApp( + _ interstitialController: PrebidMobileInterstitialControllerProtocol + ) + + /// Notifies the delegate that the interstitial ad has been displayed to the user. + /// + /// - Parameters: + /// - interstitialController: The interstitial ad controller that displayed the ad. + @objc func interstitialControllerDidDisplay( + _ interstitialController: PrebidMobileInterstitialControllerProtocol + ) + + /// Notifies the delegate that the interstitial ad has completed its presentation. + /// + /// - Parameters: + /// - interstitialController: The interstitial ad controller associated with the completed ad. + @objc func interstitialControllerDidComplete( + _ interstitialController: PrebidMobileInterstitialControllerProtocol + ) + + /// Requests the `UIViewController` to be used for presenting modals from the interstitial ad controller. + /// + /// - Parameters: + /// - fromInterstitialController: The interstitial ad controller requesting the view controller. + @objc func viewControllerForModalPresentation( + fromInterstitialController: PrebidMobileInterstitialControllerProtocol + ) -> UIViewController? +} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerLoadingDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerLoadingDelegate.swift new file mode 100644 index 000000000..291bb575f --- /dev/null +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerLoadingDelegate.swift @@ -0,0 +1,39 @@ +/*   Copyright 2018-2021 Prebid.org, Inc. + + 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 Foundation + +/// A protocol that defines methods for receiving loading events related to interstitial ad controllers. +@objc +public protocol InterstitialControllerLoadingDelegate: NSObjectProtocol { + + /// Notifies the delegate that the interstitial ad has successfully loaded. + /// + /// - Parameters: + /// - interstitialController: The interstitial ad controller that successfully loaded the ad. + @objc func interstitialControllerDidLoadAd( + _ interstitialController: PrebidMobileInterstitialControllerProtocol + ) + + /// Notifies the delegate that an error occurred during the interstitial ad loading process. + /// + /// - Parameters: + /// - interstitialController: The interstitial ad controller that attempted to load the ad. + /// - error: An `Error` instance describing the issue that occurred during the ad loading. + @objc func interstitialController( + _ interstitialController: PrebidMobileInterstitialControllerProtocol, + didFailWithError error: Error + ) +} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidInterstitialControllerRenderer.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/PrebidInterstitialControllerRenderer.swift similarity index 92% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidInterstitialControllerRenderer.swift rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/PrebidInterstitialControllerRenderer.swift index af13cb2e7..1f85dd4a2 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidInterstitialControllerRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/PrebidInterstitialControllerRenderer.swift @@ -30,9 +30,9 @@ public class PrebidInterstitialControllerRenderer: public func createInterstitialController( bid: Bid, adConfiguration: AdUnitConfig, - loadingDelegate: InterstitialControllerLoadingDelegate?, - interactionDelegate: InterstitialControllerInteractionDelegate? - ) -> InterstitialControllerProtocol { + loadingDelegate: InterstitialControllerLoadingDelegate, + interactionDelegate: InterstitialControllerInteractionDelegate + ) -> PrebidMobileInterstitialControllerProtocol? { let interstitialController = InterstitialController( bid: bid, adConfiguration: adConfiguration diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/PrebidMobileInterstitialControllerProtocol.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/PrebidMobileInterstitialControllerProtocol.swift new file mode 100644 index 000000000..965473116 --- /dev/null +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/PrebidMobileInterstitialControllerProtocol.swift @@ -0,0 +1,29 @@ +/*   Copyright 2018-2021 Prebid.org, Inc. + +  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 UIKit + +/// A protocol that defines the interface for controlling and interacting with interstitial ads. +/// This protocol allows loading and displaying interstitial ads, as well as managing interactions with them. +@objc +public protocol PrebidMobileInterstitialControllerProtocol: NSObjectProtocol { + + /// Loads the ad content for the interstitial. + /// - Important: This method is expected to call the `loadingDelegate` once the ad is successfully loaded or if any error occurred. + func loadAd() + + /// Displays the interstitial ad. + func show() +} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerLoadingDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerLoadingDelegate.swift deleted file mode 100644 index 722966e8a..000000000 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerLoadingDelegate.swift +++ /dev/null @@ -1,24 +0,0 @@ -/*   Copyright 2018-2021 Prebid.org, Inc. - - 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 Foundation - -@objc -public protocol InterstitialControllerLoadingDelegate: NSObjectProtocol { - - func interstitialControllerDidLoadAd(_ interstitialController: InterstitialControllerProtocol) - func interstitialController(_ interstitialController: InterstitialControllerProtocol, - didFailWithError error: Error) -} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerProtocol.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerProtocol.swift deleted file mode 100644 index 5bdce08d1..000000000 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerProtocol.swift +++ /dev/null @@ -1,23 +0,0 @@ -/*   Copyright 2018-2021 Prebid.org, Inc. - - 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 Foundation - -@objc -public protocol InterstitialControllerProtocol: NSObjectProtocol { - - func loadAd() - func show() -} From b7c956b45a78c0c754c40ae8306328daf4082556 Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Mon, 2 Dec 2024 22:01:00 +0200 Subject: [PATCH 04/18] feat: send data in ORTB request --- PrebidMobile.xcodeproj/project.pbxproj | 4 +++ .../ORTB/PBMORTBBidRequestExtPrebid.h | 4 +-- .../ORTB/PBMORTBBidRequestExtPrebid.m | 6 ++-- .../PrebidMobilePluginRegister.swift | 7 +++++ ...rebidMobilePluginRenderer+Extensions.swift | 29 +++++++++++++++++++ .../PrebidMobilePluginRenderer.swift | 3 +- .../PBMCore/PBMPrebidParameterBuilder.m | 19 ++---------- 7 files changed, 48 insertions(+), 24 deletions(-) create mode 100644 PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer+Extensions.swift diff --git a/PrebidMobile.xcodeproj/project.pbxproj b/PrebidMobile.xcodeproj/project.pbxproj index ac4778e6b..5fd3c7d98 100644 --- a/PrebidMobile.xcodeproj/project.pbxproj +++ b/PrebidMobile.xcodeproj/project.pbxproj @@ -147,6 +147,7 @@ 53BFCD0F2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD0E2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift */; }; 53BFCD112CF9156000A3287A /* PrebidMobileInterstitialControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD102CF9155E00A3287A /* PrebidMobileInterstitialControllerProtocol.swift */; }; 53BFCD1F2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 53BFCD1E2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 53BFCD312CFE435D00A3287A /* PrebidMobilePluginRenderer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD302CFE435D00A3287A /* PrebidMobilePluginRenderer+Extensions.swift */; }; 53C8FE1729C0851300ED9230 /* ClickbrowserType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C8FE1629C0851300ED9230 /* ClickbrowserType.swift */; }; 53C925022990FB30009E6F94 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C925012990FB30009E6F94 /* String+Extensions.swift */; }; 53C925052990FBFB009E6F94 /* PrebidServerStatusRequester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C925042990FBFB009E6F94 /* PrebidServerStatusRequester.swift */; }; @@ -1039,6 +1040,7 @@ 53BFCD0E2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidInterstitialControllerRenderer.swift; sourceTree = ""; }; 53BFCD102CF9155E00A3287A /* PrebidMobileInterstitialControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidMobileInterstitialControllerProtocol.swift; sourceTree = ""; }; 53BFCD1E2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrebidMobileDisplayViewProtocol.h; sourceTree = ""; }; + 53BFCD302CFE435D00A3287A /* PrebidMobilePluginRenderer+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PrebidMobilePluginRenderer+Extensions.swift"; sourceTree = ""; }; 53C8FE1629C0851300ED9230 /* ClickbrowserType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClickbrowserType.swift; sourceTree = ""; }; 53C925012990FB30009E6F94 /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = ""; }; 53C925042990FBFB009E6F94 /* PrebidServerStatusRequester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidServerStatusRequester.swift; sourceTree = ""; }; @@ -3299,6 +3301,7 @@ children = ( A908694129E05EAF00B37479 /* PrebidMobilePluginRegister.swift */, A908694329E05ED500B37479 /* PrebidMobilePluginRenderer.swift */, + 53BFCD302CFE435D00A3287A /* PrebidMobilePluginRenderer+Extensions.swift */, A9750D792ABB9A300066E4E6 /* PluginEventListener.swift */, ); path = PluginRenderer; @@ -4427,6 +4430,7 @@ 5BC37ABD271F1D0000444D5E /* PBMOpenMeasurementEventTracker.m in Sources */, 5BC37927271F1CFF00444D5E /* PBMFunctions.m in Sources */, 53842BB829E561750069A4B7 /* PrebidImagesRepository.swift in Sources */, + 53BFCD312CFE435D00A3287A /* PrebidMobilePluginRenderer+Extensions.swift in Sources */, 53BFCD112CF9156000A3287A /* PrebidMobileInterstitialControllerProtocol.swift in Sources */, 92C85D5A27A96AC50080BAC5 /* NativeTitle.swift in Sources */, 5BC37AA4271F1D0000444D5E /* PBMAdLoadFlowController.m in Sources */, diff --git a/PrebidMobile/PrebidMobileRendering/ORTB/PBMORTBBidRequestExtPrebid.h b/PrebidMobile/PrebidMobileRendering/ORTB/PBMORTBBidRequestExtPrebid.h index 0e1a79d67..c2ed8029d 100644 --- a/PrebidMobile/PrebidMobileRendering/ORTB/PBMORTBBidRequestExtPrebid.h +++ b/PrebidMobile/PrebidMobileRendering/ORTB/PBMORTBBidRequestExtPrebid.h @@ -32,13 +32,11 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong, nullable) NSArray *> *storedBidResponses; -@property (nonatomic, strong, nullable) NSArray *> *sdkRenderers; - @property (nonatomic, strong, nullable) NSMutableDictionary *cache; @property (nonatomic, strong) PBMMutableJsonDictionary *targeting; -@property (nonatomic, strong, nullable) PBMJsonDictionary *sdk; +@property (nonatomic, strong, nullable) NSArray *sdkRenderers; @end diff --git a/PrebidMobile/PrebidMobileRendering/ORTB/PBMORTBBidRequestExtPrebid.m b/PrebidMobile/PrebidMobileRendering/ORTB/PBMORTBBidRequestExtPrebid.m index 9ead83ca4..9d4bee9ce 100644 --- a/PrebidMobile/PrebidMobileRendering/ORTB/PBMORTBBidRequestExtPrebid.m +++ b/PrebidMobile/PrebidMobileRendering/ORTB/PBMORTBBidRequestExtPrebid.m @@ -48,8 +48,10 @@ - (nonnull PBMJsonDictionary *)toJsonDictionary { PBMMutableJsonDictionary * const storedRequest = [PBMMutableJsonDictionary new]; ret[@"storedrequest"] = storedRequest; storedRequest[@"id"] = self.storedRequestID; - if (self.sdk != nil) { - ret[@"sdk"] = self.sdk; + + if (self.sdkRenderers != nil && self.sdkRenderers.count > 0) { + NSDictionary * sdk = @{ @"renderers" : self.sdkRenderers }; + ret[@"sdk"] = sdk; } ret[@"targeting"] = self.targeting; diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift index 03fd4b185..807b3d2ba 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift @@ -134,4 +134,11 @@ public class PrebidMobilePluginRegister: NSObject { return plugins.isEmpty ? [] : Array(plugins.values) } } + + public func getAllPluginsJSONRepresentation() -> [[String: Any]] { + return PrebidMobilePluginRegister + .shared + .getAllPlugins() + .map { $0.jsonDictionary() } + } } diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer+Extensions.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer+Extensions.swift new file mode 100644 index 000000000..ad0317e19 --- /dev/null +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer+Extensions.swift @@ -0,0 +1,29 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 Foundation + +extension PrebidMobilePluginRenderer { + + public func jsonDictionary() -> [String: Any] { + var result = [String: Any]() + + result["name"] = name + result["version"] = version + result["data"] = data + + return result + } +} diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift index a10d84352..143cb6651 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift @@ -1,4 +1,4 @@ -/*   Copyright 2018-2021 Prebid.org, Inc. +/*   Copyright 2018-2024 Prebid.org, Inc.  Licensed under the Apache License, Version 2.0 (the "License");  you may not use this file except in compliance with the License. @@ -26,7 +26,6 @@ public protocol PrebidMobilePluginRenderer: AnyObject { /// The version of the plugin renderer. @objc var version: String { get } - // TODO: send in ORTB /// The version of the plugin renderer. @objc var data: [AnyHashable: Any]? { get } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/PBMPrebidParameterBuilder.m b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/PBMPrebidParameterBuilder.m index 9db0a2fdc..f443dd3ca 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/PBMPrebidParameterBuilder.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/PBMPrebidParameterBuilder.m @@ -74,9 +74,8 @@ - (void)buildBidRequest:(nonnull PBMORTBBidRequest *)bidRequest { bidRequest.extPrebid.storedBidResponses = [Prebid.shared getStoredBidResponses]; bidRequest.ortbObject = [self.adConfiguration.adConfiguration getCheckedOrtbConfig]; - NSArray *renderers = [[PrebidMobilePluginRegister shared] getAllPlugins]; - if (renderers.count != 0 && self.adConfiguration.adConfiguration.isOriginalAPI == false) { - bidRequest.extPrebid.sdk = [PBMPrebidParameterBuilder getRenderersJson]; + if (!self.adConfiguration.adConfiguration.isOriginalAPI) { + bidRequest.extPrebid.sdkRenderers = [PrebidMobilePluginRegister.shared getAllPluginsJSONRepresentation]; } if (Prebid.shared.pbsDebug) { @@ -314,20 +313,6 @@ - (void)buildBidRequest:(nonnull PBMORTBBidRequest *)bidRequest { } } -+ (nonnull PBMJsonDictionary *)getRenderersJson { - PBMMutableJsonDictionary * const sdk = [PBMMutableJsonDictionary new]; - NSMutableArray *renderersArray = [NSMutableArray array]; - NSArray *renderers = [[PrebidMobilePluginRegister shared] getAllPlugins]; - for (id renderer in renderers) { - PBMMutableJsonDictionary *rendererDict = [PBMMutableJsonDictionary new]; - rendererDict[@"name"] = renderer.name; - rendererDict[@"version"] = renderer.version; - [renderersArray addObject:rendererDict]; - } - sdk[@"renderers"] = renderersArray; - return sdk; -} - + (PBMORTBFormat *)ortbFormatWithSize:(NSValue *)size { PBMORTBFormat * const format = [[PBMORTBFormat alloc] init]; CGSize const cgSize = size.CGSizeValue; From 20425b275bc26a607f1de1d69002ef64898549d4 Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Tue, 3 Dec 2024 14:54:05 +0200 Subject: [PATCH 05/18] fix: plugin register unit tests --- PrebidMobile.xcodeproj/project.pbxproj | 7 +- .../PrebidMobilePluginRegister.swift | 4 +- .../MockPrebidMobilePluginRenderer.swift | 51 ++++++++++ .../Tests/Prebid/PluginRegisterTest.swift | 95 +++++++++++++++++++ .../UnitTests/PluginRegisterTest.swift | 76 --------------- 5 files changed, 153 insertions(+), 80 deletions(-) create mode 100644 PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift create mode 100644 PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift delete mode 100644 PrebidMobileTests/UnitTests/PluginRegisterTest.swift diff --git a/PrebidMobile.xcodeproj/project.pbxproj b/PrebidMobile.xcodeproj/project.pbxproj index 5fd3c7d98..b222617c7 100644 --- a/PrebidMobile.xcodeproj/project.pbxproj +++ b/PrebidMobile.xcodeproj/project.pbxproj @@ -148,6 +148,7 @@ 53BFCD112CF9156000A3287A /* PrebidMobileInterstitialControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD102CF9155E00A3287A /* PrebidMobileInterstitialControllerProtocol.swift */; }; 53BFCD1F2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 53BFCD1E2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 53BFCD312CFE435D00A3287A /* PrebidMobilePluginRenderer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD302CFE435D00A3287A /* PrebidMobilePluginRenderer+Extensions.swift */; }; + 53BFCD332CFF30C800A3287A /* MockPrebidMobilePluginRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD322CFF30C800A3287A /* MockPrebidMobilePluginRenderer.swift */; }; 53C8FE1729C0851300ED9230 /* ClickbrowserType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C8FE1629C0851300ED9230 /* ClickbrowserType.swift */; }; 53C925022990FB30009E6F94 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C925012990FB30009E6F94 /* String+Extensions.swift */; }; 53C925052990FBFB009E6F94 /* PrebidServerStatusRequester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C925042990FBFB009E6F94 /* PrebidServerStatusRequester.swift */; }; @@ -1041,6 +1042,7 @@ 53BFCD102CF9155E00A3287A /* PrebidMobileInterstitialControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidMobileInterstitialControllerProtocol.swift; sourceTree = ""; }; 53BFCD1E2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrebidMobileDisplayViewProtocol.h; sourceTree = ""; }; 53BFCD302CFE435D00A3287A /* PrebidMobilePluginRenderer+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PrebidMobilePluginRenderer+Extensions.swift"; sourceTree = ""; }; + 53BFCD322CFF30C800A3287A /* MockPrebidMobilePluginRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockPrebidMobilePluginRenderer.swift; sourceTree = ""; }; 53C8FE1629C0851300ED9230 /* ClickbrowserType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClickbrowserType.swift; sourceTree = ""; }; 53C925012990FB30009E6F94 /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = ""; }; 53C925042990FBFB009E6F94 /* PrebidServerStatusRequester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidServerStatusRequester.swift; sourceTree = ""; }; @@ -1836,6 +1838,7 @@ 539D4C7129B5E23600B6B30E /* MockPBMAbstractCreative.swift */, 533FDF842A12030C0066ED5A /* MockPrebidJSLibraryManager.swift */, 53CE09022AD67ECE0018CB75 /* MockPBMBidRequester.swift */, + 53BFCD322CFF30C800A3287A /* MockPrebidMobilePluginRenderer.swift */, 534C61432CB5619B0026119A /* MockVideoView.swift */, ); path = Mocks; @@ -3090,7 +3093,7 @@ isa = PBXGroup; children = ( 925D5DA92737C4E800A8A2B5 /* AdLoadFlow */, - 927ADB2528058170006EB8D5 /* MediationAPI */, + 3CD0ADED2C5125E9006CDA6B /* PluginRegisterTest.swift */, 925D5E082737DF5F00A8A2B5 /* PBMBannerViewTest.swift */, 925D5E112737E04B00A8A2B5 /* PBMBidRequesterTest.swift */, 925D5E132737E74C00A8A2B5 /* PBMBidResponseTransformerTest.swift */, @@ -3320,7 +3323,6 @@ FAC837D72321583500565051 /* CollectionExtensionTest.swift */, FA5AD5E32271FA4100C8F274 /* ConstantsTest.swift */, FAEBF2A1237ECFEF006BA972 /* StorageUtilsTests.swift */, - 3CD0ADED2C5125E9006CDA6B /* PluginRegisterTest.swift */, ); path = UnitTests; sourceTree = ""; @@ -3885,6 +3887,7 @@ 922AFD742737340300732C53 /* PrebidTest.swift in Sources */, 925D5E3F2737F01000A8A2B5 /* URLComponentsTests.swift in Sources */, 38F03B332576624C00E026A2 /* TrackerManagerTests.swift in Sources */, + 53BFCD332CFF30C800A3287A /* MockPrebidMobilePluginRenderer.swift in Sources */, 925D5E382737EF0400A8A2B5 /* RewardedVideo_CompanionTest.swift in Sources */, 539D4C7029B5DDFD00B6B30E /* SafariOpenerTests.swift in Sources */, 539D4C7229B5E23600B6B30E /* MockPBMAbstractCreative.swift in Sources */, diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift index 807b3d2ba..d7b68b105 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift @@ -100,12 +100,12 @@ public class PrebidMobilePluginRegister: NSObject { } /// Returns the list of available renderers for the given ad unit for RTB request - public func getRTBListOfRenderersFor(for adUnit: AdUnitConfig) -> [PrebidMobilePluginRenderer] { + public func getRTBListOfRenderersFor(for adUnitConfig: AdUnitConfig) -> [PrebidMobilePluginRenderer] { queue.sync { plugins .values .filter { renderer in - adUnit.adFormats.contains { format in + adUnitConfig.adFormats.contains { format in renderer.isSupportRendering(for: format) } } diff --git a/PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift b/PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift new file mode 100644 index 000000000..29823c203 --- /dev/null +++ b/PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift @@ -0,0 +1,51 @@ +/* Copyright 2018-2024 Prebid.org, Inc. + + 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 Foundation +@testable import PrebidMobile + +class MockPrebidMobilePluginRenderer: PrebidMobilePluginRenderer { + + let name: String + let version: String + var data: [AnyHashable: Any]? + var formats: Set = [] + + init( + name: String, + version: String, + data: [AnyHashable: Any]? = nil + ) { + self.name = name + self.version = version + self.data = data + } + + func isSupportRendering(for format: AdFormat?) -> Bool { + guard !formats.isEmpty else { return true } + + if let format { + return formats.contains(format) + } else { + return true + } + } + + func jsonDictionary() -> [String: Any] { + var json: [String: Any] = ["name": name, "version": version] + json["data"] = data + return json + } +} diff --git a/PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift b/PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift new file mode 100644 index 000000000..d7dce5eff --- /dev/null +++ b/PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift @@ -0,0 +1,95 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 XCTest +@testable import PrebidMobile + +extension PrebidMobilePluginRegister { + + func unregisterAllPlugins() { + let plugins = getAllPlugins() + for plugin in plugins { + unregisterPlugin(plugin) + } + } +} + +class PluginRegisterTest: XCTestCase { + + let prebidMobilePluginRegister = PrebidMobilePluginRegister.shared + + let plugin = MockPrebidMobilePluginRenderer( + name: "MockPrebidMobilePluginRenderer", + version: "1.0.0" + ) + + override func setUp() { + super.setUp() + prebidMobilePluginRegister.unregisterAllPlugins() + prebidMobilePluginRegister.registerPlugin(plugin) + plugin.formats = [] + } + + func testRegisterPlugin() { + XCTAssertEqual(true, prebidMobilePluginRegister.containsPlugin(plugin)) + + let plugins = prebidMobilePluginRegister.getAllPlugins() + XCTAssertEqual(1, plugins.count) + } + + func testUnregisterPlugin() { + prebidMobilePluginRegister.unregisterPlugin(plugin) + + let containsPlugin = prebidMobilePluginRegister.containsPlugin(plugin) + XCTAssertEqual(false, containsPlugin) + } + + func testGetPluginForBidContainingSampleCustomRenderer() { + let bidResponse = Bid( + bid: RawSampleCustomRendererBidFabricator.makeSampleCustomRendererBid( + rendererName: "MockPrebidMobilePluginRenderer", + rendererVersion: "1.0.0" + ) + ) + + let pluginRenderer = prebidMobilePluginRegister.getPluginForPreferredRenderer( + bid: bidResponse, + isInterstitial: false + ) + + XCTAssertEqual(pluginRenderer.name, plugin.name) + XCTAssertEqual(pluginRenderer.version, plugin.version) + } + + func testGetRTBListOfRenderersFor() { + plugin.formats = [.banner, .video] + + let adUnitConfigBanner = AdUnitConfig( + configId: "configID", + size: CGSize(width: 300, height: 250) + ) + + var renderers = prebidMobilePluginRegister + .getRTBListOfRenderersFor(for: adUnitConfigBanner) + XCTAssertEqual(1, renderers.count) + + let adUnitConfigError = AdUnitConfig(configId: "configID") + adUnitConfigError.adFormats = [.native] + + renderers = prebidMobilePluginRegister + .getRTBListOfRenderersFor(for: adUnitConfigError) + XCTAssertEqual(0, renderers.count) + } +} diff --git a/PrebidMobileTests/UnitTests/PluginRegisterTest.swift b/PrebidMobileTests/UnitTests/PluginRegisterTest.swift deleted file mode 100644 index ae32aaa8b..000000000 --- a/PrebidMobileTests/UnitTests/PluginRegisterTest.swift +++ /dev/null @@ -1,76 +0,0 @@ -// -// PluginRegisterTest.swift -// PrebidMobileTests -// -// Created by Richard Dépierre on 24/07/2024. -// Copyright © 2024 AppNexus. All rights reserved. -// - -import XCTest - -@testable import PrebidMobile -import TestUtils - -class PluginRegisterTest: XCTestCase { - let prebidMobilePluginRegister = PrebidMobilePluginRegister.shared - let plugin = SampleCustomRenderer() - - override func setUp() { - super.setUp() - unregisterAllPlugins() - prebidMobilePluginRegister.registerPlugin(plugin) - } - - func unregisterAllPlugins() { - let plugins = prebidMobilePluginRegister.getAllPlugins() - for plugin in plugins { - prebidMobilePluginRegister.unregisterPlugin(plugin) - } - } - - func testRegisterPlugin() { - let containsPlugin = prebidMobilePluginRegister.containsPlugin(plugin) - let plugins = prebidMobilePluginRegister.getAllPlugins() - XCTAssertEqual(true, containsPlugin) - XCTAssertEqual(1, plugins.count) - } - - func testUnregisterPlugin() { - prebidMobilePluginRegister.unregisterPlugin(plugin) - - let containsPlugin = prebidMobilePluginRegister.containsPlugin(plugin) - XCTAssertEqual(false, containsPlugin) - } - - func testGetPluginForBidContainingSampleCustomRenderer() { - let bidResponse = Bid( - bid: RawSampleCustomRendererBidFabricator.makeSampleCustomRendererBid( - rendererName: "SampleCustomRenderer", - rendererVersion: "1.0.0" - ) - ) - - let pluginRenderer = prebidMobilePluginRegister.getPluginForPreferredRenderer( - bid: bidResponse - ) - XCTAssertEqual(pluginRenderer.name, plugin.name) - XCTAssertEqual(pluginRenderer.version, plugin.version) - } - - func testGetRTBListOfRenderersFor() { - let adUnitConfigBanner = AdUnitConfig( - configId: "configID", - size: CGSize( - width: 300, - height: 250 - ) - ) - let adUnitConfigError = AdUnitConfig(configId: "configID") - - var renderers = prebidMobilePluginRegister.getRTBListOfRenderersFor(for: adUnitConfigBanner) - XCTAssertEqual(1, renderers.count) - - renderers = prebidMobilePluginRegister.getRTBListOfRenderersFor(for: adUnitConfigError) - XCTAssertEqual(1, renderers.count) - } -} From f581e53718440fe895c0e5cf0617136626ef94e5 Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Tue, 3 Dec 2024 15:15:49 +0200 Subject: [PATCH 06/18] tests: add request tests --- .../DisplayView/PBMDisplayView.m | 7 +- .../PrebidBannerRenderer.swift | 150 ------------------ .../PrebidBannerViewRenderer.swift | 51 ------ .../Tests/PBMORTBAbstractTest.swift | 5 +- .../PrebidParameterBuilderTest.swift | 31 ++++ 5 files changed, 35 insertions(+), 209 deletions(-) delete mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerRenderer.swift delete mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerViewRenderer.swift diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m index 563f8588e..c7512f94b 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m @@ -48,11 +48,8 @@ @interface PBMDisplayView () @implementation PBMDisplayView -- (UIView *)adContentView { - return self; -} - // MARK: - Public API + - (instancetype)initWithFrame:(CGRect)frame bid:(Bid *)bid configId:(NSString *)configId { return self = [self initWithFrame:frame bid:bid @@ -75,8 +72,6 @@ - (instancetype)initWithFrame:(CGRect)frame return self; } -// TODO: Extract into another class (?) - - (void)loadAd { if (self.transactionFactory) { return; diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerRenderer.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerRenderer.swift deleted file mode 100644 index bde360f9b..000000000 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerRenderer.swift +++ /dev/null @@ -1,150 +0,0 @@ -/*   Copyright 2018-2021 Prebid.org, Inc. - -  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 UIKit - -public class PrebidAdViewRenderer: NSObject, PrebidMobilePluginRenderer { - - public let name = "PrebidBannerRenderer" - public let version = Prebid.shared.version - public var data: [AnyHashable: Any]? = nil - - public func isSupportRendering(for format: AdFormat?) -> Bool { - AdFormat.allCases.contains(where: { $0 == format }) - } - - private var transactionFactory: PBMTransactionFactory? - private var adViewManager: PBMAdViewManager? - - public func createBannerAdView( - with frame: CGRect, - bid: Bid, - adConfiguration: AdUnitConfig, - connection: PrebidServerConnectionProtocol, - adViewDelegate: (any PBMAdViewDelegate)? - ) -> UIView { - let displayView = PBMDisplayView( - frame: frame, - bid: bid, - adConfiguration: adConfiguration - ) - - transactionFactory = PBMTransactionFactory( - bid: bid, - adConfiguration: adConfiguration, - connection: connection - ) { [weak self] transaction, error in - self?.transactionFactory = nil - - guard let transaction else { -// adViewDelegate?.failed(toLoad: NSError(domain: "", code: 0)) - return - } - - if let error { - // adViewDelegate?.failed(toLoad: error) - return - } - - self?.displayTransaction( - transaction, - adConfiguration: adConfiguration, - connection: connection, - adViewDelegate: adViewDelegate - ) - } - - PBMWinNotifier.notifyThroughConnection( - PrebidServerConnection.shared, - winning: bid - ) { [weak self] adMarkup in - if let adMarkup { - self?.transactionFactory?.load(withAdMarkup: adMarkup) - } - } - - // TODO: Run display - - return displayView - } - - public func createInterstitialController( - bid: Bid, - adConfiguration: AdUnitConfig, - connection: PrebidServerConnectionProtocol, - adViewManagerDelegate adViewDelegate: InterstitialController?, - videoControlsConfig: VideoControlsConfiguration? - ) { - // guard transactionFactory == nil else { - // return - // } - // - // adConfiguration.adConfiguration.winningBidAdFormat = bid.adFormat - // videoControlsConfig?.initialize(with: bid.videoAdConfiguration) - // - // // This part is dedicating to test server-side ad configurations. - // // Need to be removed when ext.prebid.passthrough will be available. - // #if DEBUG - // adConfiguration.adConfiguration.videoControlsConfig.initialize(with: bid.testVideoAdConfiguration) - // #endif - // transactionFactory = PBMTransactionFactory(bid: bid, - // adConfiguration: adConfiguration, - // connection: PrebidServerConnection.shared, - // callback: { [weak adViewDelegate] transaction, error in - // - // if let transaction = transaction { - // adViewDelegate?.display(transaction: transaction) - // } else { - // self.transactionFactory = nil - // adViewDelegate?.reportFailureWithError(error) - // } - // }) - // - // PBMWinNotifier.notifyThroughConnection( - // PrebidServerConnection.shared, - // winning: bid, - // callback: { [weak self] adMarkup in - // - // if let self = self, let adMarkup = adMarkup { - // self.transactionFactory?.load(withAdMarkup: adMarkup) - // } else { - // Log.debug("Ad markup is empty") - // } - // }) - } - - public func setupBid( - _ bid: Bid, - adConfiguration: AdUnitConfig, - connection: PrebidServerConnectionProtocol - ) {} - - private func displayTransaction( - _ transaction: PBMTransaction, - adConfiguration: AdUnitConfig, - connection: PrebidServerConnectionProtocol, - adViewDelegate: (any PBMAdViewDelegate)? - ) { - adViewManager = PBMAdViewManager(connection: connection, modalManagerDelegate: adViewDelegate) - adViewManager?.adViewManagerDelegate = adViewDelegate - adViewManager?.adConfiguration = adConfiguration.adConfiguration - - if adConfiguration.adConfiguration.winningBidAdFormat == .video { - adConfiguration.adConfiguration.isBuiltInVideo = true - } - - adViewManager?.handleExternalTransaction(transaction) - } -} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerViewRenderer.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerViewRenderer.swift deleted file mode 100644 index 09dadcda0..000000000 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidBannerViewRenderer.swift +++ /dev/null @@ -1,51 +0,0 @@ -/*   Copyright 2018-2024 Prebid.org, Inc. - -  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 UIKit - -public class PrebidDisplayViewRenderer: NSObject, PrebidMobileBannerViewPluginRenderer { - - public let name = "PrebidDisplayViewRenderer" - public let version = Prebid.shared.version - public var data: [AnyHashable: Any]? - - public func isSupportRendering(for format: AdFormat?) -> Bool { - AdFormat.allCases.contains(where: { $0 == format }) - } - - private var transactionFactory: PBMTransactionFactory? - private var adViewManager: PBMAdViewManager? - private var connection = PrebidServerConnection.shared - - public func createBannerAdView( - with frame: CGRect, - bid: Bid, - adConfiguration: AdUnitConfig, - loadingDelegate: DisplayViewLoadingDelegate?, - interactionDelegate: DisplayViewInteractionDelegate? - ) -> UIView { - - let displayView = PBMDisplayView( - frame: frame, - bid: bid, - adConfiguration: adConfiguration - ) - - displayView.interactionDelegate = interactionDelegate - displayView.loadingDelegate = loadingDelegate - - return displayView - } -} diff --git a/PrebidMobileTests/RenderingTests/Tests/PBMORTBAbstractTest.swift b/PrebidMobileTests/RenderingTests/Tests/PBMORTBAbstractTest.swift index 865f808d5..7f30a864a 100644 --- a/PrebidMobileTests/RenderingTests/Tests/PBMORTBAbstractTest.swift +++ b/PrebidMobileTests/RenderingTests/Tests/PBMORTBAbstractTest.swift @@ -181,13 +181,14 @@ class PBMORTBAbstractTest : XCTestCase { extPrebid.storedRequestID = "b4eb1475-4e3d-4186-97b7-25b6a6cf8618" extPrebid.dataBidders = ["openx", "prebid", "thanatos"] extPrebid.storedAuctionResponse = "stored-auction-response-test" + extPrebid.sdkRenderers = [["name": "MockRenderer1", "version": "0.0.1"], ["name": "MockRenderer2", "version": "0.0.2"]] - codeAndDecode(abstract: extPrebid, expectedString: "{\"data\":{\"bidders\":[\"openx\",\"prebid\",\"thanatos\"]},\"storedauctionresponse\":{\"id\":\"stored-auction-response-test\"},\"storedrequest\":{\"id\":\"b4eb1475-4e3d-4186-97b7-25b6a6cf8618\"},\"targeting\":{}}") + codeAndDecode(abstract: extPrebid, expectedString: "{\"data\":{\"bidders\":[\"openx\",\"prebid\",\"thanatos\"]},\"sdk\":{\"renderers\":[{\"name\":\"MockRenderer1\",\"version\":\"0.0.1\"},{\"name\":\"MockRenderer2\",\"version\":\"0.0.2\"}]},\"storedauctionresponse\":{\"id\":\"stored-auction-response-test\"},\"storedrequest\":{\"id\":\"b4eb1475-4e3d-4186-97b7-25b6a6cf8618\"},\"targeting\":{}}") let pbmORTBBidRequest = PBMORTBBidRequest() pbmORTBBidRequest.extPrebid = extPrebid - codeAndDecode(abstract: pbmORTBBidRequest, expectedString: "{\"ext\":{\"prebid\":{\"data\":{\"bidders\":[\"openx\",\"prebid\",\"thanatos\"]},\"storedauctionresponse\":{\"id\":\"stored-auction-response-test\"},\"storedrequest\":{\"id\":\"b4eb1475-4e3d-4186-97b7-25b6a6cf8618\"},\"targeting\":{}}},\"imp\":[{\"clickbrowser\":0,\"ext\":{\"dlp\":1},\"instl\":0,\"secure\":0}]}") + codeAndDecode(abstract: pbmORTBBidRequest, expectedString: "{\"ext\":{\"prebid\":{\"data\":{\"bidders\":[\"openx\",\"prebid\",\"thanatos\"]},\"sdk\":{\"renderers\":[{\"name\":\"MockRenderer1\",\"version\":\"0.0.1\"},{\"name\":\"MockRenderer2\",\"version\":\"0.0.2\"}]},\"storedauctionresponse\":{\"id\":\"stored-auction-response-test\"},\"storedrequest\":{\"id\":\"b4eb1475-4e3d-4186-97b7-25b6a6cf8618\"},\"targeting\":{}}},\"imp\":[{\"clickbrowser\":0,\"ext\":{\"dlp\":1},\"instl\":0,\"secure\":0}]}") } func testSourceToJsonString() { diff --git a/PrebidMobileTests/RenderingTests/Tests/ParameterBuilderTests/PrebidParameterBuilderTest.swift b/PrebidMobileTests/RenderingTests/Tests/ParameterBuilderTests/PrebidParameterBuilderTest.swift index e3bfc4620..71a7d97bb 100644 --- a/PrebidMobileTests/RenderingTests/Tests/ParameterBuilderTests/PrebidParameterBuilderTest.swift +++ b/PrebidMobileTests/RenderingTests/Tests/ParameterBuilderTests/PrebidParameterBuilderTest.swift @@ -826,6 +826,37 @@ class PrebidParameterBuilderTest: XCTestCase { XCTAssert(bidRequest.ortbObject?.isEmpty == true) } + + func testExtPrebidSDKRenderers() { + let mockRenderer1 = MockPrebidMobilePluginRenderer(name: "MockRenderer1", version: "0.0.1") + let mockRenderer2 = MockPrebidMobilePluginRenderer(name: "MockRenderer2", version: "0.0.2") + let mockRenderer3 = MockPrebidMobilePluginRenderer(name: "MockRenderer3", version: "0.0.3") + + PrebidMobilePluginRegister.shared.registerPlugin(mockRenderer1) + PrebidMobilePluginRegister.shared.registerPlugin(mockRenderer2) + PrebidMobilePluginRegister.shared.registerPlugin(mockRenderer3) + + let adUnitConfig = AdUnitConfig(configId: "test") + let bidRequest = buildBidRequest(with: adUnitConfig) + let realResult = bidRequest.extPrebid.sdkRenderers + + XCTAssert(realResult?.count == 3) + } + + func testExtPrebidSDKRenderers_OriginalAPI() { + let mockRenderer1 = MockPrebidMobilePluginRenderer(name: "MockRenderer1", version: "0.0.1") + let mockRenderer2 = MockPrebidMobilePluginRenderer(name: "MockRenderer2", version: "0.0.2") + let mockRenderer3 = MockPrebidMobilePluginRenderer(name: "MockRenderer3", version: "0.0.3") + + PrebidMobilePluginRegister.shared.registerPlugin(mockRenderer1) + PrebidMobilePluginRegister.shared.registerPlugin(mockRenderer2) + PrebidMobilePluginRegister.shared.registerPlugin(mockRenderer3) + + let adUnit = AdUnit(configId: "test", size: CGSize.zero, adFormats: [.banner]) + + let bidRequest = buildBidRequest(with: adUnit.adUnitConfig) + XCTAssertNil(bidRequest.extPrebid.sdkRenderers) + } // MARK: - Helpers From 23350406fc075a9002179b39af10553bb4862108 Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Tue, 3 Dec 2024 15:34:24 +0200 Subject: [PATCH 07/18] fix: missing winning ad format --- .../Integrations/GAM/AdLoading/PBMAdLoadFlowController.m | 1 - .../Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m | 2 ++ .../PrebidMobileRendering/Prebid/PBMCore/AdUnitConfig.swift | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMAdLoadFlowController.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMAdLoadFlowController.m index b03c7fbcd..92bbcbb4e 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMAdLoadFlowController.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMAdLoadFlowController.m @@ -275,7 +275,6 @@ - (void)loadPrebidDisplayView { self.flowState = PBMAdLoadFlowState_LoadingDisplayView; AdUnitConfig * const adUnitConfig = self.savedAdUnitConfig; - adUnitConfig.adConfiguration.winningBidAdFormat = bid.adFormat; @weakify(self); dispatch_sync(dispatch_get_main_queue(), ^{ diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m index c7512f94b..8679b49e2 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m @@ -77,6 +77,8 @@ - (void)loadAd { return; } + self.adConfiguration.adConfiguration.winningBidAdFormat = self.bid.adFormat; + @weakify(self); self.transactionFactory = [[PBMTransactionFactory alloc] initWithBid:self.bid adConfiguration:self.adConfiguration diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/AdUnitConfig.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/AdUnitConfig.swift index 155916ca4..3a54f6df4 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/AdUnitConfig.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCore/AdUnitConfig.swift @@ -309,6 +309,10 @@ public class AdUnitConfig: NSObject, NSCopying { clone.adFormats = self.adFormats clone.nativeAdConfiguration = self.nativeAdConfiguration + clone.adConfiguration.bannerParameters = self.adConfiguration.bannerParameters + clone.adConfiguration.videoParameters = self.adConfiguration.videoParameters + clone.adConfiguration.videoControlsConfig = self.adConfiguration.videoControlsConfig + clone.adConfiguration.winningBidAdFormat = self.adConfiguration.winningBidAdFormat clone.sizes = sizes clone.adSize = adSize clone.minSizePerc = self.minSizePerc From e91c8f97c0fe6d7a7906a6a12ce79d545b926f2c Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Tue, 3 Dec 2024 21:46:47 +0200 Subject: [PATCH 08/18] feat: enhance InternalTestApp examples --- .../InternalTestApp.xcodeproj/project.pbxproj | 6 ++ .../Renderers/SampleAdView.swift | 41 ++++++++ .../SampleInterstitialController.swift | 93 ++++++++++--------- .../Renderers/SampleModalViewController.swift | 60 ++++++++++++ .../PrebidMobilePluginRenderer.swift | 5 + 5 files changed, 163 insertions(+), 42 deletions(-) create mode 100644 InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleModalViewController.swift diff --git a/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj b/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj index 84ea9ddd5..3de5bf150 100644 --- a/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj +++ b/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj @@ -31,6 +31,8 @@ 3CC4A3EA2C11F96800B97128 /* CustomRendererBannerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CC4A3E82C11F96800B97128 /* CustomRendererBannerController.swift */; }; 457FD34BA45C3840CC31A8F5 /* Pods_InternalTestApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C11D97034E668BBFDD0DDCA /* Pods_InternalTestApp.framework */; }; 530E722C292FACB20025B44D /* UIImageView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 530E722B292FACB20025B44D /* UIImageView+Extensions.swift */; }; + 53514C8F2CFF92D000A480C0 /* SampleModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C8E2CFF92D000A480C0 /* SampleModalViewController.swift */; }; + 53514C902CFF92D000A480C0 /* SampleModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C8E2CFF92D000A480C0 /* SampleModalViewController.swift */; }; 5397BD142936185400ABDA22 /* PrebidOriginalAPIDisplayBannerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5397BD132936185400ABDA22 /* PrebidOriginalAPIDisplayBannerController.swift */; }; 5397BD26293760F500ABDA22 /* PrebidOriginalAPIDisplayInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5397BD25293760F500ABDA22 /* PrebidOriginalAPIDisplayInterstitialController.swift */; }; 5397BD2A29376C9700ABDA22 /* PrebidOriginalAPIVideoRewardedController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5397BD2929376C9700ABDA22 /* PrebidOriginalAPIVideoRewardedController.swift */; }; @@ -389,6 +391,7 @@ 3C28C9D72C35713B00D0A7DB /* CustomRendererInterstitialController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomRendererInterstitialController.swift; sourceTree = ""; }; 3CC4A3E82C11F96800B97128 /* CustomRendererBannerController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomRendererBannerController.swift; sourceTree = ""; }; 530E722B292FACB20025B44D /* UIImageView+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageView+Extensions.swift"; sourceTree = ""; }; + 53514C8E2CFF92D000A480C0 /* SampleModalViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleModalViewController.swift; sourceTree = ""; }; 5397BD132936185400ABDA22 /* PrebidOriginalAPIDisplayBannerController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidOriginalAPIDisplayBannerController.swift; sourceTree = ""; }; 5397BD25293760F500ABDA22 /* PrebidOriginalAPIDisplayInterstitialController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidOriginalAPIDisplayInterstitialController.swift; sourceTree = ""; }; 5397BD2929376C9700ABDA22 /* PrebidOriginalAPIVideoRewardedController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidOriginalAPIVideoRewardedController.swift; sourceTree = ""; }; @@ -747,6 +750,7 @@ 53BFCD022CF792FB00A3287A /* SampleCustomAdViewRenderer.swift */, 53BFCD122CF9C67400A3287A /* SampleInterstitialController.swift */, 53BFCD162CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift */, + 53514C8E2CFF92D000A480C0 /* SampleModalViewController.swift */, ); path = Renderers; sourceTree = ""; @@ -1648,6 +1652,7 @@ 53ED301429798104007D13EE /* TestCasesSectionsViewController.swift in Sources */, 3C28C9D92C35713B00D0A7DB /* CustomRendererInterstitialController.swift in Sources */, 53ED301529798104007D13EE /* AppSettingsKeys.swift in Sources */, + 53514C902CFF92D000A480C0 /* SampleModalViewController.swift in Sources */, 53ED301729798104007D13EE /* NativeEventTracker+Extensions.swift in Sources */, 53ED301829798104007D13EE /* PrebidRewardedController.swift in Sources */, 539F960C29DEF0B90061E7A5 /* PrebidOriginalAPIMultiformatBannerController.swift in Sources */, @@ -1748,6 +1753,7 @@ 5B3EEDE22101EDA200BAA0C4 /* TestCasesSectionsViewController.swift in Sources */, 3C28C9D82C35713B00D0A7DB /* CustomRendererInterstitialController.swift in Sources */, ACC41ACD2444EADB00B9A3A7 /* AppSettingsKeys.swift in Sources */, + 53514C8F2CFF92D000A480C0 /* SampleModalViewController.swift in Sources */, 92C4E60D27A2F6D700738370 /* NativeEventTracker+Extensions.swift in Sources */, 34BA9600249CC118006AE372 /* PrebidRewardedController.swift in Sources */, 539F960B29DEF0B90061E7A5 /* PrebidOriginalAPIMultiformatBannerController.swift in Sources */, diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdView.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdView.swift index a4a222b43..17e6c907b 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdView.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdView.swift @@ -16,6 +16,7 @@ import UIKit import WebKit import PrebidMobile +import SafariServices class SampleAdView: UIView, PrebidMobileDisplayViewProtocol { @@ -58,11 +59,13 @@ class SampleAdView: UIView, PrebidMobileDisplayViewProtocol { override init(frame: CGRect) { super.init(frame: frame) setupView() + webView.navigationDelegate = self } required init?(coder: NSCoder) { super.init(coder: coder) setupView() + webView.navigationDelegate = self } func loadAd() { @@ -93,3 +96,41 @@ class SampleAdView: UIView, PrebidMobileDisplayViewProtocol { ]) } } + +extension SampleAdView: WKNavigationDelegate { + + func webView( + _ webView: WKWebView, + decidePolicyFor navigationAction: WKNavigationAction, + decisionHandler: @escaping (WKNavigationActionPolicy) -> Void + ) { + guard let url = navigationAction.request.url, + navigationAction.navigationType == .linkActivated else { + decisionHandler(.allow) + return + } + + guard let presentingVC = interactionDelegate? + .viewControllerForModalPresentation(fromDisplayView: self) else { + decisionHandler(.allow) + return + } + + let safariVC = SFSafariViewController(url: url) + safariVC.delegate = self + interactionDelegate?.willPresentModal(from: self) + presentingVC.present(safariVC, animated: true) { [weak self] in + guard let self = self else { return } + self.interactionDelegate?.didDismissModal(from: self) + } + + decisionHandler(.cancel) + } +} + +extension SampleAdView: SFSafariViewControllerDelegate { + + func safariViewControllerWillOpenInBrowser(_ controller: SFSafariViewController) { + interactionDelegate?.didLeaveApp(from: self) + } +} diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialController.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialController.swift index e0216cad0..39e328d00 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialController.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialController.swift @@ -15,7 +15,6 @@ import UIKit import WebKit - import PrebidMobile class SampleInterstitialController: NSObject, PrebidMobileInterstitialControllerProtocol { @@ -33,44 +32,23 @@ class SampleInterstitialController: NSObject, PrebidMobileInterstitialController } } } - weak var loadingDelegate: InterstitialControllerLoadingDelegate? weak var interactionDelegate: InterstitialControllerInteractionDelegate? var bid: Bid? - private var webView: WKWebView = { - let webView = WKWebView(frame: CGRect(origin: .zero, size: CGSize(width: 300, height: 250))) - webView.translatesAutoresizingMaskIntoConstraints = false - webView.backgroundColor = .blue - return webView - }() - - private var customRendererLabel: UILabel = { - let label = UILabel() - label.text = "Custom Renderer" - label.textAlignment = .center - label.font = UIFont.boldSystemFont(ofSize: 18) - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() + private var webView: WKWebView { + interstitialViewController.webView + } - private lazy var interstitialViewController: UIViewController = { - let viewController = UIViewController() - viewController.view.backgroundColor = .white + private lazy var interstitialViewController: SampleModalViewController = { + let viewController = SampleModalViewController() - viewController.view.addSubview(customRendererLabel) - viewController.view.addSubview(webView) - - NSLayoutConstraint.activate([ - customRendererLabel.topAnchor.constraint(equalTo: viewController.view.safeAreaLayoutGuide.topAnchor, constant: 20), - customRendererLabel.centerXAnchor.constraint(equalTo: viewController.view.centerXAnchor), - webView.centerXAnchor.constraint(equalTo: viewController.view.centerXAnchor), - webView.centerYAnchor.constraint(equalTo: viewController.view.centerYAnchor), - webView.widthAnchor.constraint(equalToConstant: 300), - webView.heightAnchor.constraint(equalToConstant: 250), - ]) + viewController.onDismiss = { [weak self] in + guard let self else { return } + self.interactionDelegate?.interstitialControllerDidCloseAd(self) + } return viewController }() @@ -83,13 +61,19 @@ class SampleInterstitialController: NSObject, PrebidMobileInterstitialController return topController } + override init() { + super.init() + webView.navigationDelegate = self + } + func loadAd() { - guard let adm = bid?.adm else { - loadingDelegate?.interstitialController(self, didFailWithError: SampleError.noAdm) - return - } - DispatchQueue.main.async { + guard let adm = self.bid?.adm else { + self.loadingDelegate?.interstitialController(self, didFailWithError: SampleError.noAdm) + return + } + + self.webView.loadHTMLString(adm, baseURL: nil) self.loadingDelegate?.interstitialControllerDidLoadAd(self) } @@ -98,18 +82,43 @@ class SampleInterstitialController: NSObject, PrebidMobileInterstitialController func show() { DispatchQueue.main.async { guard let presentingController = self.topViewController else { - self.loadingDelegate?.interstitialController(self, didFailWithError: SampleError.noAvailableController) + self.loadingDelegate?.interstitialController( + self, + didFailWithError: SampleError.noAvailableController + ) return } presentingController.present( self.interstitialViewController, animated: true - ) { [weak self] in - guard let self = self else { return } - self.interactionDelegate?.interstitialControllerDidCloseAd(self) - self.interactionDelegate?.interstitialControllerDidComplete(self) - } + ) + } + } +} + +extension SampleInterstitialController: WKNavigationDelegate { + + func webView( + _ webView: WKWebView, + decidePolicyFor navigationAction: WKNavigationAction, + decisionHandler: @escaping (WKNavigationActionPolicy) -> Void + ) { + guard let url = navigationAction.request.url, + navigationAction.navigationType == .linkActivated else { + decisionHandler(.allow) + return } + + interactionDelegate?.interstitialControllerDidClickAd(self) + + guard UIApplication.shared.canOpenURL(url) else { + decisionHandler(.allow) + return + } + + interactionDelegate?.interstitialControllerDidLeaveApp(self) + UIApplication.shared.open(url, options: [:], completionHandler: nil) + decisionHandler(.cancel) } } diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleModalViewController.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleModalViewController.swift new file mode 100644 index 000000000..7e4e6dcc4 --- /dev/null +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleModalViewController.swift @@ -0,0 +1,60 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + + 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 UIKit +import WebKit + +class SampleModalViewController: UIViewController { + + var onDismiss: (() -> Void)? + + let webView: WKWebView = { + let webView = WKWebView(frame: CGRect(origin: .zero, size: CGSize(width: 300, height: 250))) + webView.translatesAutoresizingMaskIntoConstraints = false + webView.backgroundColor = .blue + return webView + }() + + private let customRendererLabel: UILabel = { + let label = UILabel() + label.text = "Custom Renderer" + label.textAlignment = .center + label.font = UIFont.boldSystemFont(ofSize: 18) + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + override func viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = .white + view.addSubview(customRendererLabel) + view.addSubview(webView) + + NSLayoutConstraint.activate([ + customRendererLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20), + customRendererLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), + webView.centerXAnchor.constraint(equalTo: view.centerXAnchor), + webView.centerYAnchor.constraint(equalTo: view.centerYAnchor), + webView.widthAnchor.constraint(equalToConstant: 300), + webView.heightAnchor.constraint(equalToConstant: 250), + ]) + } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + onDismiss?() + } +} diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift index 143cb6651..32d117128 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift @@ -15,6 +15,11 @@ import UIKit +// 1. Determine the purpose of registerEventDelegate and unregisterEventDelegate +// 2. Add cases to InternalTestApp with all delegates calling +// 3. Ask if to add to Demo Apps +// 4. Unit tests. + /// A protocol for the plugin renderer, defining the basic interface that any renderer should implement. /// This protocol provides the ability to retrieve plugin details, support rendering formats, and manage event delegates. @objc From 9cb12b123f5cb8257746289b1c080cf3c9c77328 Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Wed, 4 Dec 2024 14:24:03 +0200 Subject: [PATCH 09/18] feat: add plugin renderer cases to demo apps --- .../PrebidDemo.xcodeproj/project.pbxproj | 82 +++++++++++++ ...isplayBannerPluginRendererViewController.h | 26 +++++ ...isplayBannerPluginRendererViewController.m | 71 ++++++++++++ ...InterstitialPluginRendererViewController.h | 26 +++++ ...InterstitialPluginRendererViewController.m | 65 +++++++++++ .../InApp/SampleRenderers/SampleAdView.h | 35 ++++++ .../InApp/SampleRenderers/SampleAdView.m | 89 +++++++++++++++ .../SampleRenderers/SampleAdViewRenderer.h | 30 +++++ .../SampleRenderers/SampleAdViewRenderer.m | 51 +++++++++ .../SampleInterstitialController.h | 33 ++++++ .../SampleInterstitialController.m | 89 +++++++++++++++ .../SampleInterstitialRenderer.h | 30 +++++ .../SampleInterstitialRenderer.m | 51 +++++++++ .../IntegrationCase/IntegrationCaseManager.m | 22 ++++ .../Utils/UIApplication+TopViewController.h | 26 +++++ .../Utils/UIApplication+TopViewController.m | 66 +++++++++++ ...ayBannerCustomRendererViewController.swift | 66 +++++++++++ ...ayBannerPluginRendererViewController.swift | 66 +++++++++++ ...tialPluginInterstitialViewController.swift | 61 ++++++++++ .../In-App/SampleRenderers/SampleAdView.swift | 97 ++++++++++++++++ .../SampleAdViewRenderer.swift | 46 ++++++++ .../SampleInterstitialController.swift | 108 ++++++++++++++++++ .../SampleInterstitialRenderer.swift | 46 ++++++++ .../Extensions/UIApplication+Extensions.swift | 47 +++++++- .../IntegrationCaseManager.swift | 18 +++ .../InternalTestApp.xcodeproj/project.pbxproj | 24 ++-- .../CustomRendererBannerController.swift | 2 +- ...CustomRendererInterstitialController.swift | 2 +- .../Renderers/SampleAdView.swift | 2 +- ...derer.swift => SampleAdViewRenderer.swift} | 4 +- ...swift => SampleInterstitialRenderer.swift} | 4 +- .../PrebidMobilePluginRenderer.swift | 7 -- 32 files changed, 1360 insertions(+), 32 deletions(-) create mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.h create mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.m create mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.h create mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.m create mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdView.h create mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdView.m create mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.h create mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.m create mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialController.h create mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialController.m create mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.h create mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.m create mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Utils/UIApplication+TopViewController.h create mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Utils/UIApplication+TopViewController.m create mode 100644 Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerCustomRendererViewController.swift create mode 100644 Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift create mode 100644 Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayInterstitialPluginInterstitialViewController.swift create mode 100644 Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleAdView.swift create mode 100644 Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleAdViewRenderer.swift create mode 100644 Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialController.swift create mode 100644 Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialRenderer.swift rename InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/{SampleCustomAdViewRenderer.swift => SampleAdViewRenderer.swift} (90%) rename InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/{SampleCustomInterstitialRenderer.swift => SampleInterstitialRenderer.swift} (91%) diff --git a/Example/PrebidDemo/PrebidDemo.xcodeproj/project.pbxproj b/Example/PrebidDemo/PrebidDemo.xcodeproj/project.pbxproj index 31472ff3a..2767d9f39 100644 --- a/Example/PrebidDemo/PrebidDemo.xcodeproj/project.pbxproj +++ b/Example/PrebidDemo/PrebidDemo.xcodeproj/project.pbxproj @@ -67,6 +67,19 @@ 5344E6C12922A97200A1F582 /* MAXVideoInterstitialViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5344E6C02922A97200A1F582 /* MAXVideoInterstitialViewController.swift */; }; 5344E6C32922AAE500A1F582 /* MAXVideoRewardedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5344E6C22922AAE500A1F582 /* MAXVideoRewardedViewController.swift */; }; 5344E6C52922AC2C00A1F582 /* MAXNativeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5344E6C42922AC2C00A1F582 /* MAXNativeViewController.swift */; }; + 53514C962CFF97DB00A480C0 /* InAppDisplayBannerPluginRendererViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C952CFF97DB00A480C0 /* InAppDisplayBannerPluginRendererViewController.swift */; }; + 53514C9E2CFF988E00A480C0 /* SampleAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C982CFF988E00A480C0 /* SampleAdView.swift */; }; + 53514C9F2CFF988E00A480C0 /* SampleInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C9B2CFF988E00A480C0 /* SampleInterstitialController.swift */; }; + 53514CA02CFF988E00A480C0 /* SampleAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C992CFF988E00A480C0 /* SampleAdViewRenderer.swift */; }; + 53514CA12CFF988E00A480C0 /* SampleInterstitialRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C9A2CFF988E00A480C0 /* SampleInterstitialRenderer.swift */; }; + 53514CA32CFF9DD000A480C0 /* InAppDisplayInterstitialPluginInterstitialViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CA22CFF9DD000A480C0 /* InAppDisplayInterstitialPluginInterstitialViewController.swift */; }; + 53514CA72CFFA52A00A480C0 /* SampleAdView.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CA62CFFA52A00A480C0 /* SampleAdView.m */; }; + 53514CAA2CFFA62700A480C0 /* SampleAdViewRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CA92CFFA62700A480C0 /* SampleAdViewRenderer.m */; }; + 53514CAD2CFFA99200A480C0 /* InAppDisplayBannerPluginRendererViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CAC2CFFA99200A480C0 /* InAppDisplayBannerPluginRendererViewController.m */; }; + 53514CB02CFFAB6700A480C0 /* SampleInterstitialController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CAF2CFFAB6700A480C0 /* SampleInterstitialController.m */; }; + 53514CB32CFFAD5E00A480C0 /* UIApplication+TopViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CB22CFFAD5E00A480C0 /* UIApplication+TopViewController.m */; }; + 53514CB62CFFADC200A480C0 /* SampleInterstitialRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CB52CFFADC200A480C0 /* SampleInterstitialRenderer.m */; }; + 53514CB92CFFAECB00A480C0 /* InAppDisplayInterstitialPluginRendererViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CB82CFFAECB00A480C0 /* InAppDisplayInterstitialPluginRendererViewController.m */; }; 534C614D2CB7EFD50026119A /* InAppDisplayRewardedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534C614C2CB7EFD50026119A /* InAppDisplayRewardedViewController.swift */; }; 534C614F2CB7F20A0026119A /* GAMDisplayRewardedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534C614E2CB7F20A0026119A /* GAMDisplayRewardedViewController.swift */; }; 534C61552CB7F32D0026119A /* MAXDisplayRewardedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534C61542CB7F32D0026119A /* MAXDisplayRewardedViewController.swift */; }; @@ -281,6 +294,26 @@ 5344E6C02922A97200A1F582 /* MAXVideoInterstitialViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MAXVideoInterstitialViewController.swift; sourceTree = ""; }; 5344E6C22922AAE500A1F582 /* MAXVideoRewardedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MAXVideoRewardedViewController.swift; sourceTree = ""; }; 5344E6C42922AC2C00A1F582 /* MAXNativeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MAXNativeViewController.swift; sourceTree = ""; }; + 53514C952CFF97DB00A480C0 /* InAppDisplayBannerPluginRendererViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppDisplayBannerPluginRendererViewController.swift; sourceTree = ""; }; + 53514C982CFF988E00A480C0 /* SampleAdView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAdView.swift; sourceTree = ""; }; + 53514C992CFF988E00A480C0 /* SampleAdViewRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAdViewRenderer.swift; sourceTree = ""; }; + 53514C9A2CFF988E00A480C0 /* SampleInterstitialRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleInterstitialRenderer.swift; sourceTree = ""; }; + 53514C9B2CFF988E00A480C0 /* SampleInterstitialController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleInterstitialController.swift; sourceTree = ""; }; + 53514CA22CFF9DD000A480C0 /* InAppDisplayInterstitialPluginInterstitialViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppDisplayInterstitialPluginInterstitialViewController.swift; sourceTree = ""; }; + 53514CA52CFFA52A00A480C0 /* SampleAdView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleAdView.h; sourceTree = ""; }; + 53514CA62CFFA52A00A480C0 /* SampleAdView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleAdView.m; sourceTree = ""; }; + 53514CA82CFFA62700A480C0 /* SampleAdViewRenderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleAdViewRenderer.h; sourceTree = ""; }; + 53514CA92CFFA62700A480C0 /* SampleAdViewRenderer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleAdViewRenderer.m; sourceTree = ""; }; + 53514CAB2CFFA99200A480C0 /* InAppDisplayBannerPluginRendererViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InAppDisplayBannerPluginRendererViewController.h; sourceTree = ""; }; + 53514CAC2CFFA99200A480C0 /* InAppDisplayBannerPluginRendererViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InAppDisplayBannerPluginRendererViewController.m; sourceTree = ""; }; + 53514CAE2CFFAB6700A480C0 /* SampleInterstitialController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleInterstitialController.h; sourceTree = ""; }; + 53514CAF2CFFAB6700A480C0 /* SampleInterstitialController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleInterstitialController.m; sourceTree = ""; }; + 53514CB12CFFAD5E00A480C0 /* UIApplication+TopViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIApplication+TopViewController.h"; sourceTree = ""; }; + 53514CB22CFFAD5E00A480C0 /* UIApplication+TopViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIApplication+TopViewController.m"; sourceTree = ""; }; + 53514CB42CFFADC200A480C0 /* SampleInterstitialRenderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleInterstitialRenderer.h; sourceTree = ""; }; + 53514CB52CFFADC200A480C0 /* SampleInterstitialRenderer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleInterstitialRenderer.m; sourceTree = ""; }; + 53514CB72CFFAECB00A480C0 /* InAppDisplayInterstitialPluginRendererViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InAppDisplayInterstitialPluginRendererViewController.h; sourceTree = ""; }; + 53514CB82CFFAECB00A480C0 /* InAppDisplayInterstitialPluginRendererViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InAppDisplayInterstitialPluginRendererViewController.m; sourceTree = ""; }; 534C614C2CB7EFD50026119A /* InAppDisplayRewardedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppDisplayRewardedViewController.swift; sourceTree = ""; }; 534C614E2CB7F20A0026119A /* GAMDisplayRewardedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GAMDisplayRewardedViewController.swift; sourceTree = ""; }; 534C61542CB7F32D0026119A /* MAXDisplayRewardedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MAXDisplayRewardedViewController.swift; sourceTree = ""; }; @@ -549,8 +582,11 @@ 53072B4E2920DF1000228462 /* In-App */ = { isa = PBXGroup; children = ( + 53514C972CFF981100A480C0 /* SampleRenderers */, 53072B7629226CFE00228462 /* InAppDisplayBannerViewController.swift */, + 53514C952CFF97DB00A480C0 /* InAppDisplayBannerPluginRendererViewController.swift */, 53072B7A292270EE00228462 /* InAppDisplayInterstitialViewController.swift */, + 53514CA22CFF9DD000A480C0 /* InAppDisplayInterstitialPluginInterstitialViewController.swift */, 5344E69E2922796000A1F582 /* InAppNativeViewController.swift */, 53072B7829226EF400228462 /* InAppVideoBannerViewController.swift */, 53072B802922753D00228462 /* InAppVideoInterstitialLandscapeViewController.swift */, @@ -734,6 +770,32 @@ path = Helpers; sourceTree = ""; }; + 53514C972CFF981100A480C0 /* SampleRenderers */ = { + isa = PBXGroup; + children = ( + 53514C982CFF988E00A480C0 /* SampleAdView.swift */, + 53514C992CFF988E00A480C0 /* SampleAdViewRenderer.swift */, + 53514C9B2CFF988E00A480C0 /* SampleInterstitialController.swift */, + 53514C9A2CFF988E00A480C0 /* SampleInterstitialRenderer.swift */, + ); + path = SampleRenderers; + sourceTree = ""; + }; + 53514CA42CFFA4F000A480C0 /* SampleRenderers */ = { + isa = PBXGroup; + children = ( + 53514CA52CFFA52A00A480C0 /* SampleAdView.h */, + 53514CA62CFFA52A00A480C0 /* SampleAdView.m */, + 53514CA82CFFA62700A480C0 /* SampleAdViewRenderer.h */, + 53514CA92CFFA62700A480C0 /* SampleAdViewRenderer.m */, + 53514CAE2CFFAB6700A480C0 /* SampleInterstitialController.h */, + 53514CAF2CFFAB6700A480C0 /* SampleInterstitialController.m */, + 53514CB42CFFADC200A480C0 /* SampleInterstitialRenderer.h */, + 53514CB52CFFADC200A480C0 /* SampleInterstitialRenderer.m */, + ); + path = SampleRenderers; + sourceTree = ""; + }; 539928BC292534A70078053C /* IntegrationCase */ = { isa = PBXGroup; children = ( @@ -871,12 +933,17 @@ 539928D629254EEC0078053C /* InApp */ = { isa = PBXGroup; children = ( + 53514CA42CFFA4F000A480C0 /* SampleRenderers */, 53F35F262926A3E1001C1183 /* InAppDisplayBannerViewController.h */, 53F35F272926A3E1001C1183 /* InAppDisplayBannerViewController.m */, + 53514CAB2CFFA99200A480C0 /* InAppDisplayBannerPluginRendererViewController.h */, + 53514CAC2CFFA99200A480C0 /* InAppDisplayBannerPluginRendererViewController.m */, 53F35F292926A58B001C1183 /* InAppVideoBannerViewController.h */, 53F35F2A2926A58B001C1183 /* InAppVideoBannerViewController.m */, 53F35F2C2926A6D6001C1183 /* InAppDisplayInterstitialViewController.h */, 53F35F2D2926A6D6001C1183 /* InAppDisplayInterstitialViewController.m */, + 53514CB72CFFAECB00A480C0 /* InAppDisplayInterstitialPluginRendererViewController.h */, + 53514CB82CFFAECB00A480C0 /* InAppDisplayInterstitialPluginRendererViewController.m */, 53F35F2F2926B532001C1183 /* InAppVideoInterstitialViewController.h */, 53F35F302926B532001C1183 /* InAppVideoInterstitialViewController.m */, 53F35F322926BAFE001C1183 /* InAppVideoInterstitialVerticalViewController.h */, @@ -1064,6 +1131,8 @@ isa = PBXGroup; children = ( 53F35F192926908B001C1183 /* PrebidDemoMacros.h */, + 53514CB12CFFAD5E00A480C0 /* UIApplication+TopViewController.h */, + 53514CB22CFFAD5E00A480C0 /* UIApplication+TopViewController.m */, ); path = Utils; sourceTree = ""; @@ -1507,9 +1576,14 @@ 53B03D8C291A6562000117E1 /* ExamplesViewController.swift in Sources */, 5344E6C32922AAE500A1F582 /* MAXVideoRewardedViewController.swift in Sources */, 53072B6929217D1800228462 /* GAMOriginalAPIVideoInstreamViewController.swift in Sources */, + 53514CA32CFF9DD000A480C0 /* InAppDisplayInterstitialPluginInterstitialViewController.swift in Sources */, 5344E6A92922815000A1F582 /* GAMVideoRewardedViewController.swift in Sources */, 534C61572CB7F4780026119A /* AdMobDisplayRewardedViewController.swift in Sources */, 53072B7B292270EE00228462 /* InAppDisplayInterstitialViewController.swift in Sources */, + 53514C9E2CFF988E00A480C0 /* SampleAdView.swift in Sources */, + 53514C9F2CFF988E00A480C0 /* SampleInterstitialController.swift in Sources */, + 53514CA02CFF988E00A480C0 /* SampleAdViewRenderer.swift in Sources */, + 53514CA12CFF988E00A480C0 /* SampleInterstitialRenderer.swift in Sources */, 53072B5E2921522000228462 /* GAMOriginalAPIVideoRewardedViewController.swift in Sources */, 530D4AA6291A4BC600A2C796 /* AppDelegate.swift in Sources */, 53072B6C29217E8600228462 /* InstreamBaseViewController.swift in Sources */, @@ -1517,6 +1591,7 @@ 53072B812922753D00228462 /* InAppVideoInterstitialLandscapeViewController.swift in Sources */, 5344E6C12922A97200A1F582 /* MAXVideoInterstitialViewController.swift in Sources */, 53072B7D2922733800228462 /* InAppVideoInterstitialViewController.swift in Sources */, + 53514C962CFF97DB00A480C0 /* InAppDisplayBannerPluginRendererViewController.swift in Sources */, 534C614F2CB7F20A0026119A /* GAMDisplayRewardedViewController.swift in Sources */, 5344E6C52922AC2C00A1F582 /* MAXNativeViewController.swift in Sources */, 53B03DA5291BCCE1000117E1 /* GAMOriginalAPIDisplayBannerViewController.swift in Sources */, @@ -1577,11 +1652,13 @@ 539F960929DEEDE40061E7A5 /* GAMOriginalAPIMultiformatInterstitialViewController.m in Sources */, 53F35F3A2926BDB7001C1183 /* InAppVideoRewardedViewController.m in Sources */, 53A369012AB8CDEB00A03B3E /* GAMOriginalAPIMultiformatInAppNativeViewController.m in Sources */, + 53514CB02CFFAB6700A480C0 /* SampleInterstitialController.m in Sources */, 539928DB29254F2A0078053C /* BannerBaseViewController.m in Sources */, 53F35F57292792D6001C1183 /* SettingsViewController.m in Sources */, 534C61642CB851C10026119A /* MAXDisplayRewardedViewController.m in Sources */, 539928E22925505B0078053C /* InterstitialBaseViewController.m in Sources */, 53F35F432926C84E001C1183 /* MAXVideoBannerViewController.m in Sources */, + 53514CB92CFFAECB00A480C0 /* InAppDisplayInterstitialPluginRendererViewController.m in Sources */, 5399290A292665D80078053C /* GAMOriginalAPINativeViewController.m in Sources */, 539928F5292566AD0078053C /* GAMOriginalAPIDisplayBannerViewController.m in Sources */, 539F960629DEEA0A0061E7A5 /* GAMOriginalAPIMultiformatBannerViewController.m in Sources */, @@ -1591,11 +1668,14 @@ 53F35F492926CFE3001C1183 /* MAXVideoInterstitialViewController.m in Sources */, 53F35F03292671E7001C1183 /* GAMDisplayBannerViewController.m in Sources */, 533784CC2AC2CFF5009A8650 /* GAMOriginalAPIMultiformatNativeStylesViewController.m in Sources */, + 53514CAD2CFFA99200A480C0 /* InAppDisplayBannerPluginRendererViewController.m in Sources */, 539929012926488B0078053C /* GAMOriginalAPIVideoRewardedViewController.m in Sources */, + 53514CA72CFFA52A00A480C0 /* SampleAdView.m in Sources */, 53BA02C5292531D100BE6015 /* main.m in Sources */, 53F35F1C292692DC001C1183 /* AdMobDisplayInterstitialViewController.m in Sources */, 53BA02B7292531D000BE6015 /* SceneDelegate.m in Sources */, 53F35F312926B532001C1183 /* InAppVideoInterstitialViewController.m in Sources */, + 53514CB32CFFAD5E00A480C0 /* UIApplication+TopViewController.m in Sources */, 53F35F1829268C62001C1183 /* AdMobVideoBannerViewController.m in Sources */, 53F35F0929267A30001C1183 /* GAMDisplayInterstitialViewController.m in Sources */, 53F35F152926845C001C1183 /* AdMobDisplayBannerViewController.m in Sources */, @@ -1608,6 +1688,8 @@ 53A368FD2AB8CBB300A03B3E /* MultiformatBaseViewController.m in Sources */, 53F35F2B2926A58B001C1183 /* InAppVideoBannerViewController.m in Sources */, 53F35F4C2926D130001C1183 /* MAXVideoRewardedViewController.m in Sources */, + 53514CAA2CFFA62700A480C0 /* SampleAdViewRenderer.m in Sources */, + 53514CB62CFFADC200A480C0 /* SampleInterstitialRenderer.m in Sources */, 53F35F1F29269668001C1183 /* AdMobVideoInterstitialViewController.m in Sources */, 539928C92925379C0078053C /* IntegrationKindDescriptor.m in Sources */, 53F35F0C29267C65001C1183 /* GAMVideoInterstitialViewController.m in Sources */, diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.h b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.h new file mode 100644 index 000000000..61457c5a1 --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.h @@ -0,0 +1,26 @@ +/* Copyright 2019-2022 Prebid.org, Inc. + + 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 "BannerBaseViewController.h" + +@import PrebidMobile; + +NS_ASSUME_NONNULL_BEGIN + +@interface InAppDisplayBannerPluginRendererViewController : BannerBaseViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.m new file mode 100644 index 000000000..efb37e121 --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.m @@ -0,0 +1,71 @@ +/* Copyright 2019-2022 Prebid.org, Inc. + + 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 "InAppDisplayBannerPluginRendererViewController.h" +#import "PrebidDemoMacros.h" +#import "SampleAdViewRenderer.h" + +NSString * const storedImpDisplayBannerPluginRendererInApp = @"prebid-demo-display-banner-320-50-custom-ad-view-renderer"; + +@interface InAppDisplayBannerPluginRendererViewController () + +// Prebid +@property (nonatomic) BannerView * prebidBannerView; + +@end + +@implementation InAppDisplayBannerPluginRendererViewController + +- (void)loadView { + [super loadView]; + + [self createAd]; +} + +- (void)createAd { + // 1. Create a plugin renderer + SampleAdViewRenderer * samplePluginRenderer = [SampleAdViewRenderer new]; + + // 2. Register the plugin renderer + [Prebid registerPluginRenderer:samplePluginRenderer]; + + // 3. Create a BannerView + self.prebidBannerView = [[BannerView alloc] initWithFrame:CGRectMake(0, 0, self.adSize.width, self.adSize.height) + configID:storedImpDisplayBannerPluginRendererInApp + adSize:self.adSize]; + + // 4. Configure the BannerView + self.prebidBannerView.delegate = self; + self.prebidBannerView.adFormat = AdFormat.banner; + self.prebidBannerView.videoParameters.placement = PBPlacement.InBanner; + + // Add Prebid banner view to the app UI + [self.bannerView addSubview:self.prebidBannerView]; + + // 5. Load the banner ad + [self.prebidBannerView loadAd]; +} + +// MARK: - BannerViewDelegate + +- (UIViewController *)bannerViewPresentationController { + return self; +} + +- (void)bannerView:(BannerView *)bannerView didFailToReceiveAdWith:(NSError *)error { + PBMLogError(@"%@", error.localizedDescription); +} + +@end diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.h b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.h new file mode 100644 index 000000000..29fd8d29f --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.h @@ -0,0 +1,26 @@ +/* Copyright 2019-2022 Prebid.org, Inc. + + 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 "InterstitialBaseViewController.h" + +@import PrebidMobile; + +NS_ASSUME_NONNULL_BEGIN + +@interface InAppDisplayInterstitialPluginRendererViewController : InterstitialBaseViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.m new file mode 100644 index 000000000..755115bc8 --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.m @@ -0,0 +1,65 @@ +/* Copyright 2019-2022 Prebid.org, Inc. + + 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 "InAppDisplayInterstitialPluginRendererViewController.h" +#import "PrebidDemoMacros.h" +#import "SampleInterstitialRenderer.h" + +NSString * const storedImpDisplayInterstitialPluginRendererInApp = @"prebid-demo-display-interstitial-320-480-custom-interstitial-renderer"; + +@interface InAppDisplayInterstitialPluginRendererViewController () + +// Prebid +@property (nonatomic) InterstitialRenderingAdUnit * renderingInterstitial; + +@end + +@implementation InAppDisplayInterstitialPluginRendererViewController + +- (void)loadView { + [super loadView]; + + [self createAd]; +} + +- (void)createAd { + // 1. Create a plugin renderer + SampleInterstitialRenderer * samplePluginRenderer = [SampleInterstitialRenderer new]; + + // 2. Register the plugin renderer + [Prebid registerPluginRenderer:samplePluginRenderer]; + + // 3. Create a InterstitialRenderingAdUnit + self.renderingInterstitial = [[InterstitialRenderingAdUnit alloc] initWithConfigID:storedImpDisplayInterstitialPluginRendererInApp]; + + // 4. Configure the InterstitialRenderingAdUnit + self.renderingInterstitial.adFormats = [[NSSet alloc] initWithObjects:AdFormat.banner, nil]; + self.renderingInterstitial.delegate = self; + + // 5. Load the interstitial ad + [self.renderingInterstitial loadAd]; +} + +// MARK: - InterstitialAdUnitDelegate + +- (void)interstitialDidReceiveAd:(InterstitialRenderingAdUnit *)interstitial { + [self.renderingInterstitial showFrom:self]; +} + +- (void)interstitial:(InterstitialRenderingAdUnit *)interstitial didFailToReceiveAdWithError:(NSError *)error { + PBMLogError(@"%@", error.localizedDescription); +} + +@end diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdView.h b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdView.h new file mode 100644 index 000000000..462dbf429 --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdView.h @@ -0,0 +1,35 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 +#import + +@import PrebidMobile; + +NS_ASSUME_NONNULL_BEGIN + +/// An example showcasing the implementation of the `PrebidMobileDisplayViewProtocol`. +/// A sample view that is used for rendering ads. +@interface SampleAdView : UIView + +@property (nonatomic, weak, nullable) id interactionDelegate; +@property (nonatomic, weak, nullable) id loadingDelegate; +@property (nonatomic, strong) Bid *bid; + +- (void)loadAd; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdView.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdView.m new file mode 100644 index 000000000..b355d5b6c --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdView.m @@ -0,0 +1,89 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 "SampleAdView.h" + +@interface SampleAdView () + +@property (nonatomic, strong) WKWebView *webView; +@property (nonatomic, strong) UILabel *customRendererLabel; + +@end + +@implementation SampleAdView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self setupView]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if (self) { + [self setupView]; + } + return self; +} + +- (void)setupView { + self.webView = [[WKWebView alloc] init]; + self.webView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:self.webView]; + + self.customRendererLabel = [[UILabel alloc] init]; + self.customRendererLabel.translatesAutoresizingMaskIntoConstraints = NO; + self.customRendererLabel.text = @"Custom Renderer"; + self.customRendererLabel.textColor = [UIColor whiteColor]; + self.customRendererLabel.font = [UIFont boldSystemFontOfSize:10]; + self.customRendererLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; + self.customRendererLabel.textAlignment = NSTextAlignmentCenter; + self.customRendererLabel.layer.cornerRadius = 5; + self.customRendererLabel.layer.masksToBounds = YES; + self.customRendererLabel.numberOfLines = 0; + [self addSubview:self.customRendererLabel]; + + [NSLayoutConstraint activateConstraints:@[ + [self.webView.topAnchor constraintEqualToAnchor:self.topAnchor], + [self.webView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor], + [self.webView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor], + [self.webView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor], + + [self.customRendererLabel.topAnchor constraintEqualToAnchor:self.topAnchor constant:5], + [self.customRendererLabel.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:10], + [self.customRendererLabel.heightAnchor constraintEqualToConstant:40], + [self.customRendererLabel.widthAnchor constraintEqualToConstant:50] + ]]; +} + +- (void)loadAd { + dispatch_async(dispatch_get_main_queue(), ^{ + if (self.bid.adm) { + [self.webView loadHTMLString:self.bid.adm baseURL:nil]; + [self.loadingDelegate displayViewDidLoadAd:self]; + } else { + NSString * errorMessage = @"Renderer did fail - there is no ADM in the response."; + NSError *error = [NSError errorWithDomain:@"SampleAdViewErrorDomain" + code:101 + userInfo:@{NSLocalizedDescriptionKey: errorMessage}]; + + [self.loadingDelegate displayView:self didFailWithError:error]; + } + }); +} + +@end diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.h b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.h new file mode 100644 index 000000000..ad45e59d3 --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.h @@ -0,0 +1,30 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 +#import "SampleAdView.h" + +@import PrebidMobile; + +NS_ASSUME_NONNULL_BEGIN + +/// A custom implementation of the ad view renderer. +@interface SampleAdViewRenderer : NSObject + +- (instancetype)init; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.m new file mode 100644 index 000000000..f4e67182e --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.m @@ -0,0 +1,51 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 "SampleAdViewRenderer.h" + +@implementation SampleAdViewRenderer + +@synthesize name; +@synthesize version; +@synthesize data; + +- (instancetype)init { + self = [super init]; + if (self) { + name = @"SampleAdViewRenderer"; + version = @"1.0.0"; + } + return self; +} + +- (BOOL)isSupportRenderingFor:(AdFormat *)format { + return YES; +} + +- (UIView * _Nullable)createAdViewWith:(CGRect)frame + bid:(Bid * _Nonnull)bid + adConfiguration:(AdUnitConfig * _Nonnull)adConfiguration + loadingDelegate:(id _Nonnull)loadingDelegate + interactionDelegate:(id _Nonnull)interactionDelegate { + SampleAdView *adView = [[SampleAdView alloc] initWithFrame:frame]; + + adView.interactionDelegate = interactionDelegate; + adView.loadingDelegate = loadingDelegate; + adView.bid = bid; + + return adView; +} + +@end diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialController.h b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialController.h new file mode 100644 index 000000000..48890d3d1 --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialController.h @@ -0,0 +1,33 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 +#import + +@import PrebidMobile; + +NS_ASSUME_NONNULL_BEGIN + +/// An example showcasing the implementation of the `PrebidMobileInterstitialControllerProtocol`. +/// A sample controller that is used for rendering ads. +@interface SampleInterstitialController : NSObject + +@property (nonatomic, weak) id loadingDelegate; +@property (nonatomic, weak) id interactionDelegate; +@property (nonatomic, strong) Bid *bid; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialController.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialController.m new file mode 100644 index 000000000..cdb3894c9 --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialController.m @@ -0,0 +1,89 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 "SampleInterstitialController.h" +#import "UIApplication+TopViewController.h" + +@interface SampleInterstitialController () + +@property (nonatomic, strong) UILabel *customRendererLabel; +@property (nonatomic, strong) WKWebView *webView; +@property (nonatomic, strong) UIViewController *interstitialViewController; + +@end + +@implementation SampleInterstitialController + +- (instancetype)init { + self = [super init]; + if (self) { + _webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 300, 250)]; + _webView.translatesAutoresizingMaskIntoConstraints = NO; + _webView.backgroundColor = [UIColor blueColor]; + + _customRendererLabel = [[UILabel alloc] init]; + _customRendererLabel.text = @"Custom Renderer"; + _customRendererLabel.textAlignment = NSTextAlignmentCenter; + _customRendererLabel.font = [UIFont boldSystemFontOfSize:18]; + _customRendererLabel.translatesAutoresizingMaskIntoConstraints = NO; + + _interstitialViewController = [[UIViewController alloc] init]; + _interstitialViewController.view.backgroundColor = [UIColor whiteColor]; + [_interstitialViewController.view addSubview:self.customRendererLabel]; + [_interstitialViewController.view addSubview:self.webView]; + + [NSLayoutConstraint activateConstraints:@[ + [self.customRendererLabel.topAnchor constraintEqualToAnchor:self.interstitialViewController.view.safeAreaLayoutGuide.topAnchor constant:20], + [self.customRendererLabel.centerXAnchor constraintEqualToAnchor:self.interstitialViewController.view.centerXAnchor], + [self.webView.centerXAnchor constraintEqualToAnchor:self.interstitialViewController.view.centerXAnchor], + [self.webView.centerYAnchor constraintEqualToAnchor:self.interstitialViewController.view.centerYAnchor], + [self.webView.widthAnchor constraintEqualToConstant:300], + [self.webView.heightAnchor constraintEqualToConstant:250] + ]]; + } + return self; +} + +- (void)loadAd { + dispatch_async(dispatch_get_main_queue(), ^{ + if (self.bid.adm) { + [self.webView loadHTMLString:self.bid.adm baseURL:nil]; + [self.loadingDelegate interstitialControllerDidLoadAd:self]; + } else { + NSString * errorMessage = @"Renderer did fail - there is no ADM in the response."; + NSError *error = [NSError errorWithDomain:@"SampleInterstitialControllerErrorDomain" + code:102 + userInfo:@{NSLocalizedDescriptionKey: errorMessage}]; + [self.loadingDelegate interstitialController:self didFailWithError:error]; + } + }); +} + +- (void)show { + dispatch_async(dispatch_get_main_queue(), ^{ + UIViewController *presentingController = [UIApplication.sharedApplication topViewController]; + if (presentingController) { + [presentingController presentViewController:self.interstitialViewController animated:YES completion:nil]; + } else { + NSString * errorMessage = @"Couldn't find a controller to present from."; + NSError *error = [NSError errorWithDomain:@"SampleInterstitialControllerErrorDomain" + code:103 + userInfo:@{NSLocalizedDescriptionKey: errorMessage}]; + [self.loadingDelegate interstitialController:self didFailWithError:error]; + } + }); +} + +@end diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.h b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.h new file mode 100644 index 000000000..59fee647a --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.h @@ -0,0 +1,30 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 +#import "SampleInterstitialController.h" + +@import PrebidMobile; + +NS_ASSUME_NONNULL_BEGIN + +/// A custom implementation of the interstitial ad renderer. +@interface SampleInterstitialRenderer : NSObject + +- (instancetype)init; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.m new file mode 100644 index 000000000..e8a2f2716 --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.m @@ -0,0 +1,51 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 "SampleInterstitialRenderer.h" +#import "SampleInterstitialController.h" + +@implementation SampleInterstitialRenderer + +@synthesize name; +@synthesize version; +@synthesize data; + +- (instancetype)init { + self = [super init]; + if (self) { + name = @"SampleInterstitialRenderer"; + version = @"1.0.0"; + } + return self; +} + +- (BOOL)isSupportRenderingFor:(AdFormat *)format { + return YES; +} + +- (id)createInterstitialControllerWithBid:(Bid *)bid + adConfiguration:(AdUnitConfig *)adConfiguration + loadingDelegate:(id)loadingDelegate + interactionDelegate:(id)interactionDelegate { + SampleInterstitialController *interstitialController = [[SampleInterstitialController alloc] init]; + + interstitialController.loadingDelegate = loadingDelegate; + interstitialController.interactionDelegate = interactionDelegate; + interstitialController.bid = bid; + + return interstitialController; +} + +@end diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/IntegrationCase/IntegrationCaseManager.m b/Example/PrebidDemo/PrebidDemoObjectiveC/IntegrationCase/IntegrationCaseManager.m index b2f5959f5..c0893d4eb 100644 --- a/Example/PrebidDemo/PrebidDemoObjectiveC/IntegrationCase/IntegrationCaseManager.m +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/IntegrationCase/IntegrationCaseManager.m @@ -30,8 +30,10 @@ #import "GAMOriginalAPIMultiformatNativeStylesViewController.h" #import "InAppDisplayBannerViewController.h" +#import "InAppDisplayBannerPluginRendererViewController.h" #import "InAppVideoBannerViewController.h" #import "InAppDisplayInterstitialViewController.h" +#import "InAppDisplayInterstitialPluginRendererViewController.h" #import "InAppVideoInterstitialViewController.h" #import "InAppVideoInterstitialVerticalViewController.h" #import "InAppVideoInterstitialLandscapeViewController.h" @@ -200,6 +202,16 @@ @implementation IntegrationCaseManager } ], + [ + [IntegrationCase alloc] + initWithTitle:@"In-App Display Banner Plugin Renderer 320x50" + integrationKind:IntegrationKindInApp + adFormat:AdFormatDisplayBanner + configurationClosure:^UIViewController *{ + return [[InAppDisplayBannerPluginRendererViewController alloc] init]; + } + ], + [ [IntegrationCase alloc] initWithTitle:@"In-App Video Banner 300x250" @@ -219,6 +231,16 @@ @implementation IntegrationCaseManager return [[InAppDisplayInterstitialViewController alloc] init]; } ], + + [ + [IntegrationCase alloc] + initWithTitle:@"In-App Display Interstitial Plugin Renderer 320x480" + integrationKind:IntegrationKindInApp + adFormat:AdFormatDisplayInterstitial + configurationClosure:^UIViewController *{ + return [[InAppDisplayInterstitialPluginRendererViewController alloc] init]; + } + ], [ [IntegrationCase alloc] diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Utils/UIApplication+TopViewController.h b/Example/PrebidDemo/PrebidDemoObjectiveC/Utils/UIApplication+TopViewController.h new file mode 100644 index 000000000..6c0cfd574 --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Utils/UIApplication+TopViewController.h @@ -0,0 +1,26 @@ +/* Copyright 2019-2024 Prebid.org, Inc. + + 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 + +NS_ASSUME_NONNULL_BEGIN + +@interface UIApplication (TopViewController) + +- (UIViewController * _Nullable)topViewController; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Utils/UIApplication+TopViewController.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Utils/UIApplication+TopViewController.m new file mode 100644 index 000000000..ebe70a044 --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Utils/UIApplication+TopViewController.m @@ -0,0 +1,66 @@ +/* Copyright 2019-2024 Prebid.org, Inc. + + 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 "UIApplication+TopViewController.h" + +@implementation UIApplication (TopViewController) + +- (UIViewController * _Nullable)topViewController { + UIWindow *keyWindow = nil; + + for (UIScene *scene in self.connectedScenes) { + if ([scene isKindOfClass:[UIWindowScene class]]) { + UIWindowScene *windowScene = (UIWindowScene *)scene; + for (UIWindow *window in windowScene.windows) { + if (window.isKeyWindow) { + keyWindow = window; + break; + } + } + } + if (keyWindow) break; + } + + if (!keyWindow) { + return nil; + } + + UIViewController *rootViewController = keyWindow.rootViewController; + if (!rootViewController) { + return nil; + } + + return [self findTopMostViewControllerFrom:rootViewController]; +} + +- (UIViewController *)findTopMostViewControllerFrom:(UIViewController *)viewController { + if (viewController.presentedViewController) { + return [self findTopMostViewControllerFrom:viewController.presentedViewController]; + } + + if ([viewController isKindOfClass:[UINavigationController class]]) { + UINavigationController *navigationController = (UINavigationController *)viewController; + return [self findTopMostViewControllerFrom:navigationController.visibleViewController]; + } + + if ([viewController isKindOfClass:[UITabBarController class]]) { + UITabBarController *tabBarController = (UITabBarController *)viewController; + return [self findTopMostViewControllerFrom:tabBarController.selectedViewController]; + } + + return viewController; +} + +@end diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerCustomRendererViewController.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerCustomRendererViewController.swift new file mode 100644 index 000000000..1020b526a --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerCustomRendererViewController.swift @@ -0,0 +1,66 @@ +/* Copyright 2019-2024 Prebid.org, Inc. + + 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 UIKit +import PrebidMobile + +fileprivate let storedImpDisplayBanner = "prebid-demo-display-banner-320-50-custom-ad-view-renderer" + +class InAppDisplayBannerPluginRendererViewController: BannerBaseViewController, BannerViewDelegate { + + // Prebid + private var prebidBannerView: BannerView! + + override func loadView() { + super.loadView() + + createAd() + } + + func createAd() { + // 1. Create a plugin renderer + let samplePluginRenderer = SampleAdViewRenderer() + + // 2. Register the plugin renderer + Prebid.registerPluginRenderer(samplePluginRenderer) + + // 3. Create a BannerView + prebidBannerView = BannerView( + frame: CGRect(origin: .zero, size: adSize), + configID: storedImpDisplayBanner, adSize: adSize + ) + + // 4. Configure the BannerView + prebidBannerView.delegate = self + prebidBannerView.adFormat = .banner + prebidBannerView.videoParameters.placement = .InBanner + + // Add Prebid banner view to the app UI + bannerView.addSubview(prebidBannerView) + + // 5. Load the banner ad + prebidBannerView.loadAd() + } + + // MARK: - BannerViewDelegate + + func bannerViewPresentationController() -> UIViewController? { + self + } + + func bannerView(_ bannerView: BannerView, didFailToReceiveAdWith error: Error) { + PrebidDemoLogger.shared.error("Banner view did fail to receive ad with error: \(error)") + } +} diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift new file mode 100644 index 000000000..1020b526a --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift @@ -0,0 +1,66 @@ +/* Copyright 2019-2024 Prebid.org, Inc. + + 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 UIKit +import PrebidMobile + +fileprivate let storedImpDisplayBanner = "prebid-demo-display-banner-320-50-custom-ad-view-renderer" + +class InAppDisplayBannerPluginRendererViewController: BannerBaseViewController, BannerViewDelegate { + + // Prebid + private var prebidBannerView: BannerView! + + override func loadView() { + super.loadView() + + createAd() + } + + func createAd() { + // 1. Create a plugin renderer + let samplePluginRenderer = SampleAdViewRenderer() + + // 2. Register the plugin renderer + Prebid.registerPluginRenderer(samplePluginRenderer) + + // 3. Create a BannerView + prebidBannerView = BannerView( + frame: CGRect(origin: .zero, size: adSize), + configID: storedImpDisplayBanner, adSize: adSize + ) + + // 4. Configure the BannerView + prebidBannerView.delegate = self + prebidBannerView.adFormat = .banner + prebidBannerView.videoParameters.placement = .InBanner + + // Add Prebid banner view to the app UI + bannerView.addSubview(prebidBannerView) + + // 5. Load the banner ad + prebidBannerView.loadAd() + } + + // MARK: - BannerViewDelegate + + func bannerViewPresentationController() -> UIViewController? { + self + } + + func bannerView(_ bannerView: BannerView, didFailToReceiveAdWith error: Error) { + PrebidDemoLogger.shared.error("Banner view did fail to receive ad with error: \(error)") + } +} diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayInterstitialPluginInterstitialViewController.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayInterstitialPluginInterstitialViewController.swift new file mode 100644 index 000000000..f6fc4bbff --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayInterstitialPluginInterstitialViewController.swift @@ -0,0 +1,61 @@ +/* Copyright 2019-2022 Prebid.org, Inc. + + 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 UIKit +import PrebidMobile + +fileprivate let storedImpDisplayInterstitial = "prebid-demo-display-interstitial-320-480-custom-interstitial-renderer" + +class InAppDisplayInterstitialPluginInterstitialViewController: + UIViewController, + InterstitialAdUnitDelegate { + + // Prebid + private var renderingInterstitial: InterstitialRenderingAdUnit! + + override func loadView() { + super.loadView() + + createAd() + } + + func createAd() { + // 1. Create a plugin renderer + let samplePluginRenderer = SampleInterstitialRenderer() + + // 2. Register the plugin renderer + Prebid.registerPluginRenderer(samplePluginRenderer) + + // 3. Create a InterstitialRenderingAdUnit + renderingInterstitial = InterstitialRenderingAdUnit(configID: storedImpDisplayInterstitial) + + // 4. Configure the InterstitialRenderingAdUnit + renderingInterstitial.adFormats = [.banner] + renderingInterstitial.delegate = self + + // 5. Load the interstitial ad + renderingInterstitial.loadAd() + } + + // MARK: - InterstitialAdUnitDelegate + + func interstitialDidReceiveAd(_ interstitial: InterstitialRenderingAdUnit) { + interstitial.show(from: self) + } + + func interstitial(_ interstitial: InterstitialRenderingAdUnit, didFailToReceiveAdWithError error: Error?) { + PrebidDemoLogger.shared.error("Interstitial Rendering ad unit did fail to receive ad with error: \(error)") + } +} diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleAdView.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleAdView.swift new file mode 100644 index 000000000..9e5ef79a5 --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleAdView.swift @@ -0,0 +1,97 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + +  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 UIKit +import WebKit +import PrebidMobile + +/// An example showcasing the implementation of the `PrebidMobileDisplayViewProtocol`. +/// A sample view that is used for rendering ads. +class SampleAdView: UIView, PrebidMobileDisplayViewProtocol { + + enum SampleError: LocalizedError { + case noAdm + + var errorDescription: String? { + switch self { + case .noAdm: + return "Renderer did fail - there is no ADM in the response." + } + } + } + + weak var interactionDelegate: DisplayViewInteractionDelegate? + weak var loadingDelegate: DisplayViewLoadingDelegate? + + var bid: Bid? + + private let webView: WKWebView = { + let webView = WKWebView() + webView.translatesAutoresizingMaskIntoConstraints = false + return webView + }() + + private let customRendererLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.text = "Custom Renderer" + label.textColor = .white + label.font = UIFont.boldSystemFont(ofSize: 10) + label.backgroundColor = UIColor.black.withAlphaComponent(0.5) + label.textAlignment = .center + label.layer.cornerRadius = 5 + label.layer.masksToBounds = true + label.numberOfLines = 0 + return label + }() + + override init(frame: CGRect) { + super.init(frame: frame) + setupView() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupView() + } + + func loadAd() { + DispatchQueue.main.async { + if let adm = self.bid?.adm { + self.webView.loadHTMLString(adm, baseURL: nil) + self.loadingDelegate?.displayViewDidLoadAd(self) + } else { + self.loadingDelegate?.displayView(self, didFailWithError: SampleError.noAdm) + } + } + } + + private func setupView() { + addSubview(webView) + addSubview(customRendererLabel) + + NSLayoutConstraint.activate([ + webView.topAnchor.constraint(equalTo: topAnchor), + webView.leadingAnchor.constraint(equalTo: leadingAnchor), + webView.trailingAnchor.constraint(equalTo: trailingAnchor), + webView.bottomAnchor.constraint(equalTo: bottomAnchor), + + customRendererLabel.topAnchor.constraint(equalTo: topAnchor, constant: 5), + customRendererLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 10), + customRendererLabel.heightAnchor.constraint(equalToConstant: 40), + customRendererLabel.widthAnchor.constraint(equalToConstant: 50) + ]) + } +} diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleAdViewRenderer.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleAdViewRenderer.swift new file mode 100644 index 000000000..8c4644859 --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleAdViewRenderer.swift @@ -0,0 +1,46 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + + 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 UIKit +import PrebidMobile + +/// A custom implementation of the ad view renderer. +public class SampleAdViewRenderer: NSObject, PrebidMobileAdViewPluginRenderer { + + public let name = "SampleAdViewRenderer" + public let version = "1.0.0" + public var data: [AnyHashable: Any]? + + public func isSupportRendering(for format: PrebidMobile.AdFormat?) -> Bool { + [PrebidMobile.AdFormat.banner, PrebidMobile.AdFormat.video].contains(format) + } + + /// This method creates an instance of `SampleAdView`, which is a custom view used to display the ad. + public func createAdView( + with frame: CGRect, + bid: Bid, + adConfiguration: AdUnitConfig, + loadingDelegate: DisplayViewLoadingDelegate, + interactionDelegate: DisplayViewInteractionDelegate + ) -> (UIView & PrebidMobileDisplayViewProtocol)? { + let adView = SampleAdView(frame: frame) + + adView.interactionDelegate = interactionDelegate + adView.loadingDelegate = loadingDelegate + adView.bid = bid + + return adView + } +} diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialController.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialController.swift new file mode 100644 index 000000000..1713dc68d --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialController.swift @@ -0,0 +1,108 @@ +/*   Copyright 2018-2021 Prebid.org, Inc. + +  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 UIKit +import WebKit +import PrebidMobile + +/// An example showcasing the implementation of the `PrebidMobileInterstitialControllerProtocol`. +/// A sample controller that is used for rendering ads. +class SampleInterstitialController: + NSObject, + PrebidMobileInterstitialControllerProtocol { + + enum SampleError: LocalizedError { + case noAdm + case noAvailableController + + var errorDescription: String? { + switch self { + case .noAdm: + return "Renderer did fail - there is no ADM in the response." + case .noAvailableController: + return "Coudn't find a controller to present from." + } + } + } + + weak var loadingDelegate: InterstitialControllerLoadingDelegate? + weak var interactionDelegate: InterstitialControllerInteractionDelegate? + + var bid: Bid? + + private let webView: WKWebView = { + let webView = WKWebView(frame: CGRect(origin: .zero, size: CGSize(width: 300, height: 250))) + webView.translatesAutoresizingMaskIntoConstraints = false + webView.backgroundColor = .blue + return webView + }() + + private let customRendererLabel: UILabel = { + let label = UILabel() + label.text = "Custom Renderer" + label.textAlignment = .center + label.font = UIFont.boldSystemFont(ofSize: 18) + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + private lazy var interstitialViewController: UIViewController = { + let controller = UIViewController() + + controller.view.backgroundColor = .white + controller.view.addSubview(customRendererLabel) + controller.view.addSubview(webView) + + NSLayoutConstraint.activate([ + customRendererLabel.topAnchor.constraint(equalTo: controller.view.safeAreaLayoutGuide.topAnchor, constant: 20), + customRendererLabel.centerXAnchor.constraint(equalTo: controller.view.centerXAnchor), + webView.centerXAnchor.constraint(equalTo: controller.view.centerXAnchor), + webView.centerYAnchor.constraint(equalTo: controller.view.centerYAnchor), + webView.widthAnchor.constraint(equalToConstant: 300), + webView.heightAnchor.constraint(equalToConstant: 250), + ]) + + return controller + }() + + func loadAd() { + DispatchQueue.main.async { + guard let adm = self.bid?.adm else { + self.loadingDelegate?.interstitialController(self, didFailWithError: SampleError.noAdm) + return + } + + self.webView.loadHTMLString(adm, baseURL: nil) + self.loadingDelegate?.interstitialControllerDidLoadAd(self) + } + } + + func show() { + DispatchQueue.main.async { + guard let presentingController = UIApplication.shared.topViewController else { + self.loadingDelegate?.interstitialController( + self, + didFailWithError: SampleError.noAvailableController + ) + return + } + + presentingController.present( + self.interstitialViewController, + animated: true + ) + } + } +} diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialRenderer.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialRenderer.swift new file mode 100644 index 000000000..f3a8a0ec1 --- /dev/null +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialRenderer.swift @@ -0,0 +1,46 @@ +/*   Copyright 2018-2024 Prebid.org, Inc. + + 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 UIKit +import PrebidMobile + +/// A custom implementation of the interstitial ad renderer. +class SampleInterstitialRenderer: PrebidMobileInterstitialPluginRenderer { + + var name = "SampleInterstitialRenderer" + var version = "1.0.0" + var data: [AnyHashable : Any]? + + func isSupportRendering(for format: PrebidMobile.AdFormat?) -> Bool { + [PrebidMobile.AdFormat.banner, PrebidMobile.AdFormat.video].contains(format) + } + + /// This method creates an instance of `SampleInterstitialController`, + /// a custom controller used to display interstitial ads. + func createInterstitialController( + bid: Bid, + adConfiguration: AdUnitConfig, + loadingDelegate: InterstitialControllerLoadingDelegate, + interactionDelegate: InterstitialControllerInteractionDelegate + ) -> PrebidMobileInterstitialControllerProtocol? { + let interstitialController = SampleInterstitialController() + + interstitialController.loadingDelegate = loadingDelegate + interstitialController.interactionDelegate = interactionDelegate + interstitialController.bid = bid + + return interstitialController + } +} diff --git a/Example/PrebidDemo/PrebidDemoSwift/Extensions/UIApplication+Extensions.swift b/Example/PrebidDemo/PrebidDemoSwift/Extensions/UIApplication+Extensions.swift index a4302a61c..a92d6ce19 100644 --- a/Example/PrebidDemo/PrebidDemoSwift/Extensions/UIApplication+Extensions.swift +++ b/Example/PrebidDemo/PrebidDemoSwift/Extensions/UIApplication+Extensions.swift @@ -16,16 +16,51 @@ import UIKit extension UIApplication { + func getKeyWindow() -> UIWindow? { - for scene in UIApplication.shared.connectedScenes { - if let windowScene = scene as? UIWindowScene { - for window in windowScene.windows { - if window.isKeyWindow { - return window - } + for scene in UIApplication.shared.connectedScenes { + if let windowScene = scene as? UIWindowScene { + for window in windowScene.windows { + if window.isKeyWindow { + return window } } } + } + return nil } + + var topViewController: UIViewController? { + guard let keyWindow = connectedScenes + .compactMap({ $0 as? UIWindowScene }) + .flatMap({ $0.windows }) + .first(where: { $0.isKeyWindow }) else { + return nil + } + + guard let rootViewController = keyWindow.rootViewController else { + return nil + } + + return findTopMostViewController(from: rootViewController) + } + + private func findTopMostViewController(from viewController: UIViewController) -> UIViewController { + if let presentedViewController = viewController.presentedViewController { + return findTopMostViewController(from: presentedViewController) + } + + if let navigationController = viewController as? UINavigationController, + let visibleViewController = navigationController.visibleViewController { + return findTopMostViewController(from: visibleViewController) + } + + if let tabBarController = viewController as? UITabBarController, + let selectedViewController = tabBarController.selectedViewController { + return findTopMostViewController(from: selectedViewController) + } + + return viewController + } } diff --git a/Example/PrebidDemo/PrebidDemoSwift/IntegrationCase/IntegrationCaseManager.swift b/Example/PrebidDemo/PrebidDemoSwift/IntegrationCase/IntegrationCaseManager.swift index 1635cec7c..e7f5311dc 100644 --- a/Example/PrebidDemo/PrebidDemoSwift/IntegrationCase/IntegrationCaseManager.swift +++ b/Example/PrebidDemo/PrebidDemoSwift/IntegrationCase/IntegrationCaseManager.swift @@ -142,6 +142,15 @@ struct IntegrationCaseManager { } ), + IntegrationCase( + title: "In-App Display Banner Plugin Renderer 320x50", + integrationKind: .inApp, + adFormat: .displayBanner, + configurationClosure: { + InAppDisplayBannerPluginRendererViewController() + } + ), + IntegrationCase( title: "In-App Video Banner 300x250", integrationKind: .inApp, @@ -160,6 +169,15 @@ struct IntegrationCaseManager { } ), + IntegrationCase( + title: "In-App Display Interstitial Plugin Renderer 320x480", + integrationKind: .inApp, + adFormat: .displayInterstitial, + configurationClosure: { + InAppDisplayInterstitialPluginInterstitialViewController() + } + ), + IntegrationCase( title: "In-App Video Interstitial 320x480", integrationKind: .inApp, diff --git a/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj b/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj index 3de5bf150..084c496a5 100644 --- a/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj +++ b/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj @@ -53,14 +53,14 @@ 53A369092AB996EF00A03B3E /* PrebidMultiformatConfigurationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A369072AB996EF00A03B3E /* PrebidMultiformatConfigurationController.swift */; }; 53A651842AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A651832AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift */; }; 53A651852AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A651832AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift */; }; - 53BFCD032CF792FB00A3287A /* SampleCustomAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD022CF792FB00A3287A /* SampleCustomAdViewRenderer.swift */; }; - 53BFCD042CF792FB00A3287A /* SampleCustomAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD022CF792FB00A3287A /* SampleCustomAdViewRenderer.swift */; }; + 53BFCD032CF792FB00A3287A /* SampleAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD022CF792FB00A3287A /* SampleAdViewRenderer.swift */; }; + 53BFCD042CF792FB00A3287A /* SampleAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD022CF792FB00A3287A /* SampleAdViewRenderer.swift */; }; 53BFCD0C2CF8F56300A3287A /* SampleAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */; }; 53BFCD0D2CF8F56300A3287A /* SampleAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */; }; 53BFCD132CF9C67400A3287A /* SampleInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD122CF9C67400A3287A /* SampleInterstitialController.swift */; }; 53BFCD142CF9C67400A3287A /* SampleInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD122CF9C67400A3287A /* SampleInterstitialController.swift */; }; - 53BFCD172CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD162CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift */; }; - 53BFCD182CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD162CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift */; }; + 53BFCD172CF9F12300A3287A /* SampleInterstitialRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD162CF9F12300A3287A /* SampleInterstitialRenderer.swift */; }; + 53BFCD182CF9F12300A3287A /* SampleInterstitialRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD162CF9F12300A3287A /* SampleInterstitialRenderer.swift */; }; 53ED2FD329798104007D13EE /* LogInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D70F6A24E546DD0048CC78 /* LogInfo.swift */; }; 53ED2FD429798104007D13EE /* PrebidOriginalAPINativeController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5397BD2D2937821D00ABDA22 /* PrebidOriginalAPINativeController.swift */; }; 53ED2FD529798104007D13EE /* AdapterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6EB3CC211336D300317ED9 /* AdapterViewController.swift */; }; @@ -405,10 +405,10 @@ 53A369042AB98F9700A03B3E /* PrebidOriginalAPIMultiformatInAppNativeController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidOriginalAPIMultiformatInAppNativeController.swift; sourceTree = ""; }; 53A369072AB996EF00A03B3E /* PrebidMultiformatConfigurationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidMultiformatConfigurationController.swift; sourceTree = ""; }; 53A651832AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidOriginalAPIMultiformatNativeStylesController.swift; sourceTree = ""; }; - 53BFCD022CF792FB00A3287A /* SampleCustomAdViewRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleCustomAdViewRenderer.swift; sourceTree = ""; }; + 53BFCD022CF792FB00A3287A /* SampleAdViewRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAdViewRenderer.swift; sourceTree = ""; }; 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAdView.swift; sourceTree = ""; }; 53BFCD122CF9C67400A3287A /* SampleInterstitialController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleInterstitialController.swift; sourceTree = ""; }; - 53BFCD162CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleCustomInterstitialRenderer.swift; sourceTree = ""; }; + 53BFCD162CF9F12300A3287A /* SampleInterstitialRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleInterstitialRenderer.swift; sourceTree = ""; }; 53ED304329798104007D13EE /* InternalTestApp-Skadn.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "InternalTestApp-Skadn.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 53ED305129798DBC007D13EE /* Info-Skadn.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Skadn.plist"; sourceTree = ""; }; 5B03D44524F5455F002F2B35 /* PBMGAMBannerEventHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PBMGAMBannerEventHandlerTests.swift; sourceTree = ""; }; @@ -747,9 +747,9 @@ isa = PBXGroup; children = ( 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */, - 53BFCD022CF792FB00A3287A /* SampleCustomAdViewRenderer.swift */, + 53BFCD022CF792FB00A3287A /* SampleAdViewRenderer.swift */, 53BFCD122CF9C67400A3287A /* SampleInterstitialController.swift */, - 53BFCD162CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift */, + 53BFCD162CF9F12300A3287A /* SampleInterstitialRenderer.swift */, 53514C8E2CFF92D000A480C0 /* SampleModalViewController.swift */, ); path = Renderers; @@ -1602,7 +1602,7 @@ 53ED2FE829798104007D13EE /* PrebidBannerController.swift in Sources */, 53ED2FE929798104007D13EE /* PrebidBannerConfigurationController.swift in Sources */, 53ED2FEA29798104007D13EE /* TestCase.swift in Sources */, - 53BFCD032CF792FB00A3287A /* SampleCustomAdViewRenderer.swift in Sources */, + 53BFCD032CF792FB00A3287A /* SampleAdViewRenderer.swift in Sources */, 53ED2FEB29798104007D13EE /* PrebidAdMobNativeViewController.swift in Sources */, 53ED2FEC29798104007D13EE /* PrebidInterstitialController.swift in Sources */, 53ED2FED29798104007D13EE /* PrebidOriginalAPIDisplayInterstitialController.swift in Sources */, @@ -1635,7 +1635,7 @@ 53ED300729798104007D13EE /* PrebidFeedTableViewController.swift in Sources */, 53ED300829798104007D13EE /* TestCasesViewController.swift in Sources */, 53ED300929798104007D13EE /* NativeAdViewBoxLinks.swift in Sources */, - 53BFCD172CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift in Sources */, + 53BFCD172CF9F12300A3287A /* SampleInterstitialRenderer.swift in Sources */, 53ED300A29798104007D13EE /* PrebidGAMRewardedController.swift in Sources */, 539F961529DEF2670061E7A5 /* PrebidOriginalAPIVideoInterstitialController.swift in Sources */, 53A369092AB996EF00A03B3E /* PrebidMultiformatConfigurationController.swift in Sources */, @@ -1703,7 +1703,7 @@ 3493022224740BEE004A6086 /* PrebidBannerController.swift in Sources */, 5BDB85DA2739794900A529F6 /* PrebidBannerConfigurationController.swift in Sources */, 5B3EEDE52101FB8800BAA0C4 /* TestCase.swift in Sources */, - 53BFCD042CF792FB00A3287A /* SampleCustomAdViewRenderer.swift in Sources */, + 53BFCD042CF792FB00A3287A /* SampleAdViewRenderer.swift in Sources */, 92C475122796FF8400C26E27 /* PrebidAdMobNativeViewController.swift in Sources */, 34FC0CF424ADD3A80045553E /* PrebidInterstitialController.swift in Sources */, 5397BD26293760F500ABDA22 /* PrebidOriginalAPIDisplayInterstitialController.swift in Sources */, @@ -1736,7 +1736,7 @@ ACAF055724D8384B0089DFB1 /* PrebidFeedTableViewController.swift in Sources */, 5B3EEDDF2101EA9200BAA0C4 /* TestCasesViewController.swift in Sources */, 92F9A5D227A15D04007B0B17 /* NativeAdViewBoxLinks.swift in Sources */, - 53BFCD182CF9F12300A3287A /* SampleCustomInterstitialRenderer.swift in Sources */, + 53BFCD182CF9F12300A3287A /* SampleInterstitialRenderer.swift in Sources */, 34FC0CF624ADD5640045553E /* PrebidGAMRewardedController.swift in Sources */, 539F961429DEF2670061E7A5 /* PrebidOriginalAPIVideoInterstitialController.swift in Sources */, 53A369082AB996EF00A03B3E /* PrebidMultiformatConfigurationController.swift in Sources */, diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererBannerController.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererBannerController.swift index efed8e37d..49c719fc7 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererBannerController.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererBannerController.swift @@ -43,7 +43,7 @@ class CustomRendererBannerController: private let reloadButton = ThreadCheckingButton() private let stopRefreshButton = ThreadCheckingButton() - private let sampleCustomRenderer = SampleCustomAdViewRenderer() + private let sampleCustomRenderer = SampleAdViewRenderer() let lastLoadedAdSizeLabel = UILabel() private let configIdLabel = UILabel() diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererInterstitialController.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererInterstitialController.swift index ca351d64b..c747ba09e 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererInterstitialController.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererInterstitialController.swift @@ -29,7 +29,7 @@ class CustomRendererInterstitialController: var adFormats: Set? private var interstitialController : InterstitialRenderingAdUnit? - private let sampleCustomRenderer = SampleCustomInterstitialRenderer() + private let sampleCustomRenderer = SampleInterstitialRenderer() private weak var adapterViewController: AdapterViewController? diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdView.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdView.swift index 17e6c907b..74a3bc98a 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdView.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdView.swift @@ -102,7 +102,7 @@ extension SampleAdView: WKNavigationDelegate { func webView( _ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, - decisionHandler: @escaping (WKNavigationActionPolicy) -> Void + decisionHandler: @MainActor @Sendable @escaping (WKNavigationActionPolicy) -> Void ) { guard let url = navigationAction.request.url, navigationAction.navigationType == .linkActivated else { diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomAdViewRenderer.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdViewRenderer.swift similarity index 90% rename from InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomAdViewRenderer.swift rename to InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdViewRenderer.swift index 61bb957fb..60601f71c 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomAdViewRenderer.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdViewRenderer.swift @@ -16,9 +16,9 @@ import UIKit import PrebidMobile -public class SampleCustomAdViewRenderer: NSObject, PrebidMobileAdViewPluginRenderer { +public class SampleAdViewRenderer: NSObject, PrebidMobileAdViewPluginRenderer { - public let name = "SampleCustomAdViewRenderer" + public let name = "SampleAdViewRenderer" public let version = "1.0.0" public var data: [AnyHashable: Any]? diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomInterstitialRenderer.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialRenderer.swift similarity index 91% rename from InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomInterstitialRenderer.swift rename to InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialRenderer.swift index 5b96b8a1b..1de6b9230 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleCustomInterstitialRenderer.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialRenderer.swift @@ -16,9 +16,9 @@ import UIKit import PrebidMobile -class SampleCustomInterstitialRenderer: PrebidMobileInterstitialPluginRenderer { +class SampleInterstitialRenderer: PrebidMobileInterstitialPluginRenderer { - var name = "SampleCustomInterstitialRenderer" + var name = "SampleInterstitialRenderer" var version = "1.0.0" var data: [AnyHashable : Any]? diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift index 32d117128..2db361741 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift @@ -15,11 +15,6 @@ import UIKit -// 1. Determine the purpose of registerEventDelegate and unregisterEventDelegate -// 2. Add cases to InternalTestApp with all delegates calling -// 3. Ask if to add to Demo Apps -// 4. Unit tests. - /// A protocol for the plugin renderer, defining the basic interface that any renderer should implement. /// This protocol provides the ability to retrieve plugin details, support rendering formats, and manage event delegates. @objc @@ -37,8 +32,6 @@ public protocol PrebidMobilePluginRenderer: AnyObject { /// Returns true only if the given ad unit could be renderer by the plugin. @objc func isSupportRendering(for format: AdFormat?) -> Bool - // TODO: Determine the purpose - /// Register a listener related to a specific ad unit config fingerprint in order to dispatch specific ad events. @objc optional func registerEventDelegate( pluginEventDelegate: PluginEventDelegate, From 8e6097caf1a3f199e2cf7358da7533120c837ad2 Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Wed, 4 Dec 2024 22:25:56 +0200 Subject: [PATCH 10/18] feat: minor corrections --- .../SampleRenderers/SampleAdViewRenderer.m | 2 +- .../SampleInterstitialRenderer.m | 2 +- ...ayBannerPluginRendererViewController.swift | 3 +- .../SampleInterstitialController.swift | 2 +- .../SampleCustomAdViewRenderer.swift | 77 ----------------- .../SampleCustomRenderer.swift | 83 ------------------- .../DisplayViewInteractionDelegate.swift | 2 +- 7 files changed, 6 insertions(+), 165 deletions(-) delete mode 100644 InternalTestApp/PrebidMobileDemoRendering/SampleCustomAdViewRenderer.swift delete mode 100644 InternalTestApp/PrebidMobileDemoRendering/SampleCustomRenderer.swift diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.m index f4e67182e..ccb88550b 100644 --- a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.m +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.m @@ -31,7 +31,7 @@ - (instancetype)init { } - (BOOL)isSupportRenderingFor:(AdFormat *)format { - return YES; + return [@[AdFormat.banner, AdFormat.video] containsObject:format]; } - (UIView * _Nullable)createAdViewWith:(CGRect)frame diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.m index e8a2f2716..1b2dfc402 100644 --- a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.m +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.m @@ -32,7 +32,7 @@ - (instancetype)init { } - (BOOL)isSupportRenderingFor:(AdFormat *)format { - return YES; + return [@[AdFormat.banner, AdFormat.video] containsObject:format]; } - (id)createInterstitialControllerWithBid:(Bid *)bid diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift index 1020b526a..e2167dc8f 100644 --- a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift @@ -39,7 +39,8 @@ class InAppDisplayBannerPluginRendererViewController: BannerBaseViewController, // 3. Create a BannerView prebidBannerView = BannerView( frame: CGRect(origin: .zero, size: adSize), - configID: storedImpDisplayBanner, adSize: adSize + configID: storedImpDisplayBanner, + adSize: adSize ) // 4. Configure the BannerView diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialController.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialController.swift index 1713dc68d..f591900ab 100644 --- a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialController.swift +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialController.swift @@ -1,4 +1,4 @@ -/*   Copyright 2018-2021 Prebid.org, Inc. +/*   Copyright 2018-2024 Prebid.org, Inc.  Licensed under the Apache License, Version 2.0 (the "License");  you may not use this file except in compliance with the License. diff --git a/InternalTestApp/PrebidMobileDemoRendering/SampleCustomAdViewRenderer.swift b/InternalTestApp/PrebidMobileDemoRendering/SampleCustomAdViewRenderer.swift deleted file mode 100644 index 5651447b8..000000000 --- a/InternalTestApp/PrebidMobileDemoRendering/SampleCustomAdViewRenderer.swift +++ /dev/null @@ -1,77 +0,0 @@ -/*   Copyright 2018-2021 Prebid.org, Inc. - - 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 UIKit -import PrebidMobile - -public class SampleCustomBannerViewRenderer: NSObject, PrebidMobilePluginRenderer { - - public let name = "SampleCustomBannerViewRenderer" - public let version = "1.0.0" - public var data: [AnyHashable: Any]? - - public func isSupportRendering(for format: AdFormat?) -> Bool { - AdFormat.allCases.contains(where: { $0 == format }) - } - - private weak var loadingDelegate: DisplayViewLoadingDelegate? - private weak var interactionDelegate: DisplayViewInteractionDelegate? - private weak var currentAdView: UIView? - - public func createBannerAdView( - with frame: CGRect, - bid: Bid, - adConfiguration: AdUnitConfig, - connection: PrebidServerConnectionProtocol, - loadingDelegate: DisplayViewLoadingDelegate?, - interactionDelegate: DisplayViewInteractionDelegate? - ) -> UIView { - - self.interactionDelegate = interactionDelegate - self.loadingDelegate = loadingDelegate - - let bannerView = UIView(frame: frame) - - let label = UILabel() - label.text = "Prebid SDK - Custom Renderer" - label.textAlignment = .center - label.textColor = .black - label.backgroundColor = .yellow - label.translatesAutoresizingMaskIntoConstraints = false - - bannerView.addSubview(label) - - NSLayoutConstraint.activate([ - label.centerXAnchor.constraint(equalTo: bannerView.centerXAnchor), - label.centerYAnchor.constraint(equalTo: bannerView.centerYAnchor), - label.widthAnchor.constraint(equalTo: bannerView.widthAnchor), - label.heightAnchor.constraint(equalTo: bannerView.heightAnchor) - ]) - - currentAdView = bannerView - - loadingDelegate?.displayViewDidLoadAd(bannerView) - - return bannerView - } - - public func createInterstitialController( - bid: Bid, - adConfiguration: AdUnitConfig, - connection: PrebidServerConnectionProtocol, - adViewManagerDelegate adViewDelegate: InterstitialController?, - videoControlsConfig: VideoControlsConfiguration? - ) {} -} diff --git a/InternalTestApp/PrebidMobileDemoRendering/SampleCustomRenderer.swift b/InternalTestApp/PrebidMobileDemoRendering/SampleCustomRenderer.swift deleted file mode 100644 index 155d14b3c..000000000 --- a/InternalTestApp/PrebidMobileDemoRendering/SampleCustomRenderer.swift +++ /dev/null @@ -1,83 +0,0 @@ -/*   Copyright 2018-2021 Prebid.org, Inc. - - 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 UIKit -import PrebidMobile - -public class SampleCustomAdViewRenderer: NSObject, PrebidMobilePluginRenderer { - - public let name = "SampleCustomRenderer" - public let version = "1.0.0" - public var data: [AnyHashable: Any]? - - public func isSupportRendering(for format: AdFormat?) -> Bool { - AdFormat.allCases.contains(where: { $0 == format }) - } - - private weak var loadingDelegate: DisplayViewLoadingDelegate? - private weak var interactionDelegate: DisplayViewInteractionDelegate? - private weak var currentAdView: UIView? - - public func createBannerAdView( - with frame: CGRect, - bid: Bid, - adConfiguration: AdUnitConfig, - connection: PrebidServerConnectionProtocol, - loadingDelegate: DisplayViewLoadingDelegate?, - interactionDelegate: DisplayViewInteractionDelegate? - ) -> UIView { - - self.interactionDelegate = interactionDelegate - self.loadingDelegate = loadingDelegate - - let bannerView = UIView(frame: frame) - - let label = UILabel() - label.text = "Prebid SDK - Custom Renderer" - label.textAlignment = .center - label.textColor = .black - label.backgroundColor = .yellow - label.translatesAutoresizingMaskIntoConstraints = false - - bannerView.addSubview(label) - - NSLayoutConstraint.activate([ - label.centerXAnchor.constraint(equalTo: bannerView.centerXAnchor), - label.centerYAnchor.constraint(equalTo: bannerView.centerYAnchor), - label.widthAnchor.constraint(equalTo: bannerView.widthAnchor), - label.heightAnchor.constraint(equalTo: bannerView.heightAnchor) - ]) - - currentAdView = bannerView - - loadingDelegate?.displayViewDidLoadAd(bannerView) - - return bannerView - } - - public func createInterstitialController( - bid: Bid, - adConfiguration: AdUnitConfig, - connection: PrebidServerConnectionProtocol, - adViewManagerDelegate adViewDelegate: InterstitialController?, - videoControlsConfig: VideoControlsConfiguration? - ) {} - - public func setupBid( - _ bid: Bid, - adConfiguration: AdUnitConfig, - connection: PrebidServerConnectionProtocol - ) {} -} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewInteractionDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewInteractionDelegate.swift index 7fc3f3d48..17d82e7b1 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewInteractionDelegate.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewInteractionDelegate.swift @@ -37,7 +37,7 @@ public protocol DisplayViewInteractionDelegate: NSObjectProtocol { /// - displayView: The `UIView` instance associated with the modal presentation. @objc func willPresentModal(from displayView: UIView) - /// Notifies the delegate that a modal view has been dismissed and control has returned to the app. + /// Notifies the delegate that a modal view has been dismissed. /// /// - Parameters: /// - displayView: The `UIView` instance associated with the dismissed modal. From d6dc040171e0aa0dbb0395058b1395ded196cda4 Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Thu, 5 Dec 2024 14:39:23 +0200 Subject: [PATCH 11/18] feat: unregister plugin renderer --- .../PrebidDemo.xcodeproj/project.pbxproj | 8 +++---- ...isplayBannerPluginRendererViewController.m | 10 +++++++-- ...InterstitialPluginRendererViewController.m | 10 +++++++-- ...ayBannerPluginRendererViewController.swift | 21 ++++++++++++------- ...stitialPluginRendererViewController.swift} | 19 ++++++++++------- .../IntegrationCaseManager.swift | 2 +- 6 files changed, 45 insertions(+), 25 deletions(-) rename Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/{InAppDisplayInterstitialPluginInterstitialViewController.swift => InAppDisplayInterstitialPluginRendererViewController.swift} (79%) diff --git a/Example/PrebidDemo/PrebidDemo.xcodeproj/project.pbxproj b/Example/PrebidDemo/PrebidDemo.xcodeproj/project.pbxproj index 2767d9f39..0eca65127 100644 --- a/Example/PrebidDemo/PrebidDemo.xcodeproj/project.pbxproj +++ b/Example/PrebidDemo/PrebidDemo.xcodeproj/project.pbxproj @@ -72,7 +72,7 @@ 53514C9F2CFF988E00A480C0 /* SampleInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C9B2CFF988E00A480C0 /* SampleInterstitialController.swift */; }; 53514CA02CFF988E00A480C0 /* SampleAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C992CFF988E00A480C0 /* SampleAdViewRenderer.swift */; }; 53514CA12CFF988E00A480C0 /* SampleInterstitialRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C9A2CFF988E00A480C0 /* SampleInterstitialRenderer.swift */; }; - 53514CA32CFF9DD000A480C0 /* InAppDisplayInterstitialPluginInterstitialViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CA22CFF9DD000A480C0 /* InAppDisplayInterstitialPluginInterstitialViewController.swift */; }; + 53514CA32CFF9DD000A480C0 /* InAppDisplayInterstitialPluginRendererViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CA22CFF9DD000A480C0 /* InAppDisplayInterstitialPluginRendererViewController.swift */; }; 53514CA72CFFA52A00A480C0 /* SampleAdView.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CA62CFFA52A00A480C0 /* SampleAdView.m */; }; 53514CAA2CFFA62700A480C0 /* SampleAdViewRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CA92CFFA62700A480C0 /* SampleAdViewRenderer.m */; }; 53514CAD2CFFA99200A480C0 /* InAppDisplayBannerPluginRendererViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CAC2CFFA99200A480C0 /* InAppDisplayBannerPluginRendererViewController.m */; }; @@ -299,7 +299,7 @@ 53514C992CFF988E00A480C0 /* SampleAdViewRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAdViewRenderer.swift; sourceTree = ""; }; 53514C9A2CFF988E00A480C0 /* SampleInterstitialRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleInterstitialRenderer.swift; sourceTree = ""; }; 53514C9B2CFF988E00A480C0 /* SampleInterstitialController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleInterstitialController.swift; sourceTree = ""; }; - 53514CA22CFF9DD000A480C0 /* InAppDisplayInterstitialPluginInterstitialViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppDisplayInterstitialPluginInterstitialViewController.swift; sourceTree = ""; }; + 53514CA22CFF9DD000A480C0 /* InAppDisplayInterstitialPluginRendererViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppDisplayInterstitialPluginRendererViewController.swift; sourceTree = ""; }; 53514CA52CFFA52A00A480C0 /* SampleAdView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleAdView.h; sourceTree = ""; }; 53514CA62CFFA52A00A480C0 /* SampleAdView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleAdView.m; sourceTree = ""; }; 53514CA82CFFA62700A480C0 /* SampleAdViewRenderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleAdViewRenderer.h; sourceTree = ""; }; @@ -586,7 +586,7 @@ 53072B7629226CFE00228462 /* InAppDisplayBannerViewController.swift */, 53514C952CFF97DB00A480C0 /* InAppDisplayBannerPluginRendererViewController.swift */, 53072B7A292270EE00228462 /* InAppDisplayInterstitialViewController.swift */, - 53514CA22CFF9DD000A480C0 /* InAppDisplayInterstitialPluginInterstitialViewController.swift */, + 53514CA22CFF9DD000A480C0 /* InAppDisplayInterstitialPluginRendererViewController.swift */, 5344E69E2922796000A1F582 /* InAppNativeViewController.swift */, 53072B7829226EF400228462 /* InAppVideoBannerViewController.swift */, 53072B802922753D00228462 /* InAppVideoInterstitialLandscapeViewController.swift */, @@ -1576,7 +1576,7 @@ 53B03D8C291A6562000117E1 /* ExamplesViewController.swift in Sources */, 5344E6C32922AAE500A1F582 /* MAXVideoRewardedViewController.swift in Sources */, 53072B6929217D1800228462 /* GAMOriginalAPIVideoInstreamViewController.swift in Sources */, - 53514CA32CFF9DD000A480C0 /* InAppDisplayInterstitialPluginInterstitialViewController.swift in Sources */, + 53514CA32CFF9DD000A480C0 /* InAppDisplayInterstitialPluginRendererViewController.swift in Sources */, 5344E6A92922815000A1F582 /* GAMVideoRewardedViewController.swift in Sources */, 534C61572CB7F4780026119A /* AdMobDisplayRewardedViewController.swift in Sources */, 53072B7B292270EE00228462 /* InAppDisplayInterstitialViewController.swift in Sources */, diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.m index efb37e121..4a75e319a 100644 --- a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.m +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.m @@ -23,6 +23,7 @@ @interface InAppDisplayBannerPluginRendererViewController () // Prebid @property (nonatomic) BannerView * prebidBannerView; +@property (nonatomic, strong) SampleAdViewRenderer * samplePluginRenderer; @end @@ -34,12 +35,17 @@ - (void)loadView { [self createAd]; } +- (void)dealloc { + // Unregister plugin when you no longer needed + [Prebid unregisterPluginRenderer:self.samplePluginRenderer]; +} + - (void)createAd { // 1. Create a plugin renderer - SampleAdViewRenderer * samplePluginRenderer = [SampleAdViewRenderer new]; + self.samplePluginRenderer = [SampleAdViewRenderer new]; // 2. Register the plugin renderer - [Prebid registerPluginRenderer:samplePluginRenderer]; + [Prebid registerPluginRenderer:self.samplePluginRenderer]; // 3. Create a BannerView self.prebidBannerView = [[BannerView alloc] initWithFrame:CGRectMake(0, 0, self.adSize.width, self.adSize.height) diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.m index 755115bc8..ec287aef3 100644 --- a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.m +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.m @@ -23,6 +23,7 @@ @interface InAppDisplayInterstitialPluginRendererViewController () // Prebid @property (nonatomic) InterstitialRenderingAdUnit * renderingInterstitial; +@property (nonatomic, strong) SampleInterstitialRenderer * samplePluginRenderer; @end @@ -34,12 +35,17 @@ - (void)loadView { [self createAd]; } +- (void)dealloc { + // Unregister plugin when you no longer needed + [Prebid unregisterPluginRenderer:self.samplePluginRenderer]; +} + - (void)createAd { // 1. Create a plugin renderer - SampleInterstitialRenderer * samplePluginRenderer = [SampleInterstitialRenderer new]; + self.samplePluginRenderer = [SampleInterstitialRenderer new]; // 2. Register the plugin renderer - [Prebid registerPluginRenderer:samplePluginRenderer]; + [Prebid registerPluginRenderer:self.samplePluginRenderer]; // 3. Create a InterstitialRenderingAdUnit self.renderingInterstitial = [[InterstitialRenderingAdUnit alloc] initWithConfigID:storedImpDisplayInterstitialPluginRendererInApp]; diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift index e2167dc8f..ab0a6953c 100644 --- a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift @@ -18,10 +18,13 @@ import PrebidMobile fileprivate let storedImpDisplayBanner = "prebid-demo-display-banner-320-50-custom-ad-view-renderer" -class InAppDisplayBannerPluginRendererViewController: BannerBaseViewController, BannerViewDelegate { +class InAppDisplayBannerPluginRendererViewController: + BannerBaseViewController, + BannerViewDelegate { // Prebid private var prebidBannerView: BannerView! + private let samplePluginRenderer = SampleAdViewRenderer() override func loadView() { super.loadView() @@ -29,21 +32,23 @@ class InAppDisplayBannerPluginRendererViewController: BannerBaseViewController, createAd() } + deinit { + // Unregister plugin when you no longer needed + Prebid.unregisterPluginRenderer(samplePluginRenderer) + } + func createAd() { - // 1. Create a plugin renderer - let samplePluginRenderer = SampleAdViewRenderer() - - // 2. Register the plugin renderer + // 1. Register the plugin renderer Prebid.registerPluginRenderer(samplePluginRenderer) - // 3. Create a BannerView + // 2. Create a BannerView prebidBannerView = BannerView( frame: CGRect(origin: .zero, size: adSize), configID: storedImpDisplayBanner, adSize: adSize ) - // 4. Configure the BannerView + // 3. Configure the BannerView prebidBannerView.delegate = self prebidBannerView.adFormat = .banner prebidBannerView.videoParameters.placement = .InBanner @@ -51,7 +56,7 @@ class InAppDisplayBannerPluginRendererViewController: BannerBaseViewController, // Add Prebid banner view to the app UI bannerView.addSubview(prebidBannerView) - // 5. Load the banner ad + // 4. Load the banner ad prebidBannerView.loadAd() } diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayInterstitialPluginInterstitialViewController.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayInterstitialPluginRendererViewController.swift similarity index 79% rename from Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayInterstitialPluginInterstitialViewController.swift rename to Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayInterstitialPluginRendererViewController.swift index f6fc4bbff..bbec35413 100644 --- a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayInterstitialPluginInterstitialViewController.swift +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayInterstitialPluginRendererViewController.swift @@ -18,12 +18,13 @@ import PrebidMobile fileprivate let storedImpDisplayInterstitial = "prebid-demo-display-interstitial-320-480-custom-interstitial-renderer" -class InAppDisplayInterstitialPluginInterstitialViewController: +class InAppDisplayInterstitialPluginRendererViewController: UIViewController, InterstitialAdUnitDelegate { // Prebid private var renderingInterstitial: InterstitialRenderingAdUnit! + private let samplePluginRenderer = SampleInterstitialRenderer() override func loadView() { super.loadView() @@ -31,21 +32,23 @@ class InAppDisplayInterstitialPluginInterstitialViewController: createAd() } + deinit { + // Unregister plugin when you no longer needed + Prebid.unregisterPluginRenderer(samplePluginRenderer) + } + func createAd() { - // 1. Create a plugin renderer - let samplePluginRenderer = SampleInterstitialRenderer() - - // 2. Register the plugin renderer + // 1. Register the plugin renderer Prebid.registerPluginRenderer(samplePluginRenderer) - // 3. Create a InterstitialRenderingAdUnit + // 2. Create a InterstitialRenderingAdUnit renderingInterstitial = InterstitialRenderingAdUnit(configID: storedImpDisplayInterstitial) - // 4. Configure the InterstitialRenderingAdUnit + // 3. Configure the InterstitialRenderingAdUnit renderingInterstitial.adFormats = [.banner] renderingInterstitial.delegate = self - // 5. Load the interstitial ad + // 4. Load the interstitial ad renderingInterstitial.loadAd() } diff --git a/Example/PrebidDemo/PrebidDemoSwift/IntegrationCase/IntegrationCaseManager.swift b/Example/PrebidDemo/PrebidDemoSwift/IntegrationCase/IntegrationCaseManager.swift index e7f5311dc..db99edeb8 100644 --- a/Example/PrebidDemo/PrebidDemoSwift/IntegrationCase/IntegrationCaseManager.swift +++ b/Example/PrebidDemo/PrebidDemoSwift/IntegrationCase/IntegrationCaseManager.swift @@ -174,7 +174,7 @@ struct IntegrationCaseManager { integrationKind: .inApp, adFormat: .displayInterstitial, configurationClosure: { - InAppDisplayInterstitialPluginInterstitialViewController() + InAppDisplayInterstitialPluginRendererViewController() } ), From 07f55b8e2547a1c6fc61cf2ad999f4ed1a592d60 Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Tue, 10 Dec 2024 11:42:29 +0200 Subject: [PATCH 12/18] fix: resolve issues after rebasing --- .../Sources/PrebidAdMobRewardedAdapter.swift | 20 ++-- .../InternalTestApp.xcodeproj/project.pbxproj | 105 +++++++++--------- .../GAM/AdLoading/PBMInterstitialAdLoader.m | 4 +- .../GAM/BaseInterstitialAdUnit.swift | 26 +---- .../GAM/BaseInterstitialAdUnitProtocol.swift | 2 +- .../Integrations/GAM/BaseRewardedAdUnit.swift | 5 +- .../GAM/InterstitialRenderingAdUnit.swift | 2 +- .../Integrations/GAM/RewardedAdUnit.swift | 36 ++++-- .../Integrations/GAM/RewardedConfig.swift | 2 +- .../DisplayView/PBMDisplayView.m | 1 + .../InterstitialController.swift | 7 +- ...stitialControllerInteractionDelegate.swift | 10 ++ 12 files changed, 115 insertions(+), 105 deletions(-) diff --git a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobRewardedAdapter.swift b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobRewardedAdapter.swift index 759310bcc..d7f1bf4df 100644 --- a/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobRewardedAdapter.swift +++ b/EventHandlers/PrebidMobileAdMobAdapters/Sources/PrebidAdMobRewardedAdapter.swift @@ -113,7 +113,7 @@ public class PrebidAdMobRewardedAdapter: // MARK: - InterstitialControllerLoadingDelegate - public func interstitialControllerDidLoadAd(_ interstitialController: InterstitialController) { + public func interstitialControllerDidLoadAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { adAvailable = true if let handler = completionHandler { @@ -121,46 +121,46 @@ public class PrebidAdMobRewardedAdapter: } } - public func interstitialController(_ interstitialController: InterstitialController, didFailWithError error: Error) { + public func interstitialController(_ interstitialController: PrebidMobileInterstitialControllerProtocol, didFailWithError error: Error) { adAvailable = false } // MARK: - InterstitialControllerInteractionDelegate - public func trackImpression(forInterstitialController: InterstitialController) { + public func trackImpression(forInterstitialController: PrebidMobileInterstitialControllerProtocol) { delegate?.reportImpression() } - public func trackUserReward(_ interstitialController: InterstitialController, _ reward: PrebidReward) { + public func trackUserReward(_ interstitialController: PrebidMobileInterstitialControllerProtocol, _ reward: PrebidReward) { delegate?.didRewardUser() } - public func interstitialControllerDidClickAd(_ interstitialController: InterstitialController) { + public func interstitialControllerDidClickAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { delegate?.reportClick() } - public func interstitialControllerDidCloseAd(_ interstitialController: InterstitialController) { + public func interstitialControllerDidCloseAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { adAvailable = false delegate?.willDismissFullScreenView() delegate?.didDismissFullScreenView() } - public func interstitialControllerDidDisplay(_ interstitialController: InterstitialController) { + public func interstitialControllerDidDisplay(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { delegate?.willPresentFullScreenView() delegate?.didStartVideo() delegate?.didEndVideo() } - public func interstitialControllerDidComplete(_ interstitialController: InterstitialController) { + public func interstitialControllerDidComplete(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { adAvailable = false rootViewController = nil delegate?.didRewardUser() } - public func viewControllerForModalPresentation(fromInterstitialController: InterstitialController) -> UIViewController? { + public func viewControllerForModalPresentation(fromInterstitialController: PrebidMobileInterstitialControllerProtocol) -> UIViewController? { rootViewController } - public func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialController) {} + public func interstitialControllerDidLeaveApp(_ interstitialController: PrebidMobileInterstitialControllerProtocol) {} } diff --git a/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj b/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj index 084c496a5..2588fe3f5 100644 --- a/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj +++ b/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj @@ -25,14 +25,22 @@ 34E5698A237DB96900B47B01 /* UtilitiesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E56989237DB96900B47B01 /* UtilitiesViewController.swift */; }; 34FC0CF424ADD3A80045553E /* PrebidInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34FC0CF324ADD3A80045553E /* PrebidInterstitialController.swift */; }; 34FC0CF624ADD5640045553E /* PrebidGAMRewardedController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34FC0CF524ADD5640045553E /* PrebidGAMRewardedController.swift */; }; - 3C28C9D82C35713B00D0A7DB /* CustomRendererInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C28C9D72C35713B00D0A7DB /* CustomRendererInterstitialController.swift */; }; - 3C28C9D92C35713B00D0A7DB /* CustomRendererInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C28C9D72C35713B00D0A7DB /* CustomRendererInterstitialController.swift */; }; - 3CC4A3E92C11F96800B97128 /* CustomRendererBannerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CC4A3E82C11F96800B97128 /* CustomRendererBannerController.swift */; }; - 3CC4A3EA2C11F96800B97128 /* CustomRendererBannerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CC4A3E82C11F96800B97128 /* CustomRendererBannerController.swift */; }; 457FD34BA45C3840CC31A8F5 /* Pods_InternalTestApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C11D97034E668BBFDD0DDCA /* Pods_InternalTestApp.framework */; }; 530E722C292FACB20025B44D /* UIImageView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 530E722B292FACB20025B44D /* UIImageView+Extensions.swift */; }; - 53514C8F2CFF92D000A480C0 /* SampleModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C8E2CFF92D000A480C0 /* SampleModalViewController.swift */; }; - 53514C902CFF92D000A480C0 /* SampleModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C8E2CFF92D000A480C0 /* SampleModalViewController.swift */; }; + 53514CE12D08416B00A480C0 /* CustomRendererInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDF2D08416B00A480C0 /* CustomRendererInterstitialController.swift */; }; + 53514CE22D08416B00A480C0 /* SampleAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CD92D08416B00A480C0 /* SampleAdViewRenderer.swift */; }; + 53514CE32D08416B00A480C0 /* SampleModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDC2D08416B00A480C0 /* SampleModalViewController.swift */; }; + 53514CE42D08416B00A480C0 /* SampleInterstitialRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDB2D08416B00A480C0 /* SampleInterstitialRenderer.swift */; }; + 53514CE52D08416B00A480C0 /* SampleInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDA2D08416B00A480C0 /* SampleInterstitialController.swift */; }; + 53514CE62D08416B00A480C0 /* SampleAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CD82D08416B00A480C0 /* SampleAdView.swift */; }; + 53514CE72D08416B00A480C0 /* CustomRendererBannerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDE2D08416B00A480C0 /* CustomRendererBannerController.swift */; }; + 53514CE82D08416B00A480C0 /* CustomRendererInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDF2D08416B00A480C0 /* CustomRendererInterstitialController.swift */; }; + 53514CE92D08416B00A480C0 /* SampleAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CD92D08416B00A480C0 /* SampleAdViewRenderer.swift */; }; + 53514CEA2D08416B00A480C0 /* SampleModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDC2D08416B00A480C0 /* SampleModalViewController.swift */; }; + 53514CEB2D08416B00A480C0 /* SampleInterstitialRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDB2D08416B00A480C0 /* SampleInterstitialRenderer.swift */; }; + 53514CEC2D08416B00A480C0 /* SampleInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDA2D08416B00A480C0 /* SampleInterstitialController.swift */; }; + 53514CED2D08416B00A480C0 /* SampleAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CD82D08416B00A480C0 /* SampleAdView.swift */; }; + 53514CEE2D08416B00A480C0 /* CustomRendererBannerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDE2D08416B00A480C0 /* CustomRendererBannerController.swift */; }; 5397BD142936185400ABDA22 /* PrebidOriginalAPIDisplayBannerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5397BD132936185400ABDA22 /* PrebidOriginalAPIDisplayBannerController.swift */; }; 5397BD26293760F500ABDA22 /* PrebidOriginalAPIDisplayInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5397BD25293760F500ABDA22 /* PrebidOriginalAPIDisplayInterstitialController.swift */; }; 5397BD2A29376C9700ABDA22 /* PrebidOriginalAPIVideoRewardedController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5397BD2929376C9700ABDA22 /* PrebidOriginalAPIVideoRewardedController.swift */; }; @@ -53,14 +61,6 @@ 53A369092AB996EF00A03B3E /* PrebidMultiformatConfigurationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A369072AB996EF00A03B3E /* PrebidMultiformatConfigurationController.swift */; }; 53A651842AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A651832AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift */; }; 53A651852AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A651832AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift */; }; - 53BFCD032CF792FB00A3287A /* SampleAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD022CF792FB00A3287A /* SampleAdViewRenderer.swift */; }; - 53BFCD042CF792FB00A3287A /* SampleAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD022CF792FB00A3287A /* SampleAdViewRenderer.swift */; }; - 53BFCD0C2CF8F56300A3287A /* SampleAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */; }; - 53BFCD0D2CF8F56300A3287A /* SampleAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */; }; - 53BFCD132CF9C67400A3287A /* SampleInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD122CF9C67400A3287A /* SampleInterstitialController.swift */; }; - 53BFCD142CF9C67400A3287A /* SampleInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD122CF9C67400A3287A /* SampleInterstitialController.swift */; }; - 53BFCD172CF9F12300A3287A /* SampleInterstitialRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD162CF9F12300A3287A /* SampleInterstitialRenderer.swift */; }; - 53BFCD182CF9F12300A3287A /* SampleInterstitialRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD162CF9F12300A3287A /* SampleInterstitialRenderer.swift */; }; 53ED2FD329798104007D13EE /* LogInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D70F6A24E546DD0048CC78 /* LogInfo.swift */; }; 53ED2FD429798104007D13EE /* PrebidOriginalAPINativeController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5397BD2D2937821D00ABDA22 /* PrebidOriginalAPINativeController.swift */; }; 53ED2FD529798104007D13EE /* AdapterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6EB3CC211336D300317ED9 /* AdapterViewController.swift */; }; @@ -388,10 +388,14 @@ 34FC0CF524ADD5640045553E /* PrebidGAMRewardedController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidGAMRewardedController.swift; sourceTree = ""; }; 35F94D131F93F85D00CF46DB /* InternalTestAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InternalTestAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 35F94D171F93F85D00CF46DB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 3C28C9D72C35713B00D0A7DB /* CustomRendererInterstitialController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomRendererInterstitialController.swift; sourceTree = ""; }; - 3CC4A3E82C11F96800B97128 /* CustomRendererBannerController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomRendererBannerController.swift; sourceTree = ""; }; 530E722B292FACB20025B44D /* UIImageView+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageView+Extensions.swift"; sourceTree = ""; }; - 53514C8E2CFF92D000A480C0 /* SampleModalViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleModalViewController.swift; sourceTree = ""; }; + 53514CD82D08416B00A480C0 /* SampleAdView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAdView.swift; sourceTree = ""; }; + 53514CD92D08416B00A480C0 /* SampleAdViewRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAdViewRenderer.swift; sourceTree = ""; }; + 53514CDA2D08416B00A480C0 /* SampleInterstitialController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleInterstitialController.swift; sourceTree = ""; }; + 53514CDB2D08416B00A480C0 /* SampleInterstitialRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleInterstitialRenderer.swift; sourceTree = ""; }; + 53514CDC2D08416B00A480C0 /* SampleModalViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleModalViewController.swift; sourceTree = ""; }; + 53514CDE2D08416B00A480C0 /* CustomRendererBannerController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomRendererBannerController.swift; sourceTree = ""; }; + 53514CDF2D08416B00A480C0 /* CustomRendererInterstitialController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomRendererInterstitialController.swift; sourceTree = ""; }; 5397BD132936185400ABDA22 /* PrebidOriginalAPIDisplayBannerController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidOriginalAPIDisplayBannerController.swift; sourceTree = ""; }; 5397BD25293760F500ABDA22 /* PrebidOriginalAPIDisplayInterstitialController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidOriginalAPIDisplayInterstitialController.swift; sourceTree = ""; }; 5397BD2929376C9700ABDA22 /* PrebidOriginalAPIVideoRewardedController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidOriginalAPIVideoRewardedController.swift; sourceTree = ""; }; @@ -405,10 +409,6 @@ 53A369042AB98F9700A03B3E /* PrebidOriginalAPIMultiformatInAppNativeController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidOriginalAPIMultiformatInAppNativeController.swift; sourceTree = ""; }; 53A369072AB996EF00A03B3E /* PrebidMultiformatConfigurationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidMultiformatConfigurationController.swift; sourceTree = ""; }; 53A651832AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidOriginalAPIMultiformatNativeStylesController.swift; sourceTree = ""; }; - 53BFCD022CF792FB00A3287A /* SampleAdViewRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAdViewRenderer.swift; sourceTree = ""; }; - 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAdView.swift; sourceTree = ""; }; - 53BFCD122CF9C67400A3287A /* SampleInterstitialController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleInterstitialController.swift; sourceTree = ""; }; - 53BFCD162CF9F12300A3287A /* SampleInterstitialRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleInterstitialRenderer.swift; sourceTree = ""; }; 53ED304329798104007D13EE /* InternalTestApp-Skadn.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "InternalTestApp-Skadn.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 53ED305129798DBC007D13EE /* Info-Skadn.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Skadn.plist"; sourceTree = ""; }; 5B03D44524F5455F002F2B35 /* PBMGAMBannerEventHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PBMGAMBannerEventHandlerTests.swift; sourceTree = ""; }; @@ -656,7 +656,6 @@ isa = PBXGroup; children = ( 92E92500276B2986002B57F3 /* AdMob */, - 3CC4A3E72C11F93A00B97128 /* CustomRenderer */, 3493021A2473F2FB004A6086 /* GAM */, 9289873D28003BFE0062BFAA /* MAX */, 3461835425A6020500783A2C /* NativeAdViewBox.swift */, @@ -684,7 +683,7 @@ 3493022024740BD8004A6086 /* OpenX */ = { isa = PBXGroup; children = ( - 3CC4A3E72C11F93A00B97128 /* CustomRenderer */, + 53514CE02D08416B00A480C0 /* CustomRenderer */, 3493022124740BEE004A6086 /* PrebidBannerController.swift */, 34FC0CF324ADD3A80045553E /* PrebidInterstitialController.swift */, 34BA95FF249CC118006AE372 /* PrebidRewardedController.swift */, @@ -714,12 +713,24 @@ path = PrebidMobileDemoRenderingUITests; sourceTree = ""; }; - 3CC4A3E72C11F93A00B97128 /* CustomRenderer */ = { + 53514CDD2D08416B00A480C0 /* Renderers */ = { isa = PBXGroup; children = ( - 53BFCD152CF9C68000A3287A /* Renderers */, - 3CC4A3E82C11F96800B97128 /* CustomRendererBannerController.swift */, - 3C28C9D72C35713B00D0A7DB /* CustomRendererInterstitialController.swift */, + 53514CD82D08416B00A480C0 /* SampleAdView.swift */, + 53514CD92D08416B00A480C0 /* SampleAdViewRenderer.swift */, + 53514CDA2D08416B00A480C0 /* SampleInterstitialController.swift */, + 53514CDB2D08416B00A480C0 /* SampleInterstitialRenderer.swift */, + 53514CDC2D08416B00A480C0 /* SampleModalViewController.swift */, + ); + path = Renderers; + sourceTree = ""; + }; + 53514CE02D08416B00A480C0 /* CustomRenderer */ = { + isa = PBXGroup; + children = ( + 53514CDD2D08416B00A480C0 /* Renderers */, + 53514CDE2D08416B00A480C0 /* CustomRendererBannerController.swift */, + 53514CDF2D08416B00A480C0 /* CustomRendererInterstitialController.swift */, ); path = CustomRenderer; sourceTree = ""; @@ -743,18 +754,6 @@ path = OriginalAPI; sourceTree = ""; }; - 53BFCD152CF9C68000A3287A /* Renderers */ = { - isa = PBXGroup; - children = ( - 53BFCD0B2CF8F56300A3287A /* SampleAdView.swift */, - 53BFCD022CF792FB00A3287A /* SampleAdViewRenderer.swift */, - 53BFCD122CF9C67400A3287A /* SampleInterstitialController.swift */, - 53BFCD162CF9F12300A3287A /* SampleInterstitialRenderer.swift */, - 53514C8E2CFF92D000A480C0 /* SampleModalViewController.swift */, - ); - path = Renderers; - sourceTree = ""; - }; 5B1BDB782100D59000B46B43 /* Resources */ = { isa = PBXGroup; children = ( @@ -1581,11 +1580,9 @@ 53A651852AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift in Sources */, 53ED2FD729798104007D13EE /* UtilitiesViewController.swift in Sources */, 53ED2FD829798104007D13EE /* AdMobNativeAdView.swift in Sources */, - 3CC4A3EA2C11F96800B97128 /* CustomRendererBannerController.swift in Sources */, 53ED2FD929798104007D13EE /* PrebidGAMInterstitialController.swift in Sources */, 53ED2FDA29798104007D13EE /* PrebidMAXRewardedController.swift in Sources */, 53ED2FDB29798104007D13EE /* PrebidMAXNativeController.swift in Sources */, - 53BFCD142CF9C67400A3287A /* SampleInterstitialController.swift in Sources */, 53ED2FDC29798104007D13EE /* PrebidMAXBannerController.swift in Sources */, 53ED2FDD29798104007D13EE /* IABConsentHelper.swift in Sources */, 53ED2FDE29798104007D13EE /* PrebidNativeAdController.swift in Sources */, @@ -1602,7 +1599,6 @@ 53ED2FE829798104007D13EE /* PrebidBannerController.swift in Sources */, 53ED2FE929798104007D13EE /* PrebidBannerConfigurationController.swift in Sources */, 53ED2FEA29798104007D13EE /* TestCase.swift in Sources */, - 53BFCD032CF792FB00A3287A /* SampleAdViewRenderer.swift in Sources */, 53ED2FEB29798104007D13EE /* PrebidAdMobNativeViewController.swift in Sources */, 53ED2FEC29798104007D13EE /* PrebidInterstitialController.swift in Sources */, 53ED2FED29798104007D13EE /* PrebidOriginalAPIDisplayInterstitialController.swift in Sources */, @@ -1635,24 +1631,27 @@ 53ED300729798104007D13EE /* PrebidFeedTableViewController.swift in Sources */, 53ED300829798104007D13EE /* TestCasesViewController.swift in Sources */, 53ED300929798104007D13EE /* NativeAdViewBoxLinks.swift in Sources */, - 53BFCD172CF9F12300A3287A /* SampleInterstitialRenderer.swift in Sources */, 53ED300A29798104007D13EE /* PrebidGAMRewardedController.swift in Sources */, 539F961529DEF2670061E7A5 /* PrebidOriginalAPIVideoInterstitialController.swift in Sources */, 53A369092AB996EF00A03B3E /* PrebidMultiformatConfigurationController.swift in Sources */, 53ED300B29798104007D13EE /* PrebidMAXInterstitialController.swift in Sources */, 53ED300C29798104007D13EE /* DummyTableViewCell.swift in Sources */, 53ED300D29798104007D13EE /* AboutViewController.swift in Sources */, + 53514CE12D08416B00A480C0 /* CustomRendererInterstitialController.swift in Sources */, + 53514CE22D08416B00A480C0 /* SampleAdViewRenderer.swift in Sources */, + 53514CE32D08416B00A480C0 /* SampleModalViewController.swift in Sources */, + 53514CE42D08416B00A480C0 /* SampleInterstitialRenderer.swift in Sources */, + 53514CE52D08416B00A480C0 /* SampleInterstitialController.swift in Sources */, + 53514CE62D08416B00A480C0 /* SampleAdView.swift in Sources */, + 53514CE72D08416B00A480C0 /* CustomRendererBannerController.swift in Sources */, 53ED300E29798104007D13EE /* NativeAdViewBoxProtocol.swift in Sources */, 53ED300F29798104007D13EE /* FormViewController+RowBuildHelpers.swift in Sources */, 53ED301029798104007D13EE /* PrebidGAMBannerController.swift in Sources */, 53ED301129798104007D13EE /* AppConfiguration.swift in Sources */, 53ED301229798104007D13EE /* ReactiveSdkInitFlag.swift in Sources */, 53ED301329798104007D13EE /* PrebidOriginalAPINativeBannerController.swift in Sources */, - 53BFCD0C2CF8F56300A3287A /* SampleAdView.swift in Sources */, 53ED301429798104007D13EE /* TestCasesSectionsViewController.swift in Sources */, - 3C28C9D92C35713B00D0A7DB /* CustomRendererInterstitialController.swift in Sources */, 53ED301529798104007D13EE /* AppSettingsKeys.swift in Sources */, - 53514C902CFF92D000A480C0 /* SampleModalViewController.swift in Sources */, 53ED301729798104007D13EE /* NativeEventTracker+Extensions.swift in Sources */, 53ED301829798104007D13EE /* PrebidRewardedController.swift in Sources */, 539F960C29DEF0B90061E7A5 /* PrebidOriginalAPIMultiformatBannerController.swift in Sources */, @@ -1682,11 +1681,9 @@ 53A651842AC200AA000D42E4 /* PrebidOriginalAPIMultiformatNativeStylesController.swift in Sources */, 34E5698A237DB96900B47B01 /* UtilitiesViewController.swift in Sources */, 92ABD58C279DA7E200AFDFF6 /* AdMobNativeAdView.swift in Sources */, - 3CC4A3E92C11F96800B97128 /* CustomRendererBannerController.swift in Sources */, 34BA95FE249CBF05006AE372 /* PrebidGAMInterstitialController.swift in Sources */, 92221CE52804BBB6005DF671 /* PrebidMAXRewardedController.swift in Sources */, 92986537280604E4007A2F34 /* PrebidMAXNativeController.swift in Sources */, - 53BFCD132CF9C67400A3287A /* SampleInterstitialController.swift in Sources */, 9289873F28003C250062BFAA /* PrebidMAXBannerController.swift in Sources */, 34BAD451239547420042DB33 /* IABConsentHelper.swift in Sources */, 92102C7227B11B67003F12B2 /* PrebidNativeAdController.swift in Sources */, @@ -1703,7 +1700,6 @@ 3493022224740BEE004A6086 /* PrebidBannerController.swift in Sources */, 5BDB85DA2739794900A529F6 /* PrebidBannerConfigurationController.swift in Sources */, 5B3EEDE52101FB8800BAA0C4 /* TestCase.swift in Sources */, - 53BFCD042CF792FB00A3287A /* SampleAdViewRenderer.swift in Sources */, 92C475122796FF8400C26E27 /* PrebidAdMobNativeViewController.swift in Sources */, 34FC0CF424ADD3A80045553E /* PrebidInterstitialController.swift in Sources */, 5397BD26293760F500ABDA22 /* PrebidOriginalAPIDisplayInterstitialController.swift in Sources */, @@ -1736,24 +1732,27 @@ ACAF055724D8384B0089DFB1 /* PrebidFeedTableViewController.swift in Sources */, 5B3EEDDF2101EA9200BAA0C4 /* TestCasesViewController.swift in Sources */, 92F9A5D227A15D04007B0B17 /* NativeAdViewBoxLinks.swift in Sources */, - 53BFCD182CF9F12300A3287A /* SampleInterstitialRenderer.swift in Sources */, 34FC0CF624ADD5640045553E /* PrebidGAMRewardedController.swift in Sources */, 539F961429DEF2670061E7A5 /* PrebidOriginalAPIVideoInterstitialController.swift in Sources */, 53A369082AB996EF00A03B3E /* PrebidMultiformatConfigurationController.swift in Sources */, 92221CE12804AF5B005DF671 /* PrebidMAXInterstitialController.swift in Sources */, 5B8EB5EF22676914003CC15C /* DummyTableViewCell.swift in Sources */, 5B3EEDCB2101D1AF00BAA0C4 /* AboutViewController.swift in Sources */, + 53514CE82D08416B00A480C0 /* CustomRendererInterstitialController.swift in Sources */, + 53514CE92D08416B00A480C0 /* SampleAdViewRenderer.swift in Sources */, + 53514CEA2D08416B00A480C0 /* SampleModalViewController.swift in Sources */, + 53514CEB2D08416B00A480C0 /* SampleInterstitialRenderer.swift in Sources */, + 53514CEC2D08416B00A480C0 /* SampleInterstitialController.swift in Sources */, + 53514CED2D08416B00A480C0 /* SampleAdView.swift in Sources */, + 53514CEE2D08416B00A480C0 /* CustomRendererBannerController.swift in Sources */, 92F9A5D127A15BD1007B0B17 /* NativeAdViewBoxProtocol.swift in Sources */, 341CC3142562C9D000186F29 /* FormViewController+RowBuildHelpers.swift in Sources */, 3493021C2473F408004A6086 /* PrebidGAMBannerController.swift in Sources */, D551B96F21491AAA00FFF51D /* AppConfiguration.swift in Sources */, 346C6F5725DFAB7E00457DD3 /* ReactiveSdkInitFlag.swift in Sources */, 5397BD2C2937764100ABDA22 /* PrebidOriginalAPINativeBannerController.swift in Sources */, - 53BFCD0D2CF8F56300A3287A /* SampleAdView.swift in Sources */, 5B3EEDE22101EDA200BAA0C4 /* TestCasesSectionsViewController.swift in Sources */, - 3C28C9D82C35713B00D0A7DB /* CustomRendererInterstitialController.swift in Sources */, ACC41ACD2444EADB00B9A3A7 /* AppSettingsKeys.swift in Sources */, - 53514C8F2CFF92D000A480C0 /* SampleModalViewController.swift in Sources */, 92C4E60D27A2F6D700738370 /* NativeEventTracker+Extensions.swift in Sources */, 34BA9600249CC118006AE372 /* PrebidRewardedController.swift in Sources */, 539F960B29DEF0B90061E7A5 /* PrebidOriginalAPIMultiformatBannerController.swift in Sources */, diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m index aa4001ffa..33f155c5c 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m @@ -32,6 +32,7 @@ @interface PBMInterstitialAdLoader () delegate; @property (nonatomic, strong, nullable) id renderer; +@property (nonatomic, weak, nullable, readonly) id eventHandler; @end @@ -41,7 +42,8 @@ @implementation PBMInterstitialAdLoader // MARK: - Lifecycle -- (instancetype)initWithDelegate:(id)delegate { +- (instancetype)initWithDelegate:(id)delegate + eventHandler:(nonnull id)eventHandler { if (!(self = [super init])) { return nil; } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnit.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnit.swift index 03e78c8cd..1ca836d5c 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnit.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnit.swift @@ -213,9 +213,9 @@ class BaseInterstitialAdUnit: delegate?.callDelegate_willLeaveApplication() } - public func interstitialControllerDidDisplay(_ interstitialController: InterstitialControllerProtocol) {} - public func interstitialControllerDidComplete(_ interstitialController: InterstitialControllerProtocol) {} - public func trackUserReward(_ interstitialController: InterstitialControllerProtocol, _ reward: PrebidReward) {} + public func interstitialControllerDidDisplay(_ interstitialController: PrebidMobileInterstitialControllerProtocol) {} + public func interstitialControllerDidComplete(_ interstitialController: PrebidMobileInterstitialControllerProtocol) {} + public func trackUserReward(_ interstitialController: PrebidMobileInterstitialControllerProtocol, _ reward: PrebidReward) {} public func viewControllerForModalPresentation( fromInterstitialController: PrebidMobileInterstitialControllerProtocol @@ -223,26 +223,6 @@ class BaseInterstitialAdUnit: return targetController } - /// Called when the interstitial controller displays an ad. - public func interstitialControllerDidDisplay(_ interstitialController: PrebidMobileInterstitialControllerProtocol) {} - - /// Called when the interstitial controller completes the ad display. - public func interstitialControllerDidComplete(_ interstitialController: PrebidMobileInterstitialControllerProtocol) {} - - // MARK: - Private methods - - private func reportLoadingSuccess() { - DispatchQueue.main.async { - self.callDelegate_didReceiveAd() - } - } - - private func reportLoadingFailed(with error: Error?) { - DispatchQueue.main.async { - self.callDelegate_didFailToReceiveAd(with: error) - } - } - // MARK: - InterstitialEventInteractionDelegate /// Called when an ad is about to be presented. diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnitProtocol.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnitProtocol.swift index b59adab0d..f2495680f 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnitProtocol.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseInterstitialAdUnitProtocol.swift @@ -16,7 +16,7 @@ import UIKit @objc -public protocol BaseInterstitialAdUnitProtocol: NSObjectProtocol { +protocol BaseInterstitialAdUnitProtocol: NSObjectProtocol { @objc func interstitialControllerDidCloseAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseRewardedAdUnit.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseRewardedAdUnit.swift index 4d7f833db..98b2ba1dc 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseRewardedAdUnit.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/BaseRewardedAdUnit.swift @@ -35,7 +35,10 @@ class BaseRewardedAdUnit: BaseInterstitialAdUnit, RewardedEventInteractionDelega // MARK: - InterstitialControllerInteractionDelegate - override func trackUserReward(_ interstitialController: InterstitialController, _ reward: PrebidReward) { + override func trackUserReward( + _ interstitialController: PrebidMobileInterstitialControllerProtocol, + _ reward: PrebidReward + ) { DispatchQueue.main.async { self.delegate?.callDelegate_rewardedAdUserDidEarnReward?(reward: reward) } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/InterstitialRenderingAdUnit.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/InterstitialRenderingAdUnit.swift index 2ee10b83d..689ab00dc 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/InterstitialRenderingAdUnit.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/InterstitialRenderingAdUnit.swift @@ -372,7 +372,7 @@ public class InterstitialRenderingAdUnit: NSObject, BaseInterstitialAdUnitProtoc // MARK: - Internal methods - func interstitialControllerDidCloseAd(_ interstitialController: InterstitialController) { + func interstitialControllerDidCloseAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { baseAdUnit.interstitialControllerDidCloseAd(interstitialController) } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedAdUnit.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedAdUnit.swift index d9b020d4a..ac61f16dc 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedAdUnit.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedAdUnit.swift @@ -203,14 +203,34 @@ public class RewardedAdUnit: NSObject, BaseInterstitialAdUnitProtocol { addExtData(key: key, value: data) } - // MARK: - BaseInterstitialAdUnitProtocol protocol + /// Updates context data for a specified key. + /// - Parameters: + /// - data: A set of data to update. + /// - key: The key associated with the data. + @available(*, deprecated, message: "This method is deprecated. Please, use updateExtData method instead.") + public func updateContextData(_ data: Set, forKey key: String) { + updateExtData(key: key, value: data) + } - /// Called when the interstitial ad is closed. - /// - /// - Parameter interstitialController: The controller managing the interstitial ad. - @objc public override func interstitialControllerDidCloseAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { - callDelegate_rewardedAdUserDidEarnReward() - super.interstitialControllerDidCloseAd(interstitialController) + /// Removes context data for a specified key. + /// - Parameter key: The key associated with the data to remove. + @available(*, deprecated, message: "This method is deprecated. Please, use removeExtData method instead.") + public func removeContextDate(forKey key: String) { + removeExtData(forKey: key) + } + + /// Clears all context data. + @available(*, deprecated, message: "This method is deprecated. Please, use clearExtData method instead.") + public func clearContextData() { + clearExtData() + } + + /// Adds ext data. + /// - Parameters: + /// - key: The key for the data. + /// - value: The value for the data. + public func addExtData(key: String, value: String) { + adUnitConfig.addExtData(key: key, value: value) } /// Updates ext data. @@ -336,7 +356,7 @@ public class RewardedAdUnit: NSObject, BaseInterstitialAdUnitProtocol { // MARK: - Internal methods - func interstitialControllerDidCloseAd(_ interstitialController: InterstitialController) { + func interstitialControllerDidCloseAd(_ interstitialController: PrebidMobileInterstitialControllerProtocol) { baseAdUnit.interstitialControllerDidCloseAd(interstitialController) } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedConfig.swift b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedConfig.swift index cabdbefbb..1228f3fbd 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedConfig.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/RewardedConfig.swift @@ -75,7 +75,7 @@ public class RewardedConfig: NSObject { private let ortbRewarded: PBMORTBRewardedConfiguration? - init(ortbRewarded: PBMORTBRewardedConfiguration?) { + public init(ortbRewarded: PBMORTBRewardedConfiguration?) { self.ortbRewarded = ortbRewarded } } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m index 8679b49e2..8d6850728 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m @@ -78,6 +78,7 @@ - (void)loadAd { } self.adConfiguration.adConfiguration.winningBidAdFormat = self.bid.adFormat; + self.adConfiguration.adConfiguration.rewardedConfig = [[PBMRewardedConfig alloc] initWithOrtbRewarded:self.bid.rewardedConfig]; @weakify(self); self.transactionFactory = [[PBMTransactionFactory alloc] initWithBid:self.bid diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialController.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialController.swift index ba2b8307d..bebd17947 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialController.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialController.swift @@ -73,6 +73,7 @@ public class InterstitialController: } adConfiguration.adConfiguration.winningBidAdFormat = bid.adFormat + adConfiguration.adConfiguration.rewardedConfig = RewardedConfig(ortbRewarded: bid.rewardedConfig) videoControlsConfig.initialize(with: bid.videoAdConfiguration) // This part is dedicating to test server-side ad configurations. @@ -169,12 +170,6 @@ public class InterstitialController: } } - @objc public func adDidSendRewardedEvent() { - if let delegate = interactionDelegate { - delegate.trackUserReward?(self, PrebidReward(with: bid.rewardedConfig?.reward)) - } - } - @objc public func interstitialDisplayProperties() -> PBMInterstitialDisplayProperties { displayProperties } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerInteractionDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerInteractionDelegate.swift index 25d7fab60..4d4064b9c 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerInteractionDelegate.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerInteractionDelegate.swift @@ -74,4 +74,14 @@ public protocol InterstitialControllerInteractionDelegate: NSObjectProtocol { @objc func viewControllerForModalPresentation( fromInterstitialController: PrebidMobileInterstitialControllerProtocol ) -> UIViewController? + + /// Notifies the delegate when a reward is granted to the user after interacting with a rewarded interstitial ad. + /// + /// - Parameters: + /// - interstitialController: The instance of the interstitial ad controller responsible for managing the ad. + /// - reward: An object containing details about the reward, such as the type and amount. + @objc optional func trackUserReward( + _ interstitialController: PrebidMobileInterstitialControllerProtocol, + _ reward: PrebidReward + ) } From 50d0ec3315dafe0b3b79d9525ad7a6b71fb152c8 Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Tue, 10 Dec 2024 13:22:59 +0200 Subject: [PATCH 13/18] feat: make universal Renderer protocol --- .../PrebidDemo.xcodeproj/project.pbxproj | 70 +++++++-------- ...isplayBannerPluginRendererViewController.m | 6 +- ...InterstitialPluginRendererViewController.m | 6 +- .../SampleRenderers/SampleAdViewRenderer.m | 51 ----------- .../SampleInterstitialRenderer.h | 30 ------- ...ampleAdViewRenderer.h => SampleRenderer.h} | 3 +- ...nterstitialRenderer.m => SampleRenderer.m} | 21 ++++- ...ayBannerPluginRendererViewController.swift | 2 +- ...rstitialPluginRendererViewController.swift | 2 +- .../SampleInterstitialRenderer.swift | 46 ---------- ...iewRenderer.swift => SampleRenderer.swift} | 23 ++++- .../BannerAdsTest.swift | 27 ++++-- .../PrebidDemoSwiftUITests/BaseAdsTest.swift | 1 - .../InterstitialAdsTest.swift | 38 +++++++- .../Utils/TestCases.swift | 2 + .../InternalTestApp.xcodeproj/project.pbxproj | 18 ++-- .../CustomRendererBannerController.swift | 2 +- ...CustomRendererInterstitialController.swift | 2 +- .../SampleInterstitialRenderer.swift | 43 --------- ...iewRenderer.swift => SampleRenderer.swift} | 21 ++++- PrebidMobile.xcodeproj/project.pbxproj | 54 ++++-------- .../PrebidMobilePluginRegister.swift | 29 +++---- .../PrebidMobilePluginRenderer.swift | 18 +--- .../GAM/AdLoading/PBMBannerAdLoader.m | 32 ++----- .../GAM/AdLoading/PBMInterstitialAdLoader.m | 30 ++----- .../PrebidDisplayViewRenderer.swift | 46 ---------- .../DisplayViewInteractionDelegate.swift | 0 .../DisplayViewLoadingDelegate.swift | 0 .../InterstitialController.swift | 0 ...stitialControllerInteractionDelegate.swift | 87 ------------------- ...stitialControllerInteractionDelegate.swift | 71 +++++++++++++-- ...nterstitialControllerLoadingDelegate.swift | 0 .../PBMDisplayView+InternalState.h | 0 .../{DisplayView => }/PBMDisplayView.h | 0 .../{DisplayView => }/PBMDisplayView.m | 0 .../PrebidMobileDisplayViewProtocol.h | 0 ...MobileInterstitialControllerProtocol.swift | 0 ...lerRenderer.swift => PrebidRenderer.swift} | 29 +++++-- 38 files changed, 294 insertions(+), 516 deletions(-) delete mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.m delete mode 100644 Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.h rename Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/{SampleAdViewRenderer.h => SampleRenderer.h} (88%) rename Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/{SampleInterstitialRenderer.m => SampleRenderer.m} (66%) delete mode 100644 Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialRenderer.swift rename Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/{SampleAdViewRenderer.swift => SampleRenderer.swift} (63%) delete mode 100644 InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialRenderer.swift rename InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/{SampleAdViewRenderer.swift => SampleRenderer.swift} (64%) delete mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PrebidDisplayViewRenderer.swift rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{DisplayView => }/DisplayViewInteractionDelegate.swift (100%) rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{DisplayView => }/DisplayViewLoadingDelegate.swift (100%) rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{InterstitialController => }/InterstitialController.swift (100%) delete mode 100644 PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerInteractionDelegate.swift rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{InterstitialController => }/InterstitialControllerLoadingDelegate.swift (100%) rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{DisplayView => }/PBMDisplayView+InternalState.h (100%) rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{DisplayView => }/PBMDisplayView.h (100%) rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{DisplayView => }/PBMDisplayView.m (100%) rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{DisplayView => }/PrebidMobileDisplayViewProtocol.h (100%) rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{InterstitialController => }/PrebidMobileInterstitialControllerProtocol.swift (100%) rename PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/{InterstitialController/PrebidInterstitialControllerRenderer.swift => PrebidRenderer.swift} (64%) diff --git a/Example/PrebidDemo/PrebidDemo.xcodeproj/project.pbxproj b/Example/PrebidDemo/PrebidDemo.xcodeproj/project.pbxproj index 0eca65127..68c6df8dd 100644 --- a/Example/PrebidDemo/PrebidDemo.xcodeproj/project.pbxproj +++ b/Example/PrebidDemo/PrebidDemo.xcodeproj/project.pbxproj @@ -67,27 +67,25 @@ 5344E6C12922A97200A1F582 /* MAXVideoInterstitialViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5344E6C02922A97200A1F582 /* MAXVideoInterstitialViewController.swift */; }; 5344E6C32922AAE500A1F582 /* MAXVideoRewardedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5344E6C22922AAE500A1F582 /* MAXVideoRewardedViewController.swift */; }; 5344E6C52922AC2C00A1F582 /* MAXNativeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5344E6C42922AC2C00A1F582 /* MAXNativeViewController.swift */; }; + 534C614D2CB7EFD50026119A /* InAppDisplayRewardedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534C614C2CB7EFD50026119A /* InAppDisplayRewardedViewController.swift */; }; + 534C614F2CB7F20A0026119A /* GAMDisplayRewardedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534C614E2CB7F20A0026119A /* GAMDisplayRewardedViewController.swift */; }; + 534C61552CB7F32D0026119A /* MAXDisplayRewardedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534C61542CB7F32D0026119A /* MAXDisplayRewardedViewController.swift */; }; + 534C61572CB7F4780026119A /* AdMobDisplayRewardedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534C61562CB7F4780026119A /* AdMobDisplayRewardedViewController.swift */; }; + 534C615B2CB809F70026119A /* InAppDisplayRewardedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 534C615A2CB809F70026119A /* InAppDisplayRewardedViewController.m */; }; + 534C615E2CB84DCB0026119A /* AdMobDisplayRewardedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 534C615D2CB84DCB0026119A /* AdMobDisplayRewardedViewController.m */; }; + 534C61612CB850FD0026119A /* GAMDisplayRewardedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 534C61602CB850FD0026119A /* GAMDisplayRewardedViewController.m */; }; + 534C61642CB851C10026119A /* MAXDisplayRewardedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 534C61632CB851C10026119A /* MAXDisplayRewardedViewController.m */; }; 53514C962CFF97DB00A480C0 /* InAppDisplayBannerPluginRendererViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C952CFF97DB00A480C0 /* InAppDisplayBannerPluginRendererViewController.swift */; }; 53514C9E2CFF988E00A480C0 /* SampleAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C982CFF988E00A480C0 /* SampleAdView.swift */; }; 53514C9F2CFF988E00A480C0 /* SampleInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C9B2CFF988E00A480C0 /* SampleInterstitialController.swift */; }; - 53514CA02CFF988E00A480C0 /* SampleAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C992CFF988E00A480C0 /* SampleAdViewRenderer.swift */; }; - 53514CA12CFF988E00A480C0 /* SampleInterstitialRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C9A2CFF988E00A480C0 /* SampleInterstitialRenderer.swift */; }; + 53514CA02CFF988E00A480C0 /* SampleRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514C992CFF988E00A480C0 /* SampleRenderer.swift */; }; 53514CA32CFF9DD000A480C0 /* InAppDisplayInterstitialPluginRendererViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CA22CFF9DD000A480C0 /* InAppDisplayInterstitialPluginRendererViewController.swift */; }; 53514CA72CFFA52A00A480C0 /* SampleAdView.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CA62CFFA52A00A480C0 /* SampleAdView.m */; }; - 53514CAA2CFFA62700A480C0 /* SampleAdViewRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CA92CFFA62700A480C0 /* SampleAdViewRenderer.m */; }; + 53514CAA2CFFA62700A480C0 /* SampleRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CA92CFFA62700A480C0 /* SampleRenderer.m */; }; 53514CAD2CFFA99200A480C0 /* InAppDisplayBannerPluginRendererViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CAC2CFFA99200A480C0 /* InAppDisplayBannerPluginRendererViewController.m */; }; 53514CB02CFFAB6700A480C0 /* SampleInterstitialController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CAF2CFFAB6700A480C0 /* SampleInterstitialController.m */; }; 53514CB32CFFAD5E00A480C0 /* UIApplication+TopViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CB22CFFAD5E00A480C0 /* UIApplication+TopViewController.m */; }; - 53514CB62CFFADC200A480C0 /* SampleInterstitialRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CB52CFFADC200A480C0 /* SampleInterstitialRenderer.m */; }; 53514CB92CFFAECB00A480C0 /* InAppDisplayInterstitialPluginRendererViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 53514CB82CFFAECB00A480C0 /* InAppDisplayInterstitialPluginRendererViewController.m */; }; - 534C614D2CB7EFD50026119A /* InAppDisplayRewardedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534C614C2CB7EFD50026119A /* InAppDisplayRewardedViewController.swift */; }; - 534C614F2CB7F20A0026119A /* GAMDisplayRewardedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534C614E2CB7F20A0026119A /* GAMDisplayRewardedViewController.swift */; }; - 534C61552CB7F32D0026119A /* MAXDisplayRewardedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534C61542CB7F32D0026119A /* MAXDisplayRewardedViewController.swift */; }; - 534C61572CB7F4780026119A /* AdMobDisplayRewardedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534C61562CB7F4780026119A /* AdMobDisplayRewardedViewController.swift */; }; - 534C615B2CB809F70026119A /* InAppDisplayRewardedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 534C615A2CB809F70026119A /* InAppDisplayRewardedViewController.m */; }; - 534C615E2CB84DCB0026119A /* AdMobDisplayRewardedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 534C615D2CB84DCB0026119A /* AdMobDisplayRewardedViewController.m */; }; - 534C61612CB850FD0026119A /* GAMDisplayRewardedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 534C61602CB850FD0026119A /* GAMDisplayRewardedViewController.m */; }; - 534C61642CB851C10026119A /* MAXDisplayRewardedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 534C61632CB851C10026119A /* MAXDisplayRewardedViewController.m */; }; 539928BF292534EB0078053C /* IntegrationCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 539928BE292534EA0078053C /* IntegrationCase.m */; }; 539928C2292535B70078053C /* AdFormatDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 539928C1292535B70078053C /* AdFormatDescriptor.m */; }; 539928C92925379C0078053C /* IntegrationKindDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 539928C82925379C0078053C /* IntegrationKindDescriptor.m */; }; @@ -294,38 +292,35 @@ 5344E6C02922A97200A1F582 /* MAXVideoInterstitialViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MAXVideoInterstitialViewController.swift; sourceTree = ""; }; 5344E6C22922AAE500A1F582 /* MAXVideoRewardedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MAXVideoRewardedViewController.swift; sourceTree = ""; }; 5344E6C42922AC2C00A1F582 /* MAXNativeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MAXNativeViewController.swift; sourceTree = ""; }; + 534C614C2CB7EFD50026119A /* InAppDisplayRewardedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppDisplayRewardedViewController.swift; sourceTree = ""; }; + 534C614E2CB7F20A0026119A /* GAMDisplayRewardedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GAMDisplayRewardedViewController.swift; sourceTree = ""; }; + 534C61542CB7F32D0026119A /* MAXDisplayRewardedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MAXDisplayRewardedViewController.swift; sourceTree = ""; }; + 534C61562CB7F4780026119A /* AdMobDisplayRewardedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdMobDisplayRewardedViewController.swift; sourceTree = ""; }; + 534C61592CB809F70026119A /* InAppDisplayRewardedViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InAppDisplayRewardedViewController.h; sourceTree = ""; }; + 534C615A2CB809F70026119A /* InAppDisplayRewardedViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InAppDisplayRewardedViewController.m; sourceTree = ""; }; + 534C615C2CB84DCB0026119A /* AdMobDisplayRewardedViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AdMobDisplayRewardedViewController.h; sourceTree = ""; }; + 534C615D2CB84DCB0026119A /* AdMobDisplayRewardedViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AdMobDisplayRewardedViewController.m; sourceTree = ""; }; + 534C615F2CB850FD0026119A /* GAMDisplayRewardedViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GAMDisplayRewardedViewController.h; sourceTree = ""; }; + 534C61602CB850FD0026119A /* GAMDisplayRewardedViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GAMDisplayRewardedViewController.m; sourceTree = ""; }; + 534C61622CB851C10026119A /* MAXDisplayRewardedViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MAXDisplayRewardedViewController.h; sourceTree = ""; }; + 534C61632CB851C10026119A /* MAXDisplayRewardedViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MAXDisplayRewardedViewController.m; sourceTree = ""; }; 53514C952CFF97DB00A480C0 /* InAppDisplayBannerPluginRendererViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppDisplayBannerPluginRendererViewController.swift; sourceTree = ""; }; 53514C982CFF988E00A480C0 /* SampleAdView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAdView.swift; sourceTree = ""; }; - 53514C992CFF988E00A480C0 /* SampleAdViewRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAdViewRenderer.swift; sourceTree = ""; }; - 53514C9A2CFF988E00A480C0 /* SampleInterstitialRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleInterstitialRenderer.swift; sourceTree = ""; }; + 53514C992CFF988E00A480C0 /* SampleRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleRenderer.swift; sourceTree = ""; }; 53514C9B2CFF988E00A480C0 /* SampleInterstitialController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleInterstitialController.swift; sourceTree = ""; }; 53514CA22CFF9DD000A480C0 /* InAppDisplayInterstitialPluginRendererViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppDisplayInterstitialPluginRendererViewController.swift; sourceTree = ""; }; 53514CA52CFFA52A00A480C0 /* SampleAdView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleAdView.h; sourceTree = ""; }; 53514CA62CFFA52A00A480C0 /* SampleAdView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleAdView.m; sourceTree = ""; }; - 53514CA82CFFA62700A480C0 /* SampleAdViewRenderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleAdViewRenderer.h; sourceTree = ""; }; - 53514CA92CFFA62700A480C0 /* SampleAdViewRenderer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleAdViewRenderer.m; sourceTree = ""; }; + 53514CA82CFFA62700A480C0 /* SampleRenderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleRenderer.h; sourceTree = ""; }; + 53514CA92CFFA62700A480C0 /* SampleRenderer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleRenderer.m; sourceTree = ""; }; 53514CAB2CFFA99200A480C0 /* InAppDisplayBannerPluginRendererViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InAppDisplayBannerPluginRendererViewController.h; sourceTree = ""; }; 53514CAC2CFFA99200A480C0 /* InAppDisplayBannerPluginRendererViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InAppDisplayBannerPluginRendererViewController.m; sourceTree = ""; }; 53514CAE2CFFAB6700A480C0 /* SampleInterstitialController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleInterstitialController.h; sourceTree = ""; }; 53514CAF2CFFAB6700A480C0 /* SampleInterstitialController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleInterstitialController.m; sourceTree = ""; }; 53514CB12CFFAD5E00A480C0 /* UIApplication+TopViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIApplication+TopViewController.h"; sourceTree = ""; }; 53514CB22CFFAD5E00A480C0 /* UIApplication+TopViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIApplication+TopViewController.m"; sourceTree = ""; }; - 53514CB42CFFADC200A480C0 /* SampleInterstitialRenderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleInterstitialRenderer.h; sourceTree = ""; }; - 53514CB52CFFADC200A480C0 /* SampleInterstitialRenderer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleInterstitialRenderer.m; sourceTree = ""; }; 53514CB72CFFAECB00A480C0 /* InAppDisplayInterstitialPluginRendererViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InAppDisplayInterstitialPluginRendererViewController.h; sourceTree = ""; }; 53514CB82CFFAECB00A480C0 /* InAppDisplayInterstitialPluginRendererViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InAppDisplayInterstitialPluginRendererViewController.m; sourceTree = ""; }; - 534C614C2CB7EFD50026119A /* InAppDisplayRewardedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppDisplayRewardedViewController.swift; sourceTree = ""; }; - 534C614E2CB7F20A0026119A /* GAMDisplayRewardedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GAMDisplayRewardedViewController.swift; sourceTree = ""; }; - 534C61542CB7F32D0026119A /* MAXDisplayRewardedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MAXDisplayRewardedViewController.swift; sourceTree = ""; }; - 534C61562CB7F4780026119A /* AdMobDisplayRewardedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdMobDisplayRewardedViewController.swift; sourceTree = ""; }; - 534C61592CB809F70026119A /* InAppDisplayRewardedViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InAppDisplayRewardedViewController.h; sourceTree = ""; }; - 534C615A2CB809F70026119A /* InAppDisplayRewardedViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InAppDisplayRewardedViewController.m; sourceTree = ""; }; - 534C615C2CB84DCB0026119A /* AdMobDisplayRewardedViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AdMobDisplayRewardedViewController.h; sourceTree = ""; }; - 534C615D2CB84DCB0026119A /* AdMobDisplayRewardedViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AdMobDisplayRewardedViewController.m; sourceTree = ""; }; - 534C615F2CB850FD0026119A /* GAMDisplayRewardedViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GAMDisplayRewardedViewController.h; sourceTree = ""; }; - 534C61602CB850FD0026119A /* GAMDisplayRewardedViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GAMDisplayRewardedViewController.m; sourceTree = ""; }; - 534C61622CB851C10026119A /* MAXDisplayRewardedViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MAXDisplayRewardedViewController.h; sourceTree = ""; }; - 534C61632CB851C10026119A /* MAXDisplayRewardedViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MAXDisplayRewardedViewController.m; sourceTree = ""; }; 5354C0C62923E99800DB25EA /* TestUtils.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = TestUtils.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 539928BD292534BB0078053C /* IntegrationCase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IntegrationCase.h; sourceTree = ""; }; 539928BE292534EA0078053C /* IntegrationCase.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IntegrationCase.m; sourceTree = ""; }; @@ -773,10 +768,9 @@ 53514C972CFF981100A480C0 /* SampleRenderers */ = { isa = PBXGroup; children = ( + 53514C992CFF988E00A480C0 /* SampleRenderer.swift */, 53514C982CFF988E00A480C0 /* SampleAdView.swift */, - 53514C992CFF988E00A480C0 /* SampleAdViewRenderer.swift */, 53514C9B2CFF988E00A480C0 /* SampleInterstitialController.swift */, - 53514C9A2CFF988E00A480C0 /* SampleInterstitialRenderer.swift */, ); path = SampleRenderers; sourceTree = ""; @@ -784,14 +778,12 @@ 53514CA42CFFA4F000A480C0 /* SampleRenderers */ = { isa = PBXGroup; children = ( + 53514CA82CFFA62700A480C0 /* SampleRenderer.h */, + 53514CA92CFFA62700A480C0 /* SampleRenderer.m */, 53514CA52CFFA52A00A480C0 /* SampleAdView.h */, 53514CA62CFFA52A00A480C0 /* SampleAdView.m */, - 53514CA82CFFA62700A480C0 /* SampleAdViewRenderer.h */, - 53514CA92CFFA62700A480C0 /* SampleAdViewRenderer.m */, 53514CAE2CFFAB6700A480C0 /* SampleInterstitialController.h */, 53514CAF2CFFAB6700A480C0 /* SampleInterstitialController.m */, - 53514CB42CFFADC200A480C0 /* SampleInterstitialRenderer.h */, - 53514CB52CFFADC200A480C0 /* SampleInterstitialRenderer.m */, ); path = SampleRenderers; sourceTree = ""; @@ -1582,8 +1574,7 @@ 53072B7B292270EE00228462 /* InAppDisplayInterstitialViewController.swift in Sources */, 53514C9E2CFF988E00A480C0 /* SampleAdView.swift in Sources */, 53514C9F2CFF988E00A480C0 /* SampleInterstitialController.swift in Sources */, - 53514CA02CFF988E00A480C0 /* SampleAdViewRenderer.swift in Sources */, - 53514CA12CFF988E00A480C0 /* SampleInterstitialRenderer.swift in Sources */, + 53514CA02CFF988E00A480C0 /* SampleRenderer.swift in Sources */, 53072B5E2921522000228462 /* GAMOriginalAPIVideoRewardedViewController.swift in Sources */, 530D4AA6291A4BC600A2C796 /* AppDelegate.swift in Sources */, 53072B6C29217E8600228462 /* InstreamBaseViewController.swift in Sources */, @@ -1688,8 +1679,7 @@ 53A368FD2AB8CBB300A03B3E /* MultiformatBaseViewController.m in Sources */, 53F35F2B2926A58B001C1183 /* InAppVideoBannerViewController.m in Sources */, 53F35F4C2926D130001C1183 /* MAXVideoRewardedViewController.m in Sources */, - 53514CAA2CFFA62700A480C0 /* SampleAdViewRenderer.m in Sources */, - 53514CB62CFFADC200A480C0 /* SampleInterstitialRenderer.m in Sources */, + 53514CAA2CFFA62700A480C0 /* SampleRenderer.m in Sources */, 53F35F1F29269668001C1183 /* AdMobVideoInterstitialViewController.m in Sources */, 539928C92925379C0078053C /* IntegrationKindDescriptor.m in Sources */, 53F35F0C29267C65001C1183 /* GAMVideoInterstitialViewController.m in Sources */, diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.m index 4a75e319a..91dd23ad0 100644 --- a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.m +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayBannerPluginRendererViewController.m @@ -15,7 +15,7 @@ #import "InAppDisplayBannerPluginRendererViewController.h" #import "PrebidDemoMacros.h" -#import "SampleAdViewRenderer.h" +#import "SampleRenderer.h" NSString * const storedImpDisplayBannerPluginRendererInApp = @"prebid-demo-display-banner-320-50-custom-ad-view-renderer"; @@ -23,7 +23,7 @@ @interface InAppDisplayBannerPluginRendererViewController () // Prebid @property (nonatomic) BannerView * prebidBannerView; -@property (nonatomic, strong) SampleAdViewRenderer * samplePluginRenderer; +@property (nonatomic, strong) SampleRenderer * samplePluginRenderer; @end @@ -42,7 +42,7 @@ - (void)dealloc { - (void)createAd { // 1. Create a plugin renderer - self.samplePluginRenderer = [SampleAdViewRenderer new]; + self.samplePluginRenderer = [SampleRenderer new]; // 2. Register the plugin renderer [Prebid registerPluginRenderer:self.samplePluginRenderer]; diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.m index ec287aef3..98de46a99 100644 --- a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.m +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/InAppDisplayInterstitialPluginRendererViewController.m @@ -15,7 +15,7 @@ #import "InAppDisplayInterstitialPluginRendererViewController.h" #import "PrebidDemoMacros.h" -#import "SampleInterstitialRenderer.h" +#import "SampleRenderer.h" NSString * const storedImpDisplayInterstitialPluginRendererInApp = @"prebid-demo-display-interstitial-320-480-custom-interstitial-renderer"; @@ -23,7 +23,7 @@ @interface InAppDisplayInterstitialPluginRendererViewController () // Prebid @property (nonatomic) InterstitialRenderingAdUnit * renderingInterstitial; -@property (nonatomic, strong) SampleInterstitialRenderer * samplePluginRenderer; +@property (nonatomic, strong) SampleRenderer * samplePluginRenderer; @end @@ -42,7 +42,7 @@ - (void)dealloc { - (void)createAd { // 1. Create a plugin renderer - self.samplePluginRenderer = [SampleInterstitialRenderer new]; + self.samplePluginRenderer = [SampleRenderer new]; // 2. Register the plugin renderer [Prebid registerPluginRenderer:self.samplePluginRenderer]; diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.m deleted file mode 100644 index ccb88550b..000000000 --- a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.m +++ /dev/null @@ -1,51 +0,0 @@ -/*   Copyright 2018-2024 Prebid.org, Inc. - -  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 "SampleAdViewRenderer.h" - -@implementation SampleAdViewRenderer - -@synthesize name; -@synthesize version; -@synthesize data; - -- (instancetype)init { - self = [super init]; - if (self) { - name = @"SampleAdViewRenderer"; - version = @"1.0.0"; - } - return self; -} - -- (BOOL)isSupportRenderingFor:(AdFormat *)format { - return [@[AdFormat.banner, AdFormat.video] containsObject:format]; -} - -- (UIView * _Nullable)createAdViewWith:(CGRect)frame - bid:(Bid * _Nonnull)bid - adConfiguration:(AdUnitConfig * _Nonnull)adConfiguration - loadingDelegate:(id _Nonnull)loadingDelegate - interactionDelegate:(id _Nonnull)interactionDelegate { - SampleAdView *adView = [[SampleAdView alloc] initWithFrame:frame]; - - adView.interactionDelegate = interactionDelegate; - adView.loadingDelegate = loadingDelegate; - adView.bid = bid; - - return adView; -} - -@end diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.h b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.h deleted file mode 100644 index 59fee647a..000000000 --- a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.h +++ /dev/null @@ -1,30 +0,0 @@ -/*   Copyright 2018-2024 Prebid.org, Inc. - -  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 -#import "SampleInterstitialController.h" - -@import PrebidMobile; - -NS_ASSUME_NONNULL_BEGIN - -/// A custom implementation of the interstitial ad renderer. -@interface SampleInterstitialRenderer : NSObject - -- (instancetype)init; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.h b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleRenderer.h similarity index 88% rename from Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.h rename to Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleRenderer.h index ad45e59d3..90922a159 100644 --- a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleAdViewRenderer.h +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleRenderer.h @@ -15,13 +15,14 @@ #import #import "SampleAdView.h" +#import "SampleInterstitialController.h" @import PrebidMobile; NS_ASSUME_NONNULL_BEGIN /// A custom implementation of the ad view renderer. -@interface SampleAdViewRenderer : NSObject +@interface SampleRenderer : NSObject - (instancetype)init; diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleRenderer.m similarity index 66% rename from Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.m rename to Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleRenderer.m index 1b2dfc402..5888717bc 100644 --- a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleInterstitialRenderer.m +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleRenderer.m @@ -13,10 +13,9 @@  limitations under the License.  */ -#import "SampleInterstitialRenderer.h" -#import "SampleInterstitialController.h" +#import "SampleRenderer.h" -@implementation SampleInterstitialRenderer +@implementation SampleRenderer @synthesize name; @synthesize version; @@ -25,7 +24,7 @@ @implementation SampleInterstitialRenderer - (instancetype)init { self = [super init]; if (self) { - name = @"SampleInterstitialRenderer"; + name = @"SampleRenderer"; version = @"1.0.0"; } return self; @@ -35,6 +34,20 @@ - (BOOL)isSupportRenderingFor:(AdFormat *)format { return [@[AdFormat.banner, AdFormat.video] containsObject:format]; } +- (UIView * _Nullable)createBannerViewWith:(CGRect)frame + bid:(Bid * _Nonnull)bid + adConfiguration:(AdUnitConfig * _Nonnull)adConfiguration + loadingDelegate:(id _Nonnull)loadingDelegate + interactionDelegate:(id _Nonnull)interactionDelegate { + SampleAdView *adView = [[SampleAdView alloc] initWithFrame:frame]; + + adView.interactionDelegate = interactionDelegate; + adView.loadingDelegate = loadingDelegate; + adView.bid = bid; + + return adView; +} + - (id)createInterstitialControllerWithBid:(Bid *)bid adConfiguration:(AdUnitConfig *)adConfiguration loadingDelegate:(id)loadingDelegate diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift index ab0a6953c..7797e5a37 100644 --- a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayBannerPluginRendererViewController.swift @@ -24,7 +24,7 @@ class InAppDisplayBannerPluginRendererViewController: // Prebid private var prebidBannerView: BannerView! - private let samplePluginRenderer = SampleAdViewRenderer() + private let samplePluginRenderer = SampleRenderer() override func loadView() { super.loadView() diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayInterstitialPluginRendererViewController.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayInterstitialPluginRendererViewController.swift index bbec35413..c4718dc40 100644 --- a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayInterstitialPluginRendererViewController.swift +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/InAppDisplayInterstitialPluginRendererViewController.swift @@ -24,7 +24,7 @@ class InAppDisplayInterstitialPluginRendererViewController: // Prebid private var renderingInterstitial: InterstitialRenderingAdUnit! - private let samplePluginRenderer = SampleInterstitialRenderer() + private let samplePluginRenderer = SampleRenderer() override func loadView() { super.loadView() diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialRenderer.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialRenderer.swift deleted file mode 100644 index f3a8a0ec1..000000000 --- a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleInterstitialRenderer.swift +++ /dev/null @@ -1,46 +0,0 @@ -/*   Copyright 2018-2024 Prebid.org, Inc. - - 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 UIKit -import PrebidMobile - -/// A custom implementation of the interstitial ad renderer. -class SampleInterstitialRenderer: PrebidMobileInterstitialPluginRenderer { - - var name = "SampleInterstitialRenderer" - var version = "1.0.0" - var data: [AnyHashable : Any]? - - func isSupportRendering(for format: PrebidMobile.AdFormat?) -> Bool { - [PrebidMobile.AdFormat.banner, PrebidMobile.AdFormat.video].contains(format) - } - - /// This method creates an instance of `SampleInterstitialController`, - /// a custom controller used to display interstitial ads. - func createInterstitialController( - bid: Bid, - adConfiguration: AdUnitConfig, - loadingDelegate: InterstitialControllerLoadingDelegate, - interactionDelegate: InterstitialControllerInteractionDelegate - ) -> PrebidMobileInterstitialControllerProtocol? { - let interstitialController = SampleInterstitialController() - - interstitialController.loadingDelegate = loadingDelegate - interstitialController.interactionDelegate = interactionDelegate - interstitialController.bid = bid - - return interstitialController - } -} diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleAdViewRenderer.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleRenderer.swift similarity index 63% rename from Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleAdViewRenderer.swift rename to Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleRenderer.swift index 8c4644859..63c73868c 100644 --- a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleAdViewRenderer.swift +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleRenderer.swift @@ -17,9 +17,9 @@ import UIKit import PrebidMobile /// A custom implementation of the ad view renderer. -public class SampleAdViewRenderer: NSObject, PrebidMobileAdViewPluginRenderer { +public class SampleRenderer: NSObject, PrebidMobilePluginRenderer { - public let name = "SampleAdViewRenderer" + public let name = "SampleRenderer" public let version = "1.0.0" public var data: [AnyHashable: Any]? @@ -28,7 +28,7 @@ public class SampleAdViewRenderer: NSObject, PrebidMobileAdViewPluginRenderer { } /// This method creates an instance of `SampleAdView`, which is a custom view used to display the ad. - public func createAdView( + public func createBannerView( with frame: CGRect, bid: Bid, adConfiguration: AdUnitConfig, @@ -43,4 +43,21 @@ public class SampleAdViewRenderer: NSObject, PrebidMobileAdViewPluginRenderer { return adView } + + /// This method creates an instance of `SampleInterstitialController`, + /// a custom controller used to display interstitial ads. + public func createInterstitialController( + bid: Bid, + adConfiguration: AdUnitConfig, + loadingDelegate: InterstitialControllerLoadingDelegate, + interactionDelegate: InterstitialControllerInteractionDelegate + ) -> PrebidMobileInterstitialControllerProtocol? { + let interstitialController = SampleInterstitialController() + + interstitialController.loadingDelegate = loadingDelegate + interstitialController.interactionDelegate = interactionDelegate + interstitialController.bid = bid + + return interstitialController + } } diff --git a/Example/PrebidDemo/PrebidDemoSwiftUITests/BannerAdsTest.swift b/Example/PrebidDemo/PrebidDemoSwiftUITests/BannerAdsTest.swift index f599fdf52..61e9930be 100644 --- a/Example/PrebidDemo/PrebidDemoSwiftUITests/BannerAdsTest.swift +++ b/Example/PrebidDemo/PrebidDemoSwiftUITests/BannerAdsTest.swift @@ -17,11 +17,23 @@ import XCTest class BannerAdsTest: BaseAdsTest { + private var labelText: String? + + override func tearDown() { + labelText = nil + } + public func testInAppBannerAd() { testAd(testCase: testCases.inAppDisplayBannerCase) } + public func testInAppBannerAdCustomRenderer() { + labelText = "Custom Renderer" + testAd(testCase: testCases.inAppDisplayBannerCustomRendererCase) + } + public func testGamOriginalBannerAd() { + labelText = "Test mode" testAd(testCase: testCases.gamOriginalDisplayBannerCase) } @@ -34,11 +46,16 @@ class BannerAdsTest: BaseAdsTest { } override func checkAd(testCase: String) { - XCTAssert(app.webViews.element.waitForExistence(timeout: 10), assertFailedMessage(testCase: testCase,reason: "Banner Web View is not displayed")) - if testCase == testCases.gamOriginalDisplayBannerCase { - XCTAssert(app.staticTexts["Test mode"].waitForExistence(timeout: 10)) + XCTAssert( + app.webViews.element.waitForExistence(timeout: 10), + assertFailedMessage(testCase: testCase,reason: "Banner Web View is not displayed") + ) + + if let labelText { + XCTAssert( + app.staticTexts[labelText].waitForExistence(timeout: 10), + assertFailedMessage(testCase: testCase, reason: "`\(labelText)` is not displayed") + ) } } - - } diff --git a/Example/PrebidDemo/PrebidDemoSwiftUITests/BaseAdsTest.swift b/Example/PrebidDemo/PrebidDemoSwiftUITests/BaseAdsTest.swift index 914a37d02..5c8eba5e9 100644 --- a/Example/PrebidDemo/PrebidDemoSwiftUITests/BaseAdsTest.swift +++ b/Example/PrebidDemo/PrebidDemoSwiftUITests/BaseAdsTest.swift @@ -42,5 +42,4 @@ class BaseAdsTest: XCTestCase { app.searchFields.element.typeText(testCase) app.tables.element(boundBy: 0).cells.element(boundBy: 0).tap() } - } diff --git a/Example/PrebidDemo/PrebidDemoSwiftUITests/InterstitialAdsTest.swift b/Example/PrebidDemo/PrebidDemoSwiftUITests/InterstitialAdsTest.swift index 344557124..5a3e8b062 100644 --- a/Example/PrebidDemo/PrebidDemoSwiftUITests/InterstitialAdsTest.swift +++ b/Example/PrebidDemo/PrebidDemoSwiftUITests/InterstitialAdsTest.swift @@ -17,25 +17,57 @@ import XCTest class InterstitialAdsTest: BaseAdsTest { + private var closeButton: String? + private var labelText: String? + + override func tearDown() { + closeButton = nil + labelText = nil + } + public func testInAppInterstitialAd() { + closeButton = "PBMCloseButton" testAd(testCase: testCases.inAppDisplayInterstitialCase) } + public func testInAppInterstitialAdCustomRenderer() { + labelText = "Custom Renderer" + testAd(testCase: testCases.inAppDisplayInterstitialCustomRendererCase) + } + public func testGamOriginalInterstitialAd() { + closeButton = "Close Advertisement" testAd(testCase: testCases.gamOriginalDisplayInterstitialCase) } public func testGamRenderingInterstitialAd() { + closeButton = "PBMCloseButton" testAd(testCase: testCases.gamDisplayInterstitialCase) } public func testAdMobInterstitialAd() { + closeButton = "PBMCloseButton" testAd(testCase: testCases.adMobDisplayInterstitialCase) } override func checkAd(testCase: String) { - XCTAssert(app.webViews.element.waitForExistence(timeout: 10),assertFailedMessage(testCase: testCase,reason: "Interstitial Web View is not displayed")) - let closeButton = testCase == testCases.gamOriginalDisplayInterstitialCase ? "Close Advertisement" : "PBMCloseButton" - XCTAssert(app.buttons[closeButton].waitForExistence(timeout: 10), assertFailedMessage(testCase: testCase,reason: "Close button is not displayed")) + XCTAssert( + app.webViews.element.waitForExistence(timeout: 10), + assertFailedMessage(testCase: testCase,reason: "Interstitial Web View is not displayed") + ) + + if let closeButton { + XCTAssert( + app.buttons[closeButton].waitForExistence(timeout: 10), + assertFailedMessage(testCase: testCase, reason: "Close button is not displayed") + ) + } + + if let labelText { + XCTAssert( + app.staticTexts[labelText].waitForExistence(timeout: 10), + assertFailedMessage(testCase: testCase, reason: "`\(labelText)` is not displayed") + ) + } } } diff --git a/Example/PrebidDemo/PrebidDemoSwiftUITests/Utils/TestCases.swift b/Example/PrebidDemo/PrebidDemoSwiftUITests/Utils/TestCases.swift index 7c13316bb..a6c20e659 100644 --- a/Example/PrebidDemo/PrebidDemoSwiftUITests/Utils/TestCases.swift +++ b/Example/PrebidDemo/PrebidDemoSwiftUITests/Utils/TestCases.swift @@ -28,9 +28,11 @@ struct TestCases { // In-App Rendering Api let inAppDisplayBannerCase = "In-App Display Banner 320x50" + let inAppDisplayBannerCustomRendererCase = "In-App Display Banner Plugin Renderer 320x50" let inAppNativeCase = "In-App Native" let inAppVideoBannerCase = "In-App Video Banner 300x250" let inAppDisplayInterstitialCase = "In-App Display Interstitial 320x480" + let inAppDisplayInterstitialCustomRendererCase = "In-App Display Interstitial Plugin Renderer 320x480" let inAppVideoInterstitialCase = "In-App Video Interstitial 320x480" let inAppVideoRewardedCase = "In-App Video Rewarded 320x480" diff --git a/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj b/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj index 2588fe3f5..bae98f082 100644 --- a/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj +++ b/InternalTestApp/InternalTestApp.xcodeproj/project.pbxproj @@ -28,16 +28,14 @@ 457FD34BA45C3840CC31A8F5 /* Pods_InternalTestApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C11D97034E668BBFDD0DDCA /* Pods_InternalTestApp.framework */; }; 530E722C292FACB20025B44D /* UIImageView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 530E722B292FACB20025B44D /* UIImageView+Extensions.swift */; }; 53514CE12D08416B00A480C0 /* CustomRendererInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDF2D08416B00A480C0 /* CustomRendererInterstitialController.swift */; }; - 53514CE22D08416B00A480C0 /* SampleAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CD92D08416B00A480C0 /* SampleAdViewRenderer.swift */; }; + 53514CE22D08416B00A480C0 /* SampleRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CD92D08416B00A480C0 /* SampleRenderer.swift */; }; 53514CE32D08416B00A480C0 /* SampleModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDC2D08416B00A480C0 /* SampleModalViewController.swift */; }; - 53514CE42D08416B00A480C0 /* SampleInterstitialRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDB2D08416B00A480C0 /* SampleInterstitialRenderer.swift */; }; 53514CE52D08416B00A480C0 /* SampleInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDA2D08416B00A480C0 /* SampleInterstitialController.swift */; }; 53514CE62D08416B00A480C0 /* SampleAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CD82D08416B00A480C0 /* SampleAdView.swift */; }; 53514CE72D08416B00A480C0 /* CustomRendererBannerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDE2D08416B00A480C0 /* CustomRendererBannerController.swift */; }; 53514CE82D08416B00A480C0 /* CustomRendererInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDF2D08416B00A480C0 /* CustomRendererInterstitialController.swift */; }; - 53514CE92D08416B00A480C0 /* SampleAdViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CD92D08416B00A480C0 /* SampleAdViewRenderer.swift */; }; + 53514CE92D08416B00A480C0 /* SampleRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CD92D08416B00A480C0 /* SampleRenderer.swift */; }; 53514CEA2D08416B00A480C0 /* SampleModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDC2D08416B00A480C0 /* SampleModalViewController.swift */; }; - 53514CEB2D08416B00A480C0 /* SampleInterstitialRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDB2D08416B00A480C0 /* SampleInterstitialRenderer.swift */; }; 53514CEC2D08416B00A480C0 /* SampleInterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDA2D08416B00A480C0 /* SampleInterstitialController.swift */; }; 53514CED2D08416B00A480C0 /* SampleAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CD82D08416B00A480C0 /* SampleAdView.swift */; }; 53514CEE2D08416B00A480C0 /* CustomRendererBannerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CDE2D08416B00A480C0 /* CustomRendererBannerController.swift */; }; @@ -390,9 +388,8 @@ 35F94D171F93F85D00CF46DB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 530E722B292FACB20025B44D /* UIImageView+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageView+Extensions.swift"; sourceTree = ""; }; 53514CD82D08416B00A480C0 /* SampleAdView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAdView.swift; sourceTree = ""; }; - 53514CD92D08416B00A480C0 /* SampleAdViewRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleAdViewRenderer.swift; sourceTree = ""; }; + 53514CD92D08416B00A480C0 /* SampleRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleRenderer.swift; sourceTree = ""; }; 53514CDA2D08416B00A480C0 /* SampleInterstitialController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleInterstitialController.swift; sourceTree = ""; }; - 53514CDB2D08416B00A480C0 /* SampleInterstitialRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleInterstitialRenderer.swift; sourceTree = ""; }; 53514CDC2D08416B00A480C0 /* SampleModalViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleModalViewController.swift; sourceTree = ""; }; 53514CDE2D08416B00A480C0 /* CustomRendererBannerController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomRendererBannerController.swift; sourceTree = ""; }; 53514CDF2D08416B00A480C0 /* CustomRendererInterstitialController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomRendererInterstitialController.swift; sourceTree = ""; }; @@ -716,10 +713,9 @@ 53514CDD2D08416B00A480C0 /* Renderers */ = { isa = PBXGroup; children = ( + 53514CD92D08416B00A480C0 /* SampleRenderer.swift */, 53514CD82D08416B00A480C0 /* SampleAdView.swift */, - 53514CD92D08416B00A480C0 /* SampleAdViewRenderer.swift */, 53514CDA2D08416B00A480C0 /* SampleInterstitialController.swift */, - 53514CDB2D08416B00A480C0 /* SampleInterstitialRenderer.swift */, 53514CDC2D08416B00A480C0 /* SampleModalViewController.swift */, ); path = Renderers; @@ -1638,9 +1634,8 @@ 53ED300C29798104007D13EE /* DummyTableViewCell.swift in Sources */, 53ED300D29798104007D13EE /* AboutViewController.swift in Sources */, 53514CE12D08416B00A480C0 /* CustomRendererInterstitialController.swift in Sources */, - 53514CE22D08416B00A480C0 /* SampleAdViewRenderer.swift in Sources */, + 53514CE22D08416B00A480C0 /* SampleRenderer.swift in Sources */, 53514CE32D08416B00A480C0 /* SampleModalViewController.swift in Sources */, - 53514CE42D08416B00A480C0 /* SampleInterstitialRenderer.swift in Sources */, 53514CE52D08416B00A480C0 /* SampleInterstitialController.swift in Sources */, 53514CE62D08416B00A480C0 /* SampleAdView.swift in Sources */, 53514CE72D08416B00A480C0 /* CustomRendererBannerController.swift in Sources */, @@ -1739,9 +1734,8 @@ 5B8EB5EF22676914003CC15C /* DummyTableViewCell.swift in Sources */, 5B3EEDCB2101D1AF00BAA0C4 /* AboutViewController.swift in Sources */, 53514CE82D08416B00A480C0 /* CustomRendererInterstitialController.swift in Sources */, - 53514CE92D08416B00A480C0 /* SampleAdViewRenderer.swift in Sources */, + 53514CE92D08416B00A480C0 /* SampleRenderer.swift in Sources */, 53514CEA2D08416B00A480C0 /* SampleModalViewController.swift in Sources */, - 53514CEB2D08416B00A480C0 /* SampleInterstitialRenderer.swift in Sources */, 53514CEC2D08416B00A480C0 /* SampleInterstitialController.swift in Sources */, 53514CED2D08416B00A480C0 /* SampleAdView.swift in Sources */, 53514CEE2D08416B00A480C0 /* CustomRendererBannerController.swift in Sources */, diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererBannerController.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererBannerController.swift index 49c719fc7..003fa36fd 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererBannerController.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererBannerController.swift @@ -43,7 +43,7 @@ class CustomRendererBannerController: private let reloadButton = ThreadCheckingButton() private let stopRefreshButton = ThreadCheckingButton() - private let sampleCustomRenderer = SampleAdViewRenderer() + private let sampleCustomRenderer = SampleRenderer() let lastLoadedAdSizeLabel = UILabel() private let configIdLabel = UILabel() diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererInterstitialController.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererInterstitialController.swift index c747ba09e..943c76b34 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererInterstitialController.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/CustomRendererInterstitialController.swift @@ -29,7 +29,7 @@ class CustomRendererInterstitialController: var adFormats: Set? private var interstitialController : InterstitialRenderingAdUnit? - private let sampleCustomRenderer = SampleInterstitialRenderer() + private let sampleCustomRenderer = SampleRenderer() private weak var adapterViewController: AdapterViewController? diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialRenderer.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialRenderer.swift deleted file mode 100644 index 1de6b9230..000000000 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleInterstitialRenderer.swift +++ /dev/null @@ -1,43 +0,0 @@ -/*   Copyright 2018-2024 Prebid.org, Inc. - - 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 UIKit -import PrebidMobile - -class SampleInterstitialRenderer: PrebidMobileInterstitialPluginRenderer { - - var name = "SampleInterstitialRenderer" - var version = "1.0.0" - var data: [AnyHashable : Any]? - - func isSupportRendering(for format: PrebidMobile.AdFormat?) -> Bool { - [AdFormat.banner, AdFormat.video].contains(format) - } - - func createInterstitialController( - bid: Bid, - adConfiguration: AdUnitConfig, - loadingDelegate: InterstitialControllerLoadingDelegate, - interactionDelegate: InterstitialControllerInteractionDelegate - ) -> PrebidMobileInterstitialControllerProtocol? { - let interstitialController = SampleInterstitialController() - - interstitialController.loadingDelegate = loadingDelegate - interstitialController.interactionDelegate = interactionDelegate - interstitialController.bid = bid - - return interstitialController - } -} diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdViewRenderer.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleRenderer.swift similarity index 64% rename from InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdViewRenderer.swift rename to InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleRenderer.swift index 60601f71c..043fa4636 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleAdViewRenderer.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleRenderer.swift @@ -16,9 +16,9 @@ import UIKit import PrebidMobile -public class SampleAdViewRenderer: NSObject, PrebidMobileAdViewPluginRenderer { +public class SampleRenderer: NSObject, PrebidMobilePluginRenderer { - public let name = "SampleAdViewRenderer" + public let name = "SampleRenderer" public let version = "1.0.0" public var data: [AnyHashable: Any]? @@ -26,7 +26,7 @@ public class SampleAdViewRenderer: NSObject, PrebidMobileAdViewPluginRenderer { [AdFormat.banner, AdFormat.video].contains(format) } - public func createAdView( + public func createBannerView( with frame: CGRect, bid: Bid, adConfiguration: AdUnitConfig, @@ -41,4 +41,19 @@ public class SampleAdViewRenderer: NSObject, PrebidMobileAdViewPluginRenderer { return bannerView } + + public func createInterstitialController( + bid: Bid, + adConfiguration: AdUnitConfig, + loadingDelegate: InterstitialControllerLoadingDelegate, + interactionDelegate: InterstitialControllerInteractionDelegate + ) -> PrebidMobileInterstitialControllerProtocol? { + let interstitialController = SampleInterstitialController() + + interstitialController.loadingDelegate = loadingDelegate + interstitialController.interactionDelegate = interactionDelegate + interstitialController.bid = bid + + return interstitialController + } } diff --git a/PrebidMobile.xcodeproj/project.pbxproj b/PrebidMobile.xcodeproj/project.pbxproj index b222617c7..f94dca2e1 100644 --- a/PrebidMobile.xcodeproj/project.pbxproj +++ b/PrebidMobile.xcodeproj/project.pbxproj @@ -104,6 +104,7 @@ 534C61462CB562E40026119A /* CloseActionManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534C61452CB562E40026119A /* CloseActionManagerTests.swift */; }; 535145E02CCB758800D40B19 /* NSObject+PBMExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 535145DF2CCB758800D40B19 /* NSObject+PBMExtensions.m */; }; 535145E12CCB758800D40B19 /* NSObject+PBMExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 535145DE2CCB758800D40B19 /* NSObject+PBMExtensions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 53514CF22D0851DE00A480C0 /* InterstitialControllerInteractionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CF12D0851DE00A480C0 /* InterstitialControllerInteractionDelegate.swift */; }; 53514CC62D01B5B900A480C0 /* InterstitialRenderingAdUnitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CC52D01B5AF00A480C0 /* InterstitialRenderingAdUnitTest.swift */; }; 53514CC82D01B5F900A480C0 /* RewardedAdUnitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CC72D01B5F200A480C0 /* RewardedAdUnitTest.swift */; }; 5355ACA929C454070014F16E /* VAST_with_empty_companion.xml in Resources */ = {isa = PBXBuildFile; fileRef = 5355ACA829C454070014F16E /* VAST_with_empty_companion.xml */; }; @@ -144,7 +145,6 @@ 53BDBF89293F5EFF004B6DE8 /* InternalUserConsentDataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 53BDBF88293F5EFF004B6DE8 /* InternalUserConsentDataManager.m */; }; 53BDBF8A293F605B004B6DE8 /* InternalUserConsentDataManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 53BDBF87293F5EF6004B6DE8 /* InternalUserConsentDataManager.h */; }; 53BDBF8C293F6573004B6DE8 /* InternalUserConsentDataManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BDBF8B293F6573004B6DE8 /* InternalUserConsentDataManagerTests.swift */; }; - 53BFCD0F2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD0E2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift */; }; 53BFCD112CF9156000A3287A /* PrebidMobileInterstitialControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD102CF9155E00A3287A /* PrebidMobileInterstitialControllerProtocol.swift */; }; 53BFCD1F2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 53BFCD1E2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 53BFCD312CFE435D00A3287A /* PrebidMobilePluginRenderer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53BFCD302CFE435D00A3287A /* PrebidMobilePluginRenderer+Extensions.swift */; }; @@ -422,7 +422,6 @@ 5BC379D8271F1D0000444D5E /* PBMDisplayView+InternalState.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BC37788271F1CFE00444D5E /* PBMDisplayView+InternalState.h */; }; 5BC379DB271F1D0000444D5E /* InterstitialControllerLoadingDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3778B271F1CFE00444D5E /* InterstitialControllerLoadingDelegate.swift */; }; 5BC379DC271F1D0000444D5E /* PBMDisplayView.h in Headers */ = {isa = PBXBuildFile; fileRef = 5BC3778C271F1CFE00444D5E /* PBMDisplayView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 5BC379DD271F1D0000444D5E /* InterstitialControllerInteractionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3778D271F1CFE00444D5E /* InterstitialControllerInteractionDelegate.swift */; }; 5BC379DE271F1D0000444D5E /* InterstitialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3778E271F1CFE00444D5E /* InterstitialController.swift */; }; 5BC379DF271F1D0000444D5E /* DisplayViewLoadingDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3778F271F1CFE00444D5E /* DisplayViewLoadingDelegate.swift */; }; 5BC379E0271F1D0000444D5E /* DisplayViewInteractionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC37790271F1CFE00444D5E /* DisplayViewInteractionDelegate.swift */; }; @@ -812,7 +811,7 @@ 9743CB86235F264B002E2CAA /* NativeEventTrackerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9743CB85235F264B002E2CAA /* NativeEventTrackerTests.swift */; }; A908694229E05EAF00B37479 /* PrebidMobilePluginRegister.swift in Sources */ = {isa = PBXBuildFile; fileRef = A908694129E05EAF00B37479 /* PrebidMobilePluginRegister.swift */; }; A908694429E05ED500B37479 /* PrebidMobilePluginRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A908694329E05ED500B37479 /* PrebidMobilePluginRenderer.swift */; }; - A908694629E05F7900B37479 /* PrebidDisplayViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A908694529E05F7900B37479 /* PrebidDisplayViewRenderer.swift */; }; + A908694629E05F7900B37479 /* PrebidRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A908694529E05F7900B37479 /* PrebidRenderer.swift */; }; A9750D7A2ABB9A300066E4E6 /* PluginEventListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9750D792ABB9A300066E4E6 /* PluginEventListener.swift */; }; FA5AD5E42271FA4100C8F274 /* ConstantsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA5AD5E32271FA4100C8F274 /* ConstantsTest.swift */; }; FA9D7F2722E8A83D006FCBEF /* AdViewUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA9D7F2622E8A83D006FCBEF /* AdViewUtilsTests.swift */; }; @@ -998,6 +997,7 @@ 534C61452CB562E40026119A /* CloseActionManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloseActionManagerTests.swift; sourceTree = ""; }; 535145DE2CCB758800D40B19 /* NSObject+PBMExtensions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSObject+PBMExtensions.h"; sourceTree = ""; }; 535145DF2CCB758800D40B19 /* NSObject+PBMExtensions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSObject+PBMExtensions.m"; sourceTree = ""; }; + 53514CF12D0851DE00A480C0 /* InterstitialControllerInteractionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterstitialControllerInteractionDelegate.swift; sourceTree = ""; }; 53514CC52D01B5AF00A480C0 /* InterstitialRenderingAdUnitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterstitialRenderingAdUnitTest.swift; sourceTree = ""; }; 53514CC72D01B5F200A480C0 /* RewardedAdUnitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RewardedAdUnitTest.swift; sourceTree = ""; }; 5355ACA829C454070014F16E /* VAST_with_empty_companion.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = VAST_with_empty_companion.xml; sourceTree = ""; }; @@ -1038,7 +1038,6 @@ 53BDBF87293F5EF6004B6DE8 /* InternalUserConsentDataManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InternalUserConsentDataManager.h; sourceTree = ""; }; 53BDBF88293F5EFF004B6DE8 /* InternalUserConsentDataManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InternalUserConsentDataManager.m; sourceTree = ""; }; 53BDBF8B293F6573004B6DE8 /* InternalUserConsentDataManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalUserConsentDataManagerTests.swift; sourceTree = ""; }; - 53BFCD0E2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidInterstitialControllerRenderer.swift; sourceTree = ""; }; 53BFCD102CF9155E00A3287A /* PrebidMobileInterstitialControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidMobileInterstitialControllerProtocol.swift; sourceTree = ""; }; 53BFCD1E2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrebidMobileDisplayViewProtocol.h; sourceTree = ""; }; 53BFCD302CFE435D00A3287A /* PrebidMobilePluginRenderer+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PrebidMobilePluginRenderer+Extensions.swift"; sourceTree = ""; }; @@ -1318,7 +1317,6 @@ 5BC37788271F1CFE00444D5E /* PBMDisplayView+InternalState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PBMDisplayView+InternalState.h"; sourceTree = ""; }; 5BC3778B271F1CFE00444D5E /* InterstitialControllerLoadingDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InterstitialControllerLoadingDelegate.swift; sourceTree = ""; }; 5BC3778C271F1CFE00444D5E /* PBMDisplayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBMDisplayView.h; sourceTree = ""; }; - 5BC3778D271F1CFE00444D5E /* InterstitialControllerInteractionDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InterstitialControllerInteractionDelegate.swift; sourceTree = ""; }; 5BC3778E271F1CFE00444D5E /* InterstitialController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InterstitialController.swift; sourceTree = ""; }; 5BC3778F271F1CFE00444D5E /* DisplayViewLoadingDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisplayViewLoadingDelegate.swift; sourceTree = ""; }; 5BC37790271F1CFE00444D5E /* DisplayViewInteractionDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisplayViewInteractionDelegate.swift; sourceTree = ""; }; @@ -1738,7 +1736,7 @@ 979177962201AF5F00E624CE /* DispatcherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DispatcherTests.swift; sourceTree = ""; }; A908694129E05EAF00B37479 /* PrebidMobilePluginRegister.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidMobilePluginRegister.swift; sourceTree = ""; }; A908694329E05ED500B37479 /* PrebidMobilePluginRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidMobilePluginRenderer.swift; sourceTree = ""; }; - A908694529E05F7900B37479 /* PrebidDisplayViewRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidDisplayViewRenderer.swift; sourceTree = ""; }; + A908694529E05F7900B37479 /* PrebidRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidRenderer.swift; sourceTree = ""; }; A9750D792ABB9A300066E4E6 /* PluginEventListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PluginEventListener.swift; sourceTree = ""; }; FA4A88432497A99D00FDCBB6 /* Swizzling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Swizzling.swift; sourceTree = ""; }; FA5AD5E32271FA4100C8F274 /* ConstantsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConstantsTest.swift; sourceTree = ""; }; @@ -2002,32 +2000,6 @@ path = CacheManagement; sourceTree = ""; }; - 53BFCD2B2CFE39A700A3287A /* DisplayView */ = { - isa = PBXGroup; - children = ( - 53BFCD1E2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h */, - 5BC3778C271F1CFE00444D5E /* PBMDisplayView.h */, - 5BC37787271F1CFE00444D5E /* PBMDisplayView.m */, - 5BC37788271F1CFE00444D5E /* PBMDisplayView+InternalState.h */, - 5BC3778F271F1CFE00444D5E /* DisplayViewLoadingDelegate.swift */, - 5BC37790271F1CFE00444D5E /* DisplayViewInteractionDelegate.swift */, - A908694529E05F7900B37479 /* PrebidDisplayViewRenderer.swift */, - ); - path = DisplayView; - sourceTree = ""; - }; - 53BFCD2C2CFE39B200A3287A /* InterstitialController */ = { - isa = PBXGroup; - children = ( - 53BFCD102CF9155E00A3287A /* PrebidMobileInterstitialControllerProtocol.swift */, - 5BC3778E271F1CFE00444D5E /* InterstitialController.swift */, - 5BC3778B271F1CFE00444D5E /* InterstitialControllerLoadingDelegate.swift */, - 5BC3778D271F1CFE00444D5E /* InterstitialControllerInteractionDelegate.swift */, - 53BFCD0E2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift */, - ); - path = InterstitialController; - sourceTree = ""; - }; 53CE08FF2AD672980018CB75 /* ORTB-samples */ = { isa = PBXGroup; children = ( @@ -2469,8 +2441,17 @@ 5BC37786271F1CFE00444D5E /* PBMCacheRenderers */ = { isa = PBXGroup; children = ( - 53BFCD2B2CFE39A700A3287A /* DisplayView */, - 53BFCD2C2CFE39B200A3287A /* InterstitialController */, + A908694529E05F7900B37479 /* PrebidRenderer.swift */, + 53BFCD1E2CFDC60100A3287A /* PrebidMobileDisplayViewProtocol.h */, + 5BC3778C271F1CFE00444D5E /* PBMDisplayView.h */, + 5BC37787271F1CFE00444D5E /* PBMDisplayView.m */, + 5BC37788271F1CFE00444D5E /* PBMDisplayView+InternalState.h */, + 5BC3778F271F1CFE00444D5E /* DisplayViewLoadingDelegate.swift */, + 5BC37790271F1CFE00444D5E /* DisplayViewInteractionDelegate.swift */, + 53BFCD102CF9155E00A3287A /* PrebidMobileInterstitialControllerProtocol.swift */, + 5BC3778E271F1CFE00444D5E /* InterstitialController.swift */, + 5BC3778B271F1CFE00444D5E /* InterstitialControllerLoadingDelegate.swift */, + 53514CF12D0851DE00A480C0 /* InterstitialControllerInteractionDelegate.swift */, ); path = PBMCacheRenderers; sourceTree = ""; @@ -4216,7 +4197,6 @@ 5BC37AC8271F1D0100444D5E /* PBMBasicParameterBuilder.m in Sources */, 9298652528058CEB007A2F34 /* MediationNativeUtils.swift in Sources */, 5BC3798F271F1D0000444D5E /* PBMCreativeModel.m in Sources */, - 53BFCD0F2CF912A600A3287A /* PrebidInterstitialControllerRenderer.swift in Sources */, 5BC37A6F271F1D0000444D5E /* PBMORTBAbstractResponse.m in Sources */, 5BC378AD271F1CFF00444D5E /* Targeting.swift in Sources */, 923B55002744F19600E00C88 /* PrebidMediationDelegate.swift in Sources */, @@ -4290,6 +4270,7 @@ FAEE4D12262DC2B200AD9966 /* RewardedVideoAdUnit.swift in Sources */, 5BC3795B271F1D0000444D5E /* PBMVastCreativeCompanionAdsCompanion.m in Sources */, 53A657B02A8B64C200AE0B4F /* PBMORTBSDKConfiguration.m in Sources */, + 53514CF22D0851DE00A480C0 /* InterstitialControllerInteractionDelegate.swift in Sources */, 92C85D5C27A96C680080BAC5 /* NativeImage.swift in Sources */, 5BC37A86271F1D0000444D5E /* BannerView.swift in Sources */, 5BC3796E271F1D0000444D5E /* PBMVastWrapperAd.m in Sources */, @@ -4349,7 +4330,6 @@ 5BC37AB9271F1D0000444D5E /* PBMOpenMeasurementWrapper.m in Sources */, 5BC37A55271F1D0000444D5E /* PBMBidResponseTransformer.m in Sources */, 53F35F6D292B9F2F001C1183 /* UserConsentDataManager.swift in Sources */, - 5BC379DD271F1D0000444D5E /* InterstitialControllerInteractionDelegate.swift in Sources */, 5BC378C3271F1CFF00444D5E /* NSString+PBMExtensions.m in Sources */, 5BC37903271F1CFF00444D5E /* PBMORTBVideo.m in Sources */, 5BC37914271F1CFF00444D5E /* PBMCircularProgressBarView.m in Sources */, @@ -4373,7 +4353,7 @@ 5BC37A8B271F1D0000444D5E /* BannerEventInteractionDelegate.swift in Sources */, FAEE4D0B262DC2B200AD9966 /* Dispatcher.swift in Sources */, 5BC37A10271F1D0000444D5E /* AdUnitConfig.swift in Sources */, - A908694629E05F7900B37479 /* PrebidDisplayViewRenderer.swift in Sources */, + A908694629E05F7900B37479 /* PrebidRenderer.swift in Sources */, 5BC37926271F1CFF00444D5E /* PBMDeepLinkPlusHelper+Testing.m in Sources */, 5BC37A90271F1D0000444D5E /* InterstitialAdUnitDelegate.swift in Sources */, 5BC37A88271F1D0000444D5E /* RewardedAdUnitDelegate.swift in Sources */, diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift index d7b68b105..bc39c234e 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift @@ -28,8 +28,7 @@ public class PrebidMobilePluginRegister: NSObject { private var plugins = [String: PrebidMobilePluginRenderer]() - private let defaultAdViewRenderer = PrebidDisplayViewRenderer() - private let defaultInterstitialRenderer = PrebidInterstitialControllerRenderer() + private let defaultRenderer = PrebidRenderer() private override init() { super.init() @@ -112,21 +111,19 @@ public class PrebidMobilePluginRegister: NSObject { } } - /// Returns the registered renderer according to the preferred renderer name in the bid response - /// If no preferred renderer is found, it returns PrebidRenderer to perform default behavior - /// Once bid is win we want to resolve the best PluginRenderer candidate to render the ad - public func getPluginForPreferredRenderer( - bid: Bid, - isInterstitial: Bool - ) -> PrebidMobilePluginRenderer { - if let preferredRendererName = bid.pluginRendererName, - let preferredPlugin = getPluginRenderer(for: preferredRendererName), - preferredPlugin.version == bid.pluginRendererVersion, - preferredPlugin.isSupportRendering(for: bid.adFormat) { - return preferredPlugin - } else { - return isInterstitial ? defaultInterstitialRenderer : defaultAdViewRenderer + /// Returns the registered renderer according to the preferred renderer name in the bid response. + /// If no preferred renderer is found, it returns PrebidRenderer to perform default behavior. + /// Once bid is win we want to resolve the best PluginRenderer candidate to render the ad. + public func getPluginForPreferredRenderer(bid: Bid) -> PrebidMobilePluginRenderer { + guard let preferredRendererName = bid.pluginRendererName, + let preferredPlugin = getPluginRenderer(for: preferredRendererName), + preferredPlugin.version == bid.pluginRendererVersion, + preferredPlugin.isSupportRendering(for: bid.adFormat) + else { + return defaultRenderer } + + return preferredPlugin } public func getAllPlugins() -> [PrebidMobilePluginRenderer] { diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift index 2db361741..1a3bb4f85 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift @@ -43,15 +43,9 @@ public protocol PrebidMobilePluginRenderer: AnyObject { pluginEventDelegate: PluginEventDelegate, adUnitConfigFingerprint: String ) -} - -/// A protocol for the ad view plugin renderer, extending the base plugin renderer functionality. -/// This protocol is used specifically for the ad views. -@objc -public protocol PrebidMobileAdViewPluginRenderer: PrebidMobilePluginRenderer { /// Creates and returns an ad view conforming to `PrebidMobileDisplayViewManagerProtocol` for a given bid response. - /// Returns nil in the case of an internal error. + /// Returns nil in the case of an internal error or if no renderer is provided. /// /// - Parameters: /// - frame: The frame specifying the initial size and position of the ad view. @@ -59,22 +53,16 @@ public protocol PrebidMobileAdViewPluginRenderer: PrebidMobilePluginRenderer { /// - adConfiguration: The `AdUnitConfig` instance providing configuration details for the ad unit. /// - loadingDelegate: The delegate conforming to `DisplayViewLoadingDelegate` for handling ad loading events. /// - interactionDelegate: The delegate conforming to `DisplayViewInteractionDelegate` for handling ad interaction events. - @objc func createAdView( + @objc func createBannerView( with frame: CGRect, bid: Bid, adConfiguration: AdUnitConfig, loadingDelegate: DisplayViewLoadingDelegate, interactionDelegate: DisplayViewInteractionDelegate ) -> (UIView & PrebidMobileDisplayViewProtocol)? -} - -/// A protocol for a Prebid Mobile interstitial plugin renderer, extending the base plugin renderer functionality. -/// This protocol is used specifically for the interstitials. -@objc -public protocol PrebidMobileInterstitialPluginRenderer: PrebidMobilePluginRenderer { /// Creates and returns an implementation of `PrebidMobileInterstitialControllerProtocol` for a given bid response. - /// Returns nil in the case of an internal error. + /// Returns nil in the case of an internal error or if no renderer is provided. /// /// - Parameters: /// - bid: The `Bid` object containing the bid response used for rendering the interstitial ad. diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m index 6c6d74fc8..5851359d3 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m @@ -33,7 +33,6 @@ @interface PBMBannerAdLoader () @property (nonatomic, weak, nullable, readonly) id delegate; -@property (nonatomic, strong, nullable) id renderer; @end @@ -66,23 +65,17 @@ - (void)createPrebidAdWithBid:(Bid *)bid adObjectSaver:(void (^)(id))adObjectSaver loadMethodInvoker:(void (^)(dispatch_block_t))loadMethodInvoker { - [self setRendererWithBid:bid]; - - if (!self.renderer) { - return; - } - - PBMLogInfo(@"Renderer: %@", self.renderer); + id renderer = [[PrebidMobilePluginRegister shared] getPluginForPreferredRendererWithBid:bid]; + PBMLogInfo(@"Renderer: %@", renderer); CGRect const displayFrame = CGRectMake(0, 0, bid.size.width, bid.size.height); dispatch_async(dispatch_get_main_queue(), ^{ - UIView * newDisplayView = [self.renderer createAdViewWith:displayFrame - bid:bid - adConfiguration:adUnitConfig - loadingDelegate:self - interactionDelegate:self.delegate - ]; + UIView * newDisplayView = [renderer createBannerViewWith:displayFrame + bid:bid + adConfiguration:adUnitConfig + loadingDelegate:self + interactionDelegate:self.delegate]; if (!newDisplayView) { PBMLogError(@"SDK couldn't retrieve an implementation of PrebidMobileDisplayViewManagerProtocol."); @@ -125,15 +118,4 @@ - (void)failedWithError:(nullable NSError *)error { [self.flowDelegate adLoader:self failedWithPrimarySDKError:error]; } -// MARK: - Helpers - -- (void)setRendererWithBid:(Bid *)bid { - id render = [[PrebidMobilePluginRegister shared] getPluginForPreferredRendererWithBid:bid - isInterstitial:false]; - - if ([render conformsToProtocol:@protocol(PrebidMobileAdViewPluginRenderer)]) { - self.renderer = render; - } -} - @end diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m index 33f155c5c..b65ecea6d 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m @@ -31,7 +31,6 @@ @interface PBMInterstitialAdLoader () @property (nonatomic, weak, nullable, readonly) id delegate; -@property (nonatomic, strong, nullable) id renderer; @property (nonatomic, weak, nullable, readonly) id eventHandler; @end @@ -65,19 +64,13 @@ - (void)createPrebidAdWithBid:(Bid *)bid adObjectSaver:(void (^)(id))adObjectSaver loadMethodInvoker:(void (^)(dispatch_block_t))loadMethodInvoker { - [self setRendererWithBid:bid]; + id renderer = [[PrebidMobilePluginRegister shared] getPluginForPreferredRendererWithBid:bid]; + PBMLogInfo(@"Renderer: %@", renderer); - if (!self.renderer) { - return; - } - - PBMLogInfo(@"Renderer: %@", self.renderer); - - id controller = [self.renderer - createInterstitialControllerWithBid:bid - adConfiguration:adUnitConfig - loadingDelegate:self - interactionDelegate:self.delegate]; + id controller = [renderer createInterstitialControllerWithBid:bid + adConfiguration:adUnitConfig + loadingDelegate:self + interactionDelegate:self.delegate]; if (!controller) { PBMLogError(@"SDK couldn't retrieve an implementation of PrebidMobileInterstitialControllerProtocol."); @@ -145,15 +138,4 @@ - (void)failedWithError:(nullable NSError *)error { [self.flowDelegate adLoader:self failedWithPrimarySDKError:error]; } -// MARK: - Helpers - -- (void)setRendererWithBid:(Bid *)bid { - id render = [[PrebidMobilePluginRegister shared] getPluginForPreferredRendererWithBid:bid - isInterstitial:true]; - - if ([render conformsToProtocol:@protocol(PrebidMobileInterstitialPluginRenderer)]) { - self.renderer = render; - } -} - @end diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PrebidDisplayViewRenderer.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PrebidDisplayViewRenderer.swift deleted file mode 100644 index 9ea0efa05..000000000 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PrebidDisplayViewRenderer.swift +++ /dev/null @@ -1,46 +0,0 @@ -/*   Copyright 2018-2024 Prebid.org, Inc. - -  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 UIKit - -public class PrebidDisplayViewRenderer: NSObject, PrebidMobileAdViewPluginRenderer { - - public let name = "PrebidDisplayViewRenderer" - public let version = Prebid.shared.version - public var data: [AnyHashable: Any]? - - public func isSupportRendering(for format: AdFormat?) -> Bool { - [AdFormat.banner, AdFormat.video].contains(format) - } - - public func createAdView( - with frame: CGRect, - bid: Bid, - adConfiguration: AdUnitConfig, - loadingDelegate: DisplayViewLoadingDelegate, - interactionDelegate: DisplayViewInteractionDelegate - ) -> (UIView & PrebidMobileDisplayViewProtocol)? { - let displayView = PBMDisplayView( - frame: frame, - bid: bid, - adConfiguration: adConfiguration - ) - - displayView.interactionDelegate = interactionDelegate - displayView.loadingDelegate = loadingDelegate - - return displayView - } -} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewInteractionDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewInteractionDelegate.swift similarity index 100% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewInteractionDelegate.swift rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewInteractionDelegate.swift diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewLoadingDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewLoadingDelegate.swift similarity index 100% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/DisplayViewLoadingDelegate.swift rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayViewLoadingDelegate.swift diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialController.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController.swift similarity index 100% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialController.swift rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController.swift diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerInteractionDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerInteractionDelegate.swift deleted file mode 100644 index 4d4064b9c..000000000 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerInteractionDelegate.swift +++ /dev/null @@ -1,87 +0,0 @@ -/*   Copyright 2018-2021 Prebid.org, Inc. - - 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 UIKit - -/// A protocol that defines methods for handling user interactions and lifecycle events related to interstitial ads. -@objc -public protocol InterstitialControllerInteractionDelegate: NSObjectProtocol { - - /// Tracks an impression for the specified interstitial ad controller. - /// - /// - Parameters: - /// - forInterstitialController: The interstitial ad controller associated with the impression. - @objc func trackImpression( - forInterstitialController: PrebidMobileInterstitialControllerProtocol - ) - - /// Notifies that the interstitial ad was clicked by the user. - /// - /// - Parameters: - /// - interstitialController: The interstitial ad controller associated with the click. - @objc func interstitialControllerDidClickAd( - _ interstitialController: PrebidMobileInterstitialControllerProtocol - ) - - /// Notifies the delegate that the interstitial ad has been closed by the user. - /// - /// - Parameters: - /// - interstitialController: The interstitial ad controller that was closed. - @objc func interstitialControllerDidCloseAd( - _ interstitialController: PrebidMobileInterstitialControllerProtocol - ) - - /// Notifies the delegate that the user has left the app after interacting with the interstitial ad. - /// - /// - Parameters: - /// - interstitialController: The interstitial ad controller that was displayed when the user left the app. - @objc func interstitialControllerDidLeaveApp( - _ interstitialController: PrebidMobileInterstitialControllerProtocol - ) - - /// Notifies the delegate that the interstitial ad has been displayed to the user. - /// - /// - Parameters: - /// - interstitialController: The interstitial ad controller that displayed the ad. - @objc func interstitialControllerDidDisplay( - _ interstitialController: PrebidMobileInterstitialControllerProtocol - ) - - /// Notifies the delegate that the interstitial ad has completed its presentation. - /// - /// - Parameters: - /// - interstitialController: The interstitial ad controller associated with the completed ad. - @objc func interstitialControllerDidComplete( - _ interstitialController: PrebidMobileInterstitialControllerProtocol - ) - - /// Requests the `UIViewController` to be used for presenting modals from the interstitial ad controller. - /// - /// - Parameters: - /// - fromInterstitialController: The interstitial ad controller requesting the view controller. - @objc func viewControllerForModalPresentation( - fromInterstitialController: PrebidMobileInterstitialControllerProtocol - ) -> UIViewController? - - /// Notifies the delegate when a reward is granted to the user after interacting with a rewarded interstitial ad. - /// - /// - Parameters: - /// - interstitialController: The instance of the interstitial ad controller responsible for managing the ad. - /// - reward: An object containing details about the reward, such as the type and amount. - @objc optional func trackUserReward( - _ interstitialController: PrebidMobileInterstitialControllerProtocol, - _ reward: PrebidReward - ) -} diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerInteractionDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerInteractionDelegate.swift index e81477881..4d4064b9c 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerInteractionDelegate.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerInteractionDelegate.swift @@ -15,18 +15,73 @@ import UIKit +/// A protocol that defines methods for handling user interactions and lifecycle events related to interstitial ads. @objc public protocol InterstitialControllerInteractionDelegate: NSObjectProtocol { - @objc func trackImpression(forInterstitialController: InterstitialControllerProtocol) + /// Tracks an impression for the specified interstitial ad controller. + /// + /// - Parameters: + /// - forInterstitialController: The interstitial ad controller associated with the impression. + @objc func trackImpression( + forInterstitialController: PrebidMobileInterstitialControllerProtocol + ) - @objc func interstitialControllerDidClickAd(_ interstitialController: InterstitialControllerProtocol) - @objc func interstitialControllerDidCloseAd(_ interstitialController: InterstitialControllerProtocol) - @objc func interstitialControllerDidLeaveApp(_ interstitialController: InterstitialControllerProtocol) - @objc func interstitialControllerDidDisplay(_ interstitialController: InterstitialControllerProtocol) - @objc func interstitialControllerDidComplete(_ interstitialController: InterstitialControllerProtocol) + /// Notifies that the interstitial ad was clicked by the user. + /// + /// - Parameters: + /// - interstitialController: The interstitial ad controller associated with the click. + @objc func interstitialControllerDidClickAd( + _ interstitialController: PrebidMobileInterstitialControllerProtocol + ) + + /// Notifies the delegate that the interstitial ad has been closed by the user. + /// + /// - Parameters: + /// - interstitialController: The interstitial ad controller that was closed. + @objc func interstitialControllerDidCloseAd( + _ interstitialController: PrebidMobileInterstitialControllerProtocol + ) + + /// Notifies the delegate that the user has left the app after interacting with the interstitial ad. + /// + /// - Parameters: + /// - interstitialController: The interstitial ad controller that was displayed when the user left the app. + @objc func interstitialControllerDidLeaveApp( + _ interstitialController: PrebidMobileInterstitialControllerProtocol + ) + + /// Notifies the delegate that the interstitial ad has been displayed to the user. + /// + /// - Parameters: + /// - interstitialController: The interstitial ad controller that displayed the ad. + @objc func interstitialControllerDidDisplay( + _ interstitialController: PrebidMobileInterstitialControllerProtocol + ) + + /// Notifies the delegate that the interstitial ad has completed its presentation. + /// + /// - Parameters: + /// - interstitialController: The interstitial ad controller associated with the completed ad. + @objc func interstitialControllerDidComplete( + _ interstitialController: PrebidMobileInterstitialControllerProtocol + ) - @objc func viewControllerForModalPresentation(fromInterstitialController: InterstitialControllerProtocol) -> UIViewController? + /// Requests the `UIViewController` to be used for presenting modals from the interstitial ad controller. + /// + /// - Parameters: + /// - fromInterstitialController: The interstitial ad controller requesting the view controller. + @objc func viewControllerForModalPresentation( + fromInterstitialController: PrebidMobileInterstitialControllerProtocol + ) -> UIViewController? - @objc optional func trackUserReward(_ interstitialController: InterstitialControllerProtocol, _ reward: PrebidReward) + /// Notifies the delegate when a reward is granted to the user after interacting with a rewarded interstitial ad. + /// + /// - Parameters: + /// - interstitialController: The instance of the interstitial ad controller responsible for managing the ad. + /// - reward: An object containing details about the reward, such as the type and amount. + @objc optional func trackUserReward( + _ interstitialController: PrebidMobileInterstitialControllerProtocol, + _ reward: PrebidReward + ) } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerLoadingDelegate.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerLoadingDelegate.swift similarity index 100% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/InterstitialControllerLoadingDelegate.swift rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialControllerLoadingDelegate.swift diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView+InternalState.h b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView+InternalState.h similarity index 100% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView+InternalState.h rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView+InternalState.h diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.h b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.h similarity index 100% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.h rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.h diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.m similarity index 100% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PBMDisplayView.m rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PBMDisplayView.m diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PrebidMobileDisplayViewProtocol.h b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidMobileDisplayViewProtocol.h similarity index 100% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/DisplayView/PrebidMobileDisplayViewProtocol.h rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidMobileDisplayViewProtocol.h diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/PrebidMobileInterstitialControllerProtocol.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidMobileInterstitialControllerProtocol.swift similarity index 100% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/PrebidMobileInterstitialControllerProtocol.swift rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidMobileInterstitialControllerProtocol.swift diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/PrebidInterstitialControllerRenderer.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift similarity index 64% rename from PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/PrebidInterstitialControllerRenderer.swift rename to PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift index 1f85dd4a2..976196479 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/InterstitialController/PrebidInterstitialControllerRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift @@ -13,20 +13,37 @@  limitations under the License.  */ -import Foundation +import UIKit -public class PrebidInterstitialControllerRenderer: - NSObject, - PrebidMobileInterstitialPluginRenderer { +public class PrebidRenderer: NSObject, PrebidMobilePluginRenderer { - public var name = "PrebidInterstitialControllerRenderer" - public var version = "1.0.0" + public let name = "PrebidRenderer" + public let version = Prebid.shared.version public var data: [AnyHashable: Any]? public func isSupportRendering(for format: AdFormat?) -> Bool { [AdFormat.banner, AdFormat.video].contains(format) } + public func createBannerView( + with frame: CGRect, + bid: Bid, + adConfiguration: AdUnitConfig, + loadingDelegate: DisplayViewLoadingDelegate, + interactionDelegate: DisplayViewInteractionDelegate + ) -> (UIView & PrebidMobileDisplayViewProtocol)? { + let displayView = PBMDisplayView( + frame: frame, + bid: bid, + adConfiguration: adConfiguration + ) + + displayView.interactionDelegate = interactionDelegate + displayView.loadingDelegate = loadingDelegate + + return displayView + } + public func createInterstitialController( bid: Bid, adConfiguration: AdUnitConfig, From 2c7c89ea02beeab0967b63344c7582a1143e09e7 Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Tue, 10 Dec 2024 14:41:42 +0200 Subject: [PATCH 14/18] feat: change data property type & use default banner view if none provided --- .../SampleRenderers/SampleRenderer.swift | 2 +- .../Renderers/SampleRenderer.swift | 2 +- .../PrebidMobilePluginRenderer.swift | 5 +- .../GAM/AdLoading/PBMBannerAdLoader.m | 48 +++++++++++------- .../GAM/AdLoading/PBMInterstitialAdLoader.m | 49 ++++++++++++------- .../PBMCacheRenderers/PrebidRenderer.swift | 2 +- .../MockPrebidMobilePluginRenderer.swift | 27 +++++++--- .../Tests/Prebid/PluginRegisterTest.swift | 5 +- 8 files changed, 90 insertions(+), 50 deletions(-) diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleRenderer.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleRenderer.swift index 63c73868c..bf07975d8 100644 --- a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleRenderer.swift +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleRenderer.swift @@ -21,7 +21,7 @@ public class SampleRenderer: NSObject, PrebidMobilePluginRenderer { public let name = "SampleRenderer" public let version = "1.0.0" - public var data: [AnyHashable: Any]? + public var data: [String: Any]? public func isSupportRendering(for format: PrebidMobile.AdFormat?) -> Bool { [PrebidMobile.AdFormat.banner, PrebidMobile.AdFormat.video].contains(format) diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleRenderer.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleRenderer.swift index 043fa4636..79b1e6a7e 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleRenderer.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleRenderer.swift @@ -20,7 +20,7 @@ public class SampleRenderer: NSObject, PrebidMobilePluginRenderer { public let name = "SampleRenderer" public let version = "1.0.0" - public var data: [AnyHashable: Any]? + public var data: [String: Any]? public func isSupportRendering(for format: AdFormat?) -> Bool { [AdFormat.banner, AdFormat.video].contains(format) diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift index 1a3bb4f85..d5b7ddd75 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift @@ -16,7 +16,8 @@ import UIKit /// A protocol for the plugin renderer, defining the basic interface that any renderer should implement. -/// This protocol provides the ability to retrieve plugin details, support rendering formats, and manage event delegates. +/// This protocol provides the ability to retrieve plugin details, support rendering formats, and manage event delegates and +/// methods for creating custom banner view and insterstitial controller. @objc public protocol PrebidMobilePluginRenderer: AnyObject { @@ -27,7 +28,7 @@ public protocol PrebidMobilePluginRenderer: AnyObject { @objc var version: String { get } /// The version of the plugin renderer. - @objc var data: [AnyHashable: Any]? { get } + @objc var data: [String: Any]? { get } /// Returns true only if the given ad unit could be renderer by the plugin. @objc func isSupportRendering(for format: AdFormat?) -> Bool diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m index 5851359d3..eb5478dc7 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m @@ -64,28 +64,14 @@ - (void)createPrebidAdWithBid:(Bid *)bid adUnitConfig:(AdUnitConfig *)adUnitConfig adObjectSaver:(void (^)(id))adObjectSaver loadMethodInvoker:(void (^)(dispatch_block_t))loadMethodInvoker { - - id renderer = [[PrebidMobilePluginRegister shared] getPluginForPreferredRendererWithBid:bid]; - PBMLogInfo(@"Renderer: %@", renderer); - - CGRect const displayFrame = CGRectMake(0, 0, bid.size.width, bid.size.height); - dispatch_async(dispatch_get_main_queue(), ^{ - UIView * newDisplayView = [renderer createBannerViewWith:displayFrame - bid:bid - adConfiguration:adUnitConfig - loadingDelegate:self - interactionDelegate:self.delegate]; - - if (!newDisplayView) { - PBMLogError(@"SDK couldn't retrieve an implementation of PrebidMobileDisplayViewManagerProtocol."); - return; - } + UIView * displayView = [self createBannerViewWithBid:bid + adUnitConfig:adUnitConfig]; - adObjectSaver(newDisplayView); + adObjectSaver(displayView); loadMethodInvoker(^{ - [newDisplayView loadAd]; + [displayView loadAd]; }); }); } @@ -118,4 +104,30 @@ - (void)failedWithError:(nullable NSError *)error { [self.flowDelegate adLoader:self failedWithPrimarySDKError:error]; } +- (UIView *)createBannerViewWithBid:(Bid *)bid adUnitConfig:(AdUnitConfig *)adUnitConfig { + id renderer = [[PrebidMobilePluginRegister shared] getPluginForPreferredRendererWithBid:bid]; + PBMLogInfo(@"Renderer: %@", renderer); + + CGRect const displayFrame = CGRectMake(0, 0, bid.size.width, bid.size.height); + + UIView * displayView = [renderer createBannerViewWith:displayFrame + bid:bid + adConfiguration:adUnitConfig + loadingDelegate:self + interactionDelegate:self.delegate]; + + if (displayView) { + return displayView; + } + + PBMLogWarn(@"SDK couldn't retrieve an implementation of PrebidMobileDisplayViewManagerProtocol. SDK will use the default one."); + + PrebidRenderer *defaultRenderer = [PrebidRenderer new]; + return [defaultRenderer createBannerViewWith:displayFrame + bid:bid + adConfiguration:adUnitConfig + loadingDelegate:self + interactionDelegate:self.delegate]; +} + @end diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m index b65ecea6d..65b5b688c 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m @@ -63,24 +63,14 @@ - (void)createPrebidAdWithBid:(Bid *)bid adUnitConfig:(AdUnitConfig *)adUnitConfig adObjectSaver:(void (^)(id))adObjectSaver loadMethodInvoker:(void (^)(dispatch_block_t))loadMethodInvoker { - - id renderer = [[PrebidMobilePluginRegister shared] getPluginForPreferredRendererWithBid:bid]; - PBMLogInfo(@"Renderer: %@", renderer); - - id controller = [renderer createInterstitialControllerWithBid:bid - adConfiguration:adUnitConfig - loadingDelegate:self - interactionDelegate:self.delegate]; - - if (!controller) { - PBMLogError(@"SDK couldn't retrieve an implementation of PrebidMobileInterstitialControllerProtocol."); - return; - } - - adObjectSaver(controller); - - loadMethodInvoker(^{ - [controller loadAd]; + dispatch_async(dispatch_get_main_queue(), ^{ + id controller = [self createInterstitialControllerWithBid:bid + adUnitConfig:adUnitConfig]; + adObjectSaver(controller); + + loadMethodInvoker(^{ + [controller loadAd]; + }); }); } @@ -138,4 +128,27 @@ - (void)failedWithError:(nullable NSError *)error { [self.flowDelegate adLoader:self failedWithPrimarySDKError:error]; } +- (id)createInterstitialControllerWithBid:(Bid *)bid + adUnitConfig:(AdUnitConfig *)adUnitConfig { + id renderer = [[PrebidMobilePluginRegister shared] getPluginForPreferredRendererWithBid:bid]; + PBMLogInfo(@"Renderer: %@", renderer); + + id controller = [renderer createInterstitialControllerWithBid:bid + adConfiguration:adUnitConfig + loadingDelegate:self + interactionDelegate:self.delegate]; + + if (controller) { + return controller; + } + + PBMLogWarn(@"SDK couldn't retrieve an implementation of PrebidMobileInterstitialControllerProtocol. SDK will use the default one."); + + PrebidRenderer *defaultRenderer = [PrebidRenderer new]; + return [defaultRenderer createInterstitialControllerWithBid:bid + adConfiguration:adUnitConfig + loadingDelegate:self + interactionDelegate:self.delegate]; +} + @end diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift index 976196479..f73842492 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift @@ -19,7 +19,7 @@ public class PrebidRenderer: NSObject, PrebidMobilePluginRenderer { public let name = "PrebidRenderer" public let version = Prebid.shared.version - public var data: [AnyHashable: Any]? + public var data: [String: Any]? public func isSupportRendering(for format: AdFormat?) -> Bool { [AdFormat.banner, AdFormat.video].contains(format) diff --git a/PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift b/PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift index 29823c203..0a1110d65 100644 --- a/PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift +++ b/PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift @@ -20,14 +20,10 @@ class MockPrebidMobilePluginRenderer: PrebidMobilePluginRenderer { let name: String let version: String - var data: [AnyHashable: Any]? + var data: [String: Any]? var formats: Set = [] - init( - name: String, - version: String, - data: [AnyHashable: Any]? = nil - ) { + init(name: String, version: String, data: [String: Any]? = nil) { self.name = name self.version = version self.data = data @@ -48,4 +44,23 @@ class MockPrebidMobilePluginRenderer: PrebidMobilePluginRenderer { json["data"] = data return json } + + func createBannerView( + with frame: CGRect, + bid: Bid, + adConfiguration: AdUnitConfig, + loadingDelegate: any DisplayViewLoadingDelegate, + interactionDelegate: any DisplayViewInteractionDelegate + ) -> (any UIView & PrebidMobileDisplayViewProtocol)? { + return nil + } + + func createInterstitialController( + bid: Bid, + adConfiguration: AdUnitConfig, + loadingDelegate: any InterstitialControllerLoadingDelegate, + interactionDelegate: any InterstitialControllerInteractionDelegate + ) -> (any PrebidMobileInterstitialControllerProtocol)? { + return nil + } } diff --git a/PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift b/PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift index d7dce5eff..1fef8dfa1 100644 --- a/PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift +++ b/PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift @@ -57,7 +57,7 @@ class PluginRegisterTest: XCTestCase { } func testGetPluginForBidContainingSampleCustomRenderer() { - let bidResponse = Bid( + let bid = Bid( bid: RawSampleCustomRendererBidFabricator.makeSampleCustomRendererBid( rendererName: "MockPrebidMobilePluginRenderer", rendererVersion: "1.0.0" @@ -65,8 +65,7 @@ class PluginRegisterTest: XCTestCase { ) let pluginRenderer = prebidMobilePluginRegister.getPluginForPreferredRenderer( - bid: bidResponse, - isInterstitial: false + bid: bid ) XCTAssertEqual(pluginRenderer.name, plugin.name) From 00ea8db0e8a1b5d238b69fc17af1bd5d227b3d7f Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Tue, 10 Dec 2024 15:29:36 +0200 Subject: [PATCH 15/18] feat: remove isSupportRendering --- .../InApp/SampleRenderers/SampleRenderer.h | 2 +- .../InApp/SampleRenderers/SampleRenderer.m | 4 ---- .../SampleRenderers/SampleRenderer.swift | 6 +----- .../Renderers/SampleRenderer.swift | 4 ---- .../PrebidMobilePluginRegister.swift | 16 +-------------- .../PrebidMobilePluginRenderer.swift | 5 +---- .../GAM/AdLoading/PBMBannerAdLoader.m | 4 ++++ .../GAM/AdLoading/PBMInterstitialAdLoader.m | 4 ++++ .../PBMCacheRenderers/PrebidRenderer.swift | 4 ---- .../MockPrebidMobilePluginRenderer.swift | 10 ---------- .../Tests/Prebid/PluginRegisterTest.swift | 20 ------------------- 11 files changed, 12 insertions(+), 67 deletions(-) diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleRenderer.h b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleRenderer.h index 90922a159..754d39b99 100644 --- a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleRenderer.h +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleRenderer.h @@ -21,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN -/// A custom implementation of the ad view renderer. +/// A custom implementation of the renderer. @interface SampleRenderer : NSObject - (instancetype)init; diff --git a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleRenderer.m b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleRenderer.m index 5888717bc..d612efaab 100644 --- a/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleRenderer.m +++ b/Example/PrebidDemo/PrebidDemoObjectiveC/Examples/InApp/SampleRenderers/SampleRenderer.m @@ -30,10 +30,6 @@ - (instancetype)init { return self; } -- (BOOL)isSupportRenderingFor:(AdFormat *)format { - return [@[AdFormat.banner, AdFormat.video] containsObject:format]; -} - - (UIView * _Nullable)createBannerViewWith:(CGRect)frame bid:(Bid * _Nonnull)bid adConfiguration:(AdUnitConfig * _Nonnull)adConfiguration diff --git a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleRenderer.swift b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleRenderer.swift index bf07975d8..9c1d5a41a 100644 --- a/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleRenderer.swift +++ b/Example/PrebidDemo/PrebidDemoSwift/Examples/In-App/SampleRenderers/SampleRenderer.swift @@ -16,17 +16,13 @@ import UIKit import PrebidMobile -/// A custom implementation of the ad view renderer. +/// A custom implementation of the renderer. public class SampleRenderer: NSObject, PrebidMobilePluginRenderer { public let name = "SampleRenderer" public let version = "1.0.0" public var data: [String: Any]? - public func isSupportRendering(for format: PrebidMobile.AdFormat?) -> Bool { - [PrebidMobile.AdFormat.banner, PrebidMobile.AdFormat.video].contains(format) - } - /// This method creates an instance of `SampleAdView`, which is a custom view used to display the ad. public func createBannerView( with frame: CGRect, diff --git a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleRenderer.swift b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleRenderer.swift index 79b1e6a7e..15f4378c6 100644 --- a/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleRenderer.swift +++ b/InternalTestApp/PrebidMobileDemoRendering/ViewControllers/Adapters/Prebid/OpenX/CustomRenderer/Renderers/SampleRenderer.swift @@ -22,10 +22,6 @@ public class SampleRenderer: NSObject, PrebidMobilePluginRenderer { public let version = "1.0.0" public var data: [String: Any]? - public func isSupportRendering(for format: AdFormat?) -> Bool { - [AdFormat.banner, AdFormat.video].contains(format) - } - public func createBannerView( with frame: CGRect, bid: Bid, diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift index bc39c234e..e9c9ba765 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift @@ -98,27 +98,13 @@ public class PrebidMobilePluginRegister: NSObject { } } - /// Returns the list of available renderers for the given ad unit for RTB request - public func getRTBListOfRenderersFor(for adUnitConfig: AdUnitConfig) -> [PrebidMobilePluginRenderer] { - queue.sync { - plugins - .values - .filter { renderer in - adUnitConfig.adFormats.contains { format in - renderer.isSupportRendering(for: format) - } - } - } - } - /// Returns the registered renderer according to the preferred renderer name in the bid response. /// If no preferred renderer is found, it returns PrebidRenderer to perform default behavior. /// Once bid is win we want to resolve the best PluginRenderer candidate to render the ad. public func getPluginForPreferredRenderer(bid: Bid) -> PrebidMobilePluginRenderer { guard let preferredRendererName = bid.pluginRendererName, let preferredPlugin = getPluginRenderer(for: preferredRendererName), - preferredPlugin.version == bid.pluginRendererVersion, - preferredPlugin.isSupportRendering(for: bid.adFormat) + preferredPlugin.version == bid.pluginRendererVersion else { return defaultRenderer } diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift index d5b7ddd75..65e708ad6 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRenderer.swift @@ -27,12 +27,9 @@ public protocol PrebidMobilePluginRenderer: AnyObject { /// The version of the plugin renderer. @objc var version: String { get } - /// The version of the plugin renderer. + /// Custom data to be included in the ORTB request. @objc var data: [String: Any]? { get } - /// Returns true only if the given ad unit could be renderer by the plugin. - @objc func isSupportRendering(for format: AdFormat?) -> Bool - /// Register a listener related to a specific ad unit config fingerprint in order to dispatch specific ad events. @objc optional func registerEventDelegate( pluginEventDelegate: PluginEventDelegate, diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m index eb5478dc7..d617f8758 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m @@ -64,7 +64,11 @@ - (void)createPrebidAdWithBid:(Bid *)bid adUnitConfig:(AdUnitConfig *)adUnitConfig adObjectSaver:(void (^)(id))adObjectSaver loadMethodInvoker:(void (^)(dispatch_block_t))loadMethodInvoker { + @weakify(self); dispatch_async(dispatch_get_main_queue(), ^{ + @strongify(self); + if (!self) { return; } + UIView * displayView = [self createBannerViewWithBid:bid adUnitConfig:adUnitConfig]; diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m index 65b5b688c..b18fa19f5 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m @@ -63,7 +63,11 @@ - (void)createPrebidAdWithBid:(Bid *)bid adUnitConfig:(AdUnitConfig *)adUnitConfig adObjectSaver:(void (^)(id))adObjectSaver loadMethodInvoker:(void (^)(dispatch_block_t))loadMethodInvoker { + @weakify(self); dispatch_async(dispatch_get_main_queue(), ^{ + @strongify(self); + if (!self) { return; } + id controller = [self createInterstitialControllerWithBid:bid adUnitConfig:adUnitConfig]; adObjectSaver(controller); diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift index f73842492..576ac2797 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift @@ -21,10 +21,6 @@ public class PrebidRenderer: NSObject, PrebidMobilePluginRenderer { public let version = Prebid.shared.version public var data: [String: Any]? - public func isSupportRendering(for format: AdFormat?) -> Bool { - [AdFormat.banner, AdFormat.video].contains(format) - } - public func createBannerView( with frame: CGRect, bid: Bid, diff --git a/PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift b/PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift index 0a1110d65..9c7429d45 100644 --- a/PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift +++ b/PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift @@ -29,16 +29,6 @@ class MockPrebidMobilePluginRenderer: PrebidMobilePluginRenderer { self.data = data } - func isSupportRendering(for format: AdFormat?) -> Bool { - guard !formats.isEmpty else { return true } - - if let format { - return formats.contains(format) - } else { - return true - } - } - func jsonDictionary() -> [String: Any] { var json: [String: Any] = ["name": name, "version": version] json["data"] = data diff --git a/PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift b/PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift index 1fef8dfa1..ed01268e2 100644 --- a/PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift +++ b/PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift @@ -71,24 +71,4 @@ class PluginRegisterTest: XCTestCase { XCTAssertEqual(pluginRenderer.name, plugin.name) XCTAssertEqual(pluginRenderer.version, plugin.version) } - - func testGetRTBListOfRenderersFor() { - plugin.formats = [.banner, .video] - - let adUnitConfigBanner = AdUnitConfig( - configId: "configID", - size: CGSize(width: 300, height: 250) - ) - - var renderers = prebidMobilePluginRegister - .getRTBListOfRenderersFor(for: adUnitConfigBanner) - XCTAssertEqual(1, renderers.count) - - let adUnitConfigError = AdUnitConfig(configId: "configID") - adUnitConfigError.adFormats = [.native] - - renderers = prebidMobilePluginRegister - .getRTBListOfRenderersFor(for: adUnitConfigError) - XCTAssertEqual(0, renderers.count) - } } From 4779cd0f2591378ddd22d63e8b2ce6bd5fc69c9c Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Tue, 17 Dec 2024 15:02:09 +0200 Subject: [PATCH 16/18] feat: store SDK renderer in plugin array & register plugin during SDK initialization --- .../PrebidSDKInitializer.swift | 3 +++ .../PrebidMobilePluginRegister.swift | 18 +++++++++++------- .../GAM/AdLoading/PBMBannerAdLoader.m | 14 +++++++------- .../GAM/AdLoading/PBMInterstitialAdLoader.m | 12 ++++++------ .../PBMCacheRenderers/PrebidRenderer.swift | 4 +++- .../Mocks/MockPrebidMobilePluginRenderer.swift | 1 - .../Tests/Prebid/PluginRegisterTest.swift | 1 - .../RenderingTests/Tests/PrebidTest.swift | 10 ++++++++++ 8 files changed, 40 insertions(+), 23 deletions(-) diff --git a/PrebidMobile/ConfigurationAndTargeting/PrebidSDKInitializer.swift b/PrebidMobile/ConfigurationAndTargeting/PrebidSDKInitializer.swift index 04781787e..b77c222af 100644 --- a/PrebidMobile/ConfigurationAndTargeting/PrebidSDKInitializer.swift +++ b/PrebidMobile/ConfigurationAndTargeting/PrebidSDKInitializer.swift @@ -28,7 +28,10 @@ class PrebidSDKInitializer { let _ = UserConsentDataManager.shared PrebidJSLibraryManager.shared.downloadLibraries() + serverStatusRequester.requestStatus { completion?($0, $1) } + + Prebid.registerPluginRenderer(PrebidRenderer()) } // check for deprecated `GADMobileAds.sdkVersion` diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift index e9c9ba765..117b74189 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift @@ -21,6 +21,11 @@ public class PrebidMobilePluginRegister: NSObject { public static let shared = PrebidMobilePluginRegister() + /// Default PrebidMobile SDK renderer + public var sdkRenderer: PrebidMobilePluginRenderer { + getPluginRenderer(for: PREBID_MOBILE_RENDERER_NAME) ?? PrebidRenderer() + } + private let queue = DispatchQueue( label: "PrebidMobilePluginRegisterQueue", attributes: .concurrent @@ -28,8 +33,6 @@ public class PrebidMobilePluginRegister: NSObject { private var plugins = [String: PrebidMobilePluginRenderer]() - private let defaultRenderer = PrebidRenderer() - private override init() { super.init() } @@ -60,10 +63,6 @@ public class PrebidMobilePluginRegister: NSObject { } } - private func getPluginRenderer(for key: String) -> PrebidMobilePluginRenderer? { - queue.sync { plugins[key] } - } - /// Register event delegate public func registerEventDelegate( _ pluginEventDelegate: PluginEventDelegate, @@ -106,7 +105,7 @@ public class PrebidMobilePluginRegister: NSObject { let preferredPlugin = getPluginRenderer(for: preferredRendererName), preferredPlugin.version == bid.pluginRendererVersion else { - return defaultRenderer + return sdkRenderer } return preferredPlugin @@ -122,6 +121,11 @@ public class PrebidMobilePluginRegister: NSObject { return PrebidMobilePluginRegister .shared .getAllPlugins() + .filter({ $0.name != PREBID_MOBILE_RENDERER_NAME }) .map { $0.jsonDictionary() } } + + private func getPluginRenderer(for key: String) -> PrebidMobilePluginRenderer? { + queue.sync { plugins[key] } + } } diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m index d617f8758..184ec77c4 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMBannerAdLoader.m @@ -124,14 +124,14 @@ - (void)failedWithError:(nullable NSError *)error { return displayView; } - PBMLogWarn(@"SDK couldn't retrieve an implementation of PrebidMobileDisplayViewManagerProtocol. SDK will use the default one."); + PBMLogWarn(@"SDK couldn't retrieve an implementation of PrebidMobileDisplayViewManagerProtocol. SDK will use the PrebidMobile SDK renderer."); - PrebidRenderer *defaultRenderer = [PrebidRenderer new]; - return [defaultRenderer createBannerViewWith:displayFrame - bid:bid - adConfiguration:adUnitConfig - loadingDelegate:self - interactionDelegate:self.delegate]; + id sdkRenderer = PrebidMobilePluginRegister.shared.sdkRenderer; + return [sdkRenderer createBannerViewWith:displayFrame + bid:bid + adConfiguration:adUnitConfig + loadingDelegate:self + interactionDelegate:self.delegate]; } @end diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m index b18fa19f5..a20cd9898 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m +++ b/PrebidMobile/PrebidMobileRendering/Prebid/Integrations/GAM/AdLoading/PBMInterstitialAdLoader.m @@ -146,13 +146,13 @@ - (void)failedWithError:(nullable NSError *)error { return controller; } - PBMLogWarn(@"SDK couldn't retrieve an implementation of PrebidMobileInterstitialControllerProtocol. SDK will use the default one."); + PBMLogWarn(@"SDK couldn't retrieve an implementation of PrebidMobileInterstitialControllerProtocol. SDK will use the PrebidMobile SDK renderer."); - PrebidRenderer *defaultRenderer = [PrebidRenderer new]; - return [defaultRenderer createInterstitialControllerWithBid:bid - adConfiguration:adUnitConfig - loadingDelegate:self - interactionDelegate:self.delegate]; + id sdkRenderer = PrebidMobilePluginRegister.shared.sdkRenderer; + return [sdkRenderer createInterstitialControllerWithBid:bid + adConfiguration:adUnitConfig + loadingDelegate:self + interactionDelegate:self.delegate]; } @end diff --git a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift index 576ac2797..092c8d313 100644 --- a/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift +++ b/PrebidMobile/PrebidMobileRendering/Prebid/PBMCacheRenderers/PrebidRenderer.swift @@ -15,9 +15,11 @@ import UIKit +public let PREBID_MOBILE_RENDERER_NAME = "PrebidRenderer" + public class PrebidRenderer: NSObject, PrebidMobilePluginRenderer { - public let name = "PrebidRenderer" + public let name = PREBID_MOBILE_RENDERER_NAME public let version = Prebid.shared.version public var data: [String: Any]? diff --git a/PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift b/PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift index 9c7429d45..357878644 100644 --- a/PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift +++ b/PrebidMobileTests/RenderingTests/Mocks/MockPrebidMobilePluginRenderer.swift @@ -21,7 +21,6 @@ class MockPrebidMobilePluginRenderer: PrebidMobilePluginRenderer { let name: String let version: String var data: [String: Any]? - var formats: Set = [] init(name: String, version: String, data: [String: Any]? = nil) { self.name = name diff --git a/PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift b/PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift index ed01268e2..7fd848b08 100644 --- a/PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift +++ b/PrebidMobileTests/RenderingTests/Tests/Prebid/PluginRegisterTest.swift @@ -39,7 +39,6 @@ class PluginRegisterTest: XCTestCase { super.setUp() prebidMobilePluginRegister.unregisterAllPlugins() prebidMobilePluginRegister.registerPlugin(plugin) - plugin.formats = [] } func testRegisterPlugin() { diff --git a/PrebidMobileTests/RenderingTests/Tests/PrebidTest.swift b/PrebidMobileTests/RenderingTests/Tests/PrebidTest.swift index 5f9fdfb91..8521f47ae 100644 --- a/PrebidMobileTests/RenderingTests/Tests/PrebidTest.swift +++ b/PrebidMobileTests/RenderingTests/Tests/PrebidTest.swift @@ -33,6 +33,7 @@ class PrebidTest: XCTestCase { sdkConfiguration = nil Prebid.reset() + PrebidMobilePluginRegister.shared.unregisterAllPlugins() super.tearDown() } @@ -329,6 +330,15 @@ class PrebidTest: XCTestCase { XCTAssertEqual(Prebid.shared.creativeFactoryTimeoutPreRenderContent, creativeFactoryTimeoutPreRenderContent) } + func testRegisterSDKRenderer() { + XCTAssertTrue(PrebidMobilePluginRegister.shared.getAllPlugins().isEmpty) + + Prebid.initializeSDK() + + XCTAssertTrue(PrebidMobilePluginRegister.shared.getAllPlugins().count == 1) + XCTAssertTrue(PrebidMobilePluginRegister.shared.getAllPlugins().first?.name == PREBID_MOBILE_RENDERER_NAME) + } + // MARK: - Private Methods private func checkInitialValue(sdkConfiguration: Prebid, file: StaticString = #file, line: UInt = #line) { From 7e8c7f58c66bc6d74317c9867836d0baab5375ee Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Tue, 17 Dec 2024 15:18:10 +0200 Subject: [PATCH 17/18] feat: restore .xcodeproj --- PrebidMobile.xcodeproj/project.pbxproj | 67 +++++++++++++++----------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/PrebidMobile.xcodeproj/project.pbxproj b/PrebidMobile.xcodeproj/project.pbxproj index f94dca2e1..7786849be 100644 --- a/PrebidMobile.xcodeproj/project.pbxproj +++ b/PrebidMobile.xcodeproj/project.pbxproj @@ -104,9 +104,9 @@ 534C61462CB562E40026119A /* CloseActionManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534C61452CB562E40026119A /* CloseActionManagerTests.swift */; }; 535145E02CCB758800D40B19 /* NSObject+PBMExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 535145DF2CCB758800D40B19 /* NSObject+PBMExtensions.m */; }; 535145E12CCB758800D40B19 /* NSObject+PBMExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 535145DE2CCB758800D40B19 /* NSObject+PBMExtensions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 53514CF22D0851DE00A480C0 /* InterstitialControllerInteractionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CF12D0851DE00A480C0 /* InterstitialControllerInteractionDelegate.swift */; }; 53514CC62D01B5B900A480C0 /* InterstitialRenderingAdUnitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CC52D01B5AF00A480C0 /* InterstitialRenderingAdUnitTest.swift */; }; 53514CC82D01B5F900A480C0 /* RewardedAdUnitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CC72D01B5F200A480C0 /* RewardedAdUnitTest.swift */; }; + 53514CF22D0851DE00A480C0 /* InterstitialControllerInteractionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53514CF12D0851DE00A480C0 /* InterstitialControllerInteractionDelegate.swift */; }; 5355ACA929C454070014F16E /* VAST_with_empty_companion.xml in Resources */ = {isa = PBXBuildFile; fileRef = 5355ACA829C454070014F16E /* VAST_with_empty_companion.xml */; }; 5355ACAB29C454770014F16E /* CreativeModelCollectionMakerVASTTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5355ACAA29C454770014F16E /* CreativeModelCollectionMakerVASTTests.swift */; }; 536A39262A84C50F00B1CCEA /* StringExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536A39252A84C50F00B1CCEA /* StringExtensionsTest.swift */; }; @@ -153,6 +153,11 @@ 53C925022990FB30009E6F94 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C925012990FB30009E6F94 /* String+Extensions.swift */; }; 53C925052990FBFB009E6F94 /* PrebidServerStatusRequester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C925042990FBFB009E6F94 /* PrebidServerStatusRequester.swift */; }; 53C9250729915466009E6F94 /* PrebidServerStatusRequesterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C9250629915466009E6F94 /* PrebidServerStatusRequesterTests.swift */; }; + 53CDA48D2D11AFD5004766F8 /* MediationBannerAdUnitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53CDA4872D11AFD5004766F8 /* MediationBannerAdUnitTest.swift */; }; + 53CDA48E2D11AFD5004766F8 /* MockMediationUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53CDA48B2D11AFD5004766F8 /* MockMediationUtils.swift */; }; + 53CDA48F2D11AFD5004766F8 /* MediationInterstitialAdUnitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53CDA4882D11AFD5004766F8 /* MediationInterstitialAdUnitTest.swift */; }; + 53CDA4902D11AFD5004766F8 /* MediationUtilsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53CDA48A2D11AFD5004766F8 /* MediationUtilsTest.swift */; }; + 53CDA4912D11AFD5004766F8 /* MediationRewardedAdUnitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53CDA4892D11AFD5004766F8 /* MediationRewardedAdUnitTest.swift */; }; 53CE09012AD673020018CB75 /* sample_ortb_native_with_win_event.json in Resources */ = {isa = PBXBuildFile; fileRef = 53CE09002AD673020018CB75 /* sample_ortb_native_with_win_event.json */; }; 53CE09032AD67ECE0018CB75 /* MockPBMBidRequester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53CE09022AD67ECE0018CB75 /* MockPBMBidRequester.swift */; }; 53CF5B3729DC690600613E84 /* VideoAdUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53CF5B3629DC690600613E84 /* VideoAdUnit.swift */; }; @@ -672,7 +677,6 @@ 9236A64E272FEAFE00ABBEF4 /* ImpressionTasksExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9236A64D272FEAFE00ABBEF4 /* ImpressionTasksExecutor.swift */; }; 9236A650272FEC5A00ABBEF4 /* ImpressionTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9236A64F272FEC5A00ABBEF4 /* ImpressionTask.swift */; }; 923B55002744F19600E00C88 /* PrebidMediationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 923B54FF2744F19600E00C88 /* PrebidMediationDelegate.swift */; }; - 923B5521274536B400E00C88 /* MockMediationUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 923B5520274536B400E00C88 /* MockMediationUtils.swift */; }; 9247FEFE2808175E00ACD84A /* VideoControlsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9247FEFD2808175E00ACD84A /* VideoControlsConfiguration.swift */; }; 924F661827FDB79C00C8DAF7 /* PBMORTBExtPrebidPassthrough.h in Headers */ = {isa = PBXBuildFile; fileRef = 924F661727FDB79C00C8DAF7 /* PBMORTBExtPrebidPassthrough.h */; settings = {ATTRIBUTES = (Public, ); }; }; 924F661A27FDB82600C8DAF7 /* PBMORTBAdConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 924F661927FDB82600C8DAF7 /* PBMORTBAdConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -721,9 +725,6 @@ 925D5E182737E7D200A8A2B5 /* PBMErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925D5E172737E7D200A8A2B5 /* PBMErrorTest.swift */; }; 925D5E1C2737E89500A8A2B5 /* PBMORTBTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925D5E1B2737E89400A8A2B5 /* PBMORTBTest.swift */; }; 925D5E1E2737E8BF00A8A2B5 /* PBMBaseInterstitialAdUnit_DelegationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925D5E1D2737E8BF00A8A2B5 /* PBMBaseInterstitialAdUnit_DelegationTest.swift */; }; - 925D5E222737EA1E00A8A2B5 /* MediationBannerAdUnitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925D5E212737EA1E00A8A2B5 /* MediationBannerAdUnitTest.swift */; }; - 925D5E272737EC5E00A8A2B5 /* MediationInterstitialAdUnitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925D5E262737EC5E00A8A2B5 /* MediationInterstitialAdUnitTest.swift */; }; - 925D5E292737EC9400A8A2B5 /* MediationRewardedAdUnitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925D5E282737EC9400A8A2B5 /* MediationRewardedAdUnitTest.swift */; }; 925D5E2D2737ECEA00A8A2B5 /* PBMWinNotifierTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925D5E2C2737ECEA00A8A2B5 /* PBMWinNotifierTest.swift */; }; 925D5E302737ED8C00A8A2B5 /* PBMRewardedVideoViewTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925D5E2F2737ED8C00A8A2B5 /* PBMRewardedVideoViewTest.swift */; }; 925D5E332737EE1C00A8A2B5 /* PBMTransactionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925D5E322737EE1C00A8A2B5 /* PBMTransactionTests.swift */; }; @@ -766,7 +767,6 @@ 92664569272AB9120064F7BD /* SkadnEventTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92664568272AB9120064F7BD /* SkadnEventTracker.swift */; }; 9266456B272AB9610064F7BD /* SkadnParametersManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9266456A272AB9610064F7BD /* SkadnParametersManager.swift */; }; 927ADB2428057B31006EB8D5 /* MediationUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 927ADB2328057B31006EB8D5 /* MediationUtils.swift */; }; - 927ADB2728058196006EB8D5 /* MediationUtilsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 927ADB2628058196006EB8D5 /* MediationUtilsTest.swift */; }; 9285B46C27AAC9C1009BD3D3 /* NativeAdMarkupTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9285B46B27AAC9C1009BD3D3 /* NativeAdMarkupTest.swift */; }; 928E5A6E27F0F706000ADA1A /* ContextType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 928E5A6D27F0F706000ADA1A /* ContextType.swift */; }; 928E5A7027F0F743000ADA1A /* ContextSubType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 928E5A6F27F0F743000ADA1A /* ContextSubType.swift */; }; @@ -997,9 +997,9 @@ 534C61452CB562E40026119A /* CloseActionManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloseActionManagerTests.swift; sourceTree = ""; }; 535145DE2CCB758800D40B19 /* NSObject+PBMExtensions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSObject+PBMExtensions.h"; sourceTree = ""; }; 535145DF2CCB758800D40B19 /* NSObject+PBMExtensions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSObject+PBMExtensions.m"; sourceTree = ""; }; - 53514CF12D0851DE00A480C0 /* InterstitialControllerInteractionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterstitialControllerInteractionDelegate.swift; sourceTree = ""; }; 53514CC52D01B5AF00A480C0 /* InterstitialRenderingAdUnitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterstitialRenderingAdUnitTest.swift; sourceTree = ""; }; 53514CC72D01B5F200A480C0 /* RewardedAdUnitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RewardedAdUnitTest.swift; sourceTree = ""; }; + 53514CF12D0851DE00A480C0 /* InterstitialControllerInteractionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterstitialControllerInteractionDelegate.swift; sourceTree = ""; }; 5355ACA829C454070014F16E /* VAST_with_empty_companion.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = VAST_with_empty_companion.xml; sourceTree = ""; }; 5355ACAA29C454770014F16E /* CreativeModelCollectionMakerVASTTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreativeModelCollectionMakerVASTTests.swift; sourceTree = ""; }; 536A39252A84C50F00B1CCEA /* StringExtensionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtensionsTest.swift; sourceTree = ""; }; @@ -1046,6 +1046,11 @@ 53C925012990FB30009E6F94 /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = ""; }; 53C925042990FBFB009E6F94 /* PrebidServerStatusRequester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidServerStatusRequester.swift; sourceTree = ""; }; 53C9250629915466009E6F94 /* PrebidServerStatusRequesterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidServerStatusRequesterTests.swift; sourceTree = ""; }; + 53CDA4872D11AFD5004766F8 /* MediationBannerAdUnitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediationBannerAdUnitTest.swift; sourceTree = ""; }; + 53CDA4882D11AFD5004766F8 /* MediationInterstitialAdUnitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediationInterstitialAdUnitTest.swift; sourceTree = ""; }; + 53CDA4892D11AFD5004766F8 /* MediationRewardedAdUnitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediationRewardedAdUnitTest.swift; sourceTree = ""; }; + 53CDA48A2D11AFD5004766F8 /* MediationUtilsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediationUtilsTest.swift; sourceTree = ""; }; + 53CDA48B2D11AFD5004766F8 /* MockMediationUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediationUtils.swift; sourceTree = ""; }; 53CE09002AD673020018CB75 /* sample_ortb_native_with_win_event.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = sample_ortb_native_with_win_event.json; sourceTree = ""; }; 53CE09022AD67ECE0018CB75 /* MockPBMBidRequester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockPBMBidRequester.swift; sourceTree = ""; }; 53CF5B3629DC690600613E84 /* VideoAdUnit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoAdUnit.swift; sourceTree = ""; }; @@ -1585,7 +1590,6 @@ 9236A64D272FEAFE00ABBEF4 /* ImpressionTasksExecutor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImpressionTasksExecutor.swift; sourceTree = ""; }; 9236A64F272FEC5A00ABBEF4 /* ImpressionTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImpressionTask.swift; sourceTree = ""; }; 923B54FF2744F19600E00C88 /* PrebidMediationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrebidMediationDelegate.swift; sourceTree = ""; }; - 923B5520274536B400E00C88 /* MockMediationUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediationUtils.swift; sourceTree = ""; }; 9247FEFD2808175E00ACD84A /* VideoControlsConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoControlsConfiguration.swift; sourceTree = ""; }; 924F661727FDB79C00C8DAF7 /* PBMORTBExtPrebidPassthrough.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PBMORTBExtPrebidPassthrough.h; sourceTree = ""; }; 924F661927FDB82600C8DAF7 /* PBMORTBAdConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PBMORTBAdConfiguration.h; sourceTree = ""; }; @@ -1637,11 +1641,8 @@ 925D5E172737E7D200A8A2B5 /* PBMErrorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PBMErrorTest.swift; sourceTree = ""; }; 925D5E1B2737E89400A8A2B5 /* PBMORTBTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PBMORTBTest.swift; sourceTree = ""; }; 925D5E1D2737E8BF00A8A2B5 /* PBMBaseInterstitialAdUnit_DelegationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PBMBaseInterstitialAdUnit_DelegationTest.swift; sourceTree = ""; }; - 925D5E212737EA1E00A8A2B5 /* MediationBannerAdUnitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediationBannerAdUnitTest.swift; sourceTree = ""; }; 925D5E232737EAE500A8A2B5 /* MediationBannerAdUnit+TestExtension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MediationBannerAdUnit+TestExtension.h"; sourceTree = ""; }; 925D5E242737EB5400A8A2B5 /* MediationInterstitialAdUnit+TestExtension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MediationInterstitialAdUnit+TestExtension.h"; sourceTree = ""; }; - 925D5E262737EC5E00A8A2B5 /* MediationInterstitialAdUnitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediationInterstitialAdUnitTest.swift; sourceTree = ""; }; - 925D5E282737EC9400A8A2B5 /* MediationRewardedAdUnitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediationRewardedAdUnitTest.swift; sourceTree = ""; }; 925D5E2C2737ECEA00A8A2B5 /* PBMWinNotifierTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PBMWinNotifierTest.swift; sourceTree = ""; }; 925D5E2F2737ED8C00A8A2B5 /* PBMRewardedVideoViewTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PBMRewardedVideoViewTest.swift; sourceTree = ""; }; 925D5E312737EDCD00A8A2B5 /* PBMVideoView+pbmTestExtension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PBMVideoView+pbmTestExtension.h"; sourceTree = ""; }; @@ -1688,7 +1689,6 @@ 92664568272AB9120064F7BD /* SkadnEventTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkadnEventTracker.swift; sourceTree = ""; }; 9266456A272AB9610064F7BD /* SkadnParametersManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkadnParametersManager.swift; sourceTree = ""; }; 927ADB2328057B31006EB8D5 /* MediationUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediationUtils.swift; sourceTree = ""; }; - 927ADB2628058196006EB8D5 /* MediationUtilsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediationUtilsTest.swift; sourceTree = ""; }; 9285B46B27AAC9C1009BD3D3 /* NativeAdMarkupTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeAdMarkupTest.swift; sourceTree = ""; }; 928E5A6D27F0F706000ADA1A /* ContextType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextType.swift; sourceTree = ""; }; 928E5A6F27F0F743000ADA1A /* ContextSubType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextSubType.swift; sourceTree = ""; }; @@ -2000,6 +2000,25 @@ path = CacheManagement; sourceTree = ""; }; + 53CDA4832D11AEE3004766F8 /* Recovered References */ = { + isa = PBXGroup; + children = ( + ); + name = "Recovered References"; + sourceTree = ""; + }; + 53CDA48C2D11AFD5004766F8 /* MediationAPI */ = { + isa = PBXGroup; + children = ( + 53CDA4872D11AFD5004766F8 /* MediationBannerAdUnitTest.swift */, + 53CDA4882D11AFD5004766F8 /* MediationInterstitialAdUnitTest.swift */, + 53CDA4892D11AFD5004766F8 /* MediationRewardedAdUnitTest.swift */, + 53CDA48A2D11AFD5004766F8 /* MediationUtilsTest.swift */, + 53CDA48B2D11AFD5004766F8 /* MockMediationUtils.swift */, + ); + path = MediationAPI; + sourceTree = ""; + }; 53CE08FF2AD672980018CB75 /* ORTB-samples */ = { isa = PBXGroup; children = ( @@ -2851,6 +2870,7 @@ 60D792F3217E229A0080F428 /* Products */, 6062B19A218243FA00CE1BA3 /* Frameworks */, EE09B07119B6562CC4356195 /* Pods */, + 53CDA4832D11AEE3004766F8 /* Recovered References */, ); sourceTree = ""; }; @@ -3073,6 +3093,7 @@ 925D5DA82737C4C400A8A2B5 /* Prebid */ = { isa = PBXGroup; children = ( + 53CDA48C2D11AFD5004766F8 /* MediationAPI */, 925D5DA92737C4E800A8A2B5 /* AdLoadFlow */, 3CD0ADED2C5125E9006CDA6B /* PluginRegisterTest.swift */, 925D5E082737DF5F00A8A2B5 /* PBMBannerViewTest.swift */, @@ -3180,18 +3201,6 @@ path = VASTTests; sourceTree = ""; }; - 927ADB2528058170006EB8D5 /* MediationAPI */ = { - isa = PBXGroup; - children = ( - 925D5E212737EA1E00A8A2B5 /* MediationBannerAdUnitTest.swift */, - 925D5E262737EC5E00A8A2B5 /* MediationInterstitialAdUnitTest.swift */, - 925D5E282737EC9400A8A2B5 /* MediationRewardedAdUnitTest.swift */, - 923B5520274536B400E00C88 /* MockMediationUtils.swift */, - 927ADB2628058196006EB8D5 /* MediationUtilsTest.swift */, - ); - path = MediationAPI; - sourceTree = ""; - }; 929638B927AB1FE900D30F3D /* NativeAssetObjectsTests */ = { isa = PBXGroup; children = ( @@ -3877,7 +3886,6 @@ FAA2990C243368A1002ACBF2 /* AdUnitSuccessorObjCTests.m in Sources */, 925D5E4B2737F1AA00A8A2B5 /* TestStringExtension.swift in Sources */, 925D5DB52737C57C00A8A2B5 /* MockPrimaryAdRequester.swift in Sources */, - 923B5521274536B400E00C88 /* MockMediationUtils.swift in Sources */, 922AFC8D27352BE900732C53 /* MockViewController.swift in Sources */, 922AFD2B2737258200732C53 /* PBMCreativeViewabilityTrackerTest.swift in Sources */, 922AFCF927370B9800732C53 /* LogObjCTest.m in Sources */, @@ -3912,7 +3920,6 @@ 929638BD27AB20FB00D30F3D /* NativeDataTests.swift in Sources */, 925D5D762737B85400A8A2B5 /* PBMVastCreativeCompanionAdsTest.swift in Sources */, 534C61462CB562E40026119A /* CloseActionManagerTests.swift in Sources */, - 925D5E222737EA1E00A8A2B5 /* MediationBannerAdUnitTest.swift in Sources */, 925D5E6C2737F4DF00A8A2B5 /* PBMVastLoaderTestOMVerificationOneInline.swift in Sources */, 925D5D912737C0A300A8A2B5 /* PBMUIViewTests.swift in Sources */, 9743CB84235F1CDB002E2CAA /* NativeAssetTests.swift in Sources */, @@ -3942,7 +3949,6 @@ 922AFCC727353B6300732C53 /* MockServer.m in Sources */, 922AFD13273718B400732C53 /* PBMAdUnitConfigTest.swift in Sources */, 5355ACAB29C454770014F16E /* CreativeModelCollectionMakerVASTTests.swift in Sources */, - 927ADB2728058196006EB8D5 /* MediationUtilsTest.swift in Sources */, 922AFD47273729B700732C53 /* PBMHTMLCreativeTest_MRAIDResize.swift in Sources */, 922AFCFD27370D8100732C53 /* PBMMRAIDControllerObjCTest.m in Sources */, 925D5E142737E74D00A8A2B5 /* PBMBidResponseTransformerTest.swift in Sources */, @@ -4001,7 +4007,6 @@ 925D5D962737C15E00A8A2B5 /* ParameterBuilderServiceTest.swift in Sources */, 925D5E742737F5AB00A8A2B5 /* PBMVideoCreativeTest.swift in Sources */, 925D5D6A2737B5BC00A8A2B5 /* ServerConnectionWithMockServer.swift in Sources */, - 925D5E292737EC9400A8A2B5 /* MediationRewardedAdUnitTest.swift in Sources */, 47D9A16ECCE6B2FB6D603053 /* MockCTTelephonyNetworkInfo.swift in Sources */, 922AFC8827352B0100732C53 /* MockUserAgentService.swift in Sources */, 925D5E702737F55800A8A2B5 /* PBMVastParserTests.swift in Sources */, @@ -4037,6 +4042,11 @@ 9285B46C27AAC9C1009BD3D3 /* NativeAdMarkupTest.swift in Sources */, 922AFC9327352CEB00732C53 /* MockPBMVideoCreative.swift in Sources */, 929638C127AB224400D30F3D /* NativeEventTrackerResponseTests.swift in Sources */, + 53CDA48D2D11AFD5004766F8 /* MediationBannerAdUnitTest.swift in Sources */, + 53CDA48E2D11AFD5004766F8 /* MockMediationUtils.swift in Sources */, + 53CDA48F2D11AFD5004766F8 /* MediationInterstitialAdUnitTest.swift in Sources */, + 53CDA4902D11AFD5004766F8 /* MediationUtilsTest.swift in Sources */, + 53CDA4912D11AFD5004766F8 /* MediationRewardedAdUnitTest.swift in Sources */, 47D9A59A1013D9036158B7E3 /* MockModalManager.swift in Sources */, 925D5E122737E04B00A8A2B5 /* PBMBidRequesterTest.swift in Sources */, 925D5E332737EE1C00A8A2B5 /* PBMTransactionTests.swift in Sources */, @@ -4088,7 +4098,6 @@ 922AFC9127352C9B00732C53 /* MockPBMWebView.swift in Sources */, 922AFCEE2736FC8600732C53 /* XCTest.swift in Sources */, 925D5E2D2737ECEA00A8A2B5 /* PBMWinNotifierTest.swift in Sources */, - 925D5E272737EC5E00A8A2B5 /* MediationInterstitialAdUnitTest.swift in Sources */, 922AFD062737120B00732C53 /* ImpressionTasksExecutorTest.swift in Sources */, 925D5E6E2737F51E00A8A2B5 /* PBMVastLoaderTestWrapperPlusInline.swift in Sources */, 922AFCD327353C5700732C53 /* MockServerMimeType.m in Sources */, From 1ac4fd52bc75a7af1a1c528dfdf0757f254c461d Mon Sep 17 00:00:00 2001 From: Olena Stepaniuk Date: Wed, 18 Dec 2024 11:58:49 +0200 Subject: [PATCH 18/18] feat: add log message in case default renderer wasn't found in registry --- .../PluginRenderer/PrebidMobilePluginRegister.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift index 117b74189..0972ec925 100644 --- a/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift +++ b/PrebidMobile/PrebidMobileRendering/PluginRenderer/PrebidMobilePluginRegister.swift @@ -23,7 +23,12 @@ public class PrebidMobilePluginRegister: NSObject { /// Default PrebidMobile SDK renderer public var sdkRenderer: PrebidMobilePluginRenderer { - getPluginRenderer(for: PREBID_MOBILE_RENDERER_NAME) ?? PrebidRenderer() + if let renderer = getPluginRenderer(for: PREBID_MOBILE_RENDERER_NAME) { + return renderer + } + + Log.error("SDK couldn't find \(PREBID_MOBILE_RENDERER_NAME) in plugin register. The new instance of \(PREBID_MOBILE_RENDERER_NAME) will be created.") + return PrebidRenderer() } private let queue = DispatchQueue(