2023-03-12 16:29:03 -06:00
|
|
|
#if USE_GOOGLE_IMA
|
2022-11-17 04:01:29 -07:00
|
|
|
import Foundation
|
|
|
|
import GoogleInteractiveMediaAds
|
|
|
|
|
2023-10-06 10:43:35 -06:00
|
|
|
class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate, IMALinkOpenerDelegate {
|
2022-11-17 04:01:29 -07:00
|
|
|
|
2023-07-06 01:52:33 -06:00
|
|
|
private weak var _video: RCTVideo?
|
2023-09-17 13:12:46 -06:00
|
|
|
private var _pipEnabled:() -> Bool
|
2022-11-17 04:01:29 -07:00
|
|
|
|
|
|
|
/* Entry point for the SDK. Used to make ad requests. */
|
|
|
|
private var adsLoader: IMAAdsLoader!
|
|
|
|
/* Main point of interaction with the SDK. Created by the SDK as the result of an ad request. */
|
|
|
|
private var adsManager: IMAAdsManager!
|
2022-11-17 04:12:50 -07:00
|
|
|
|
2023-09-17 13:12:46 -06:00
|
|
|
init(video:RCTVideo!, pipEnabled:@escaping () -> Bool) {
|
2022-11-17 04:01:29 -07:00
|
|
|
_video = video
|
2023-09-17 13:12:46 -06:00
|
|
|
_pipEnabled = pipEnabled
|
2022-11-17 04:01:29 -07:00
|
|
|
|
|
|
|
super.init()
|
|
|
|
}
|
|
|
|
|
|
|
|
func setUpAdsLoader() {
|
|
|
|
adsLoader = IMAAdsLoader(settings: nil)
|
|
|
|
adsLoader.delegate = self
|
|
|
|
}
|
|
|
|
|
|
|
|
func requestAds() {
|
2023-07-06 01:52:33 -06:00
|
|
|
guard let _video = _video else {return}
|
2022-11-17 04:01:29 -07:00
|
|
|
// Create ad display container for ad rendering.
|
|
|
|
let adDisplayContainer = IMAAdDisplayContainer(adContainer: _video, viewController: _video.reactViewController())
|
2022-11-17 04:12:50 -07:00
|
|
|
|
2022-11-17 04:01:29 -07:00
|
|
|
let adTagUrl = _video.getAdTagUrl()
|
|
|
|
let contentPlayhead = _video.getContentPlayhead()
|
|
|
|
|
|
|
|
if adTagUrl != nil && contentPlayhead != nil {
|
|
|
|
// Create an ad request with our ad tag, display container, and optional user context.
|
|
|
|
let request = IMAAdsRequest(
|
|
|
|
adTagUrl: adTagUrl!,
|
|
|
|
adDisplayContainer: adDisplayContainer,
|
|
|
|
contentPlayhead: contentPlayhead,
|
|
|
|
userContext: nil)
|
2022-11-17 04:12:50 -07:00
|
|
|
|
2022-11-17 04:01:29 -07:00
|
|
|
adsLoader.requestAds(with: request)
|
|
|
|
}
|
|
|
|
}
|
2022-11-17 04:12:50 -07:00
|
|
|
|
2022-11-17 04:01:29 -07:00
|
|
|
// MARK: - Getters
|
|
|
|
|
|
|
|
func getAdsLoader() -> IMAAdsLoader? {
|
|
|
|
return adsLoader
|
|
|
|
}
|
|
|
|
|
|
|
|
func getAdsManager() -> IMAAdsManager? {
|
|
|
|
return adsManager
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - IMAAdsLoaderDelegate
|
|
|
|
|
|
|
|
func adsLoader(_ loader: IMAAdsLoader, adsLoadedWith adsLoadedData: IMAAdsLoadedData) {
|
2023-07-06 01:52:33 -06:00
|
|
|
guard let _video = _video else {return}
|
2022-11-17 04:01:29 -07:00
|
|
|
// Grab the instance of the IMAAdsManager and set yourself as the delegate.
|
|
|
|
adsManager = adsLoadedData.adsManager
|
|
|
|
adsManager?.delegate = self
|
2022-11-17 04:12:50 -07:00
|
|
|
|
2022-11-17 04:01:29 -07:00
|
|
|
|
|
|
|
// Create ads rendering settings and tell the SDK to use the in-app browser.
|
|
|
|
let adsRenderingSettings: IMAAdsRenderingSettings = IMAAdsRenderingSettings();
|
2023-10-06 10:43:35 -06:00
|
|
|
adsRenderingSettings.linkOpenerDelegate = self;
|
2022-11-17 04:01:29 -07:00
|
|
|
adsRenderingSettings.linkOpenerPresentingController = _video.reactViewController();
|
|
|
|
|
|
|
|
adsManager.initialize(with: adsRenderingSettings)
|
|
|
|
}
|
|
|
|
|
|
|
|
func adsLoader(_ loader: IMAAdsLoader, failedWith adErrorData: IMAAdLoadingErrorData) {
|
|
|
|
if adErrorData.adError.message != nil {
|
|
|
|
print("Error loading ads: " + adErrorData.adError.message!)
|
|
|
|
}
|
|
|
|
|
2023-07-06 01:52:33 -06:00
|
|
|
_video?.setPaused(false)
|
2022-11-17 04:01:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - IMAAdsManagerDelegate
|
|
|
|
|
|
|
|
func adsManager(_ adsManager: IMAAdsManager, didReceive event: IMAAdEvent) {
|
2023-07-06 01:52:33 -06:00
|
|
|
guard let _video = _video else {return}
|
2023-03-28 05:14:48 -06:00
|
|
|
// Mute ad if the main player is muted
|
|
|
|
if (_video.isMuted()) {
|
|
|
|
adsManager.volume = 0;
|
|
|
|
}
|
2022-11-17 04:01:29 -07:00
|
|
|
// Play each ad once it has been loaded
|
|
|
|
if event.type == IMAAdEventType.LOADED {
|
2023-09-17 13:12:46 -06:00
|
|
|
if (_pipEnabled()) {
|
|
|
|
return
|
|
|
|
}
|
2022-11-17 04:01:29 -07:00
|
|
|
adsManager.start()
|
|
|
|
}
|
|
|
|
|
|
|
|
if _video.onReceiveAdEvent != nil {
|
|
|
|
let type = convertEventToString(event: event.type)
|
|
|
|
|
2023-11-27 13:43:30 -07:00
|
|
|
if (event.adData != nil) {
|
|
|
|
_video.onReceiveAdEvent?([
|
|
|
|
"event": type,
|
|
|
|
"data": event.adData ?? [String](),
|
|
|
|
"target": _video.reactTag!
|
|
|
|
]);
|
|
|
|
} else {
|
|
|
|
_video.onReceiveAdEvent?([
|
|
|
|
"event": type,
|
|
|
|
"target": _video.reactTag!
|
|
|
|
]);
|
|
|
|
}
|
2022-11-17 04:01:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func adsManager(_ adsManager: IMAAdsManager, didReceive error: IMAAdError) {
|
|
|
|
if error.message != nil {
|
|
|
|
print("AdsManager error: " + error.message!)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fall back to playing content
|
2023-07-06 01:52:33 -06:00
|
|
|
_video?.setPaused(false)
|
2022-11-17 04:01:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager) {
|
|
|
|
// Pause the content for the SDK to play ads.
|
2023-07-06 01:52:33 -06:00
|
|
|
_video?.setPaused(true)
|
|
|
|
_video?.setAdPlaying(true)
|
2022-11-17 04:01:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager) {
|
|
|
|
// Resume the content since the SDK is done playing ads (at least for now).
|
2023-07-06 01:52:33 -06:00
|
|
|
_video?.setAdPlaying(false)
|
|
|
|
_video?.setPaused(false)
|
2022-11-17 04:01:29 -07:00
|
|
|
}
|
|
|
|
|
2023-10-06 10:43:35 -06:00
|
|
|
// MARK: - IMALinkOpenerDelegate
|
|
|
|
|
|
|
|
func linkOpenerDidClose(inAppLink linkOpener: NSObject) {
|
|
|
|
adsManager?.resume()
|
|
|
|
}
|
|
|
|
|
2022-11-17 04:01:29 -07:00
|
|
|
// MARK: - Helpers
|
|
|
|
|
|
|
|
func convertEventToString(event: IMAAdEventType!) -> String {
|
|
|
|
var result = "UNKNOWN";
|
|
|
|
|
|
|
|
switch(event) {
|
|
|
|
case .AD_BREAK_READY:
|
|
|
|
result = "AD_BREAK_READY";
|
|
|
|
break;
|
|
|
|
case .AD_BREAK_ENDED:
|
|
|
|
result = "AD_BREAK_ENDED";
|
|
|
|
break;
|
|
|
|
case .AD_BREAK_STARTED:
|
|
|
|
result = "AD_BREAK_STARTED";
|
|
|
|
break;
|
|
|
|
case .AD_PERIOD_ENDED:
|
|
|
|
result = "AD_PERIOD_ENDED";
|
|
|
|
break;
|
|
|
|
case .AD_PERIOD_STARTED:
|
|
|
|
result = "AD_PERIOD_STARTED";
|
|
|
|
break;
|
|
|
|
case .ALL_ADS_COMPLETED:
|
|
|
|
result = "ALL_ADS_COMPLETED";
|
|
|
|
break;
|
|
|
|
case .CLICKED:
|
2022-11-30 04:50:48 -07:00
|
|
|
result = "CLICK";
|
2022-11-17 04:01:29 -07:00
|
|
|
break;
|
|
|
|
case .COMPLETE:
|
2023-11-23 00:45:47 -07:00
|
|
|
result = "COMPLETED";
|
2022-11-17 04:01:29 -07:00
|
|
|
break;
|
|
|
|
case .CUEPOINTS_CHANGED:
|
|
|
|
result = "CUEPOINTS_CHANGED";
|
|
|
|
break;
|
|
|
|
case .FIRST_QUARTILE:
|
|
|
|
result = "FIRST_QUARTILE";
|
|
|
|
break;
|
|
|
|
case .LOADED:
|
|
|
|
result = "LOADED";
|
|
|
|
break;
|
|
|
|
case .LOG:
|
|
|
|
result = "LOG";
|
|
|
|
break;
|
|
|
|
case .MIDPOINT:
|
|
|
|
result = "MIDPOINT";
|
|
|
|
break;
|
|
|
|
case .PAUSE:
|
2022-11-30 04:50:48 -07:00
|
|
|
result = "PAUSED";
|
2022-11-17 04:01:29 -07:00
|
|
|
break;
|
|
|
|
case .RESUME:
|
2022-11-30 04:50:48 -07:00
|
|
|
result = "RESUMED";
|
2022-11-17 04:01:29 -07:00
|
|
|
break;
|
|
|
|
case .SKIPPED:
|
|
|
|
result = "SKIPPED";
|
|
|
|
break;
|
|
|
|
case .STARTED:
|
|
|
|
result = "STARTED";
|
|
|
|
break;
|
|
|
|
case .STREAM_LOADED:
|
|
|
|
result = "STREAM_LOADED";
|
|
|
|
break;
|
|
|
|
case .TAPPED:
|
|
|
|
result = "TAPPED";
|
|
|
|
break;
|
|
|
|
case .THIRD_QUARTILE:
|
|
|
|
result = "THIRD_QUARTILE";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
result = "UNKNOWN";
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
2023-03-12 16:29:03 -06:00
|
|
|
#endif
|