在实现 Google 交互式媒体广告 (IMA) SDK 协议时,我的 mediaPlayer/audioManager(它是一个 AVPlayer 对象)在 adsManagerDidRequestContentPause 委托方法期间不会暂停。我的 mediaPlayer 符合 ObservableObject,这是我认为问题出在哪里,但我不是 100% 肯定的。
当我按下播放按钮时,我会播放音频并从我的 adsManager 类中请求广告。问题是预卷视频播放,但来自内容播放器的音频在预卷上播放。内容播放器的音频应该在预卷播放时暂停,并在结束后恢复。正如您将在代码中看到的,AudioManager 也是一个单例类。
这是用户按下播放时的代码。
@ObservedObject var manager = AudioManager.sharedInstance
func didTapPlayButton(){
isPlaying.toggle()
if isPlaying {
audioManager.playLiveStream(with: pageInfo.tritonMount)
adManager.requestAds()
} else {
audioManager.pause()
}
}
这是带有 Google IMA 委托方法的 adManager 类。在每个委托方法设置断点后,我发现对 audioManager 的每次调用都被成功调用,但是,来自 audioManager 的音频实际上并没有暂停。
@ObservedObject var manager = AudioManager.sharedInstance
func setUpContentPlayer() {
contentPlayhead = IMAAVPlayerContentPlayhead(avPlayer: player)
// Create a player layer for the player.
playerLayer = AVPlayerLayer(player: player)
playerLayer!.frame = videoView.underlyingView.layer.bounds
videoView.underlyingView.layer.addSublayer(playerLayer!)
}
func setUpAdsLoader() {
adsLoader = IMAAdsLoader(settings: nil)
adsLoader!.delegate = self
}
func requestAds() {
// Create an ad display container for ad rendering.
let adDisplayContainer = IMAAdDisplayContainer(adContainer: videoView.underlyingView, companionSlots: nil)
// Create an ad request with our ad tag, display container, and optional user context.
let request = IMAAdsRequest(
adTagUrl: kLivePrerollVastTag,
adDisplayContainer: adDisplayContainer,
contentPlayhead: contentPlayhead,
userContext: nil)
adsLoader!.requestAds(with: request)
}
func adsLoader(_ loader: IMAAdsLoader!, adsLoadedWith adsLoadedData: IMAAdsLoadedData!) {
// Grab the instance of the IMAAdsManager and set ourselves as the delegate
adsManager = adsLoadedData.adsManager
adsManager!.delegate = self
// Create ads rendering settings and tell the SDK to use the in-app browser.
let adsRenderingSettings = IMAAdsRenderingSettings()
adsRenderingSettings.webOpenerPresentingController = viewController
// Initialize the ads manager.
adsManager!.initialize(with: adsRenderingSettings)
}
//Ads Manager recieved ad request and is loading and starting ad
func adsManager(_ adsManager: IMAAdsManager!, didReceive event: IMAAdEvent!) {
if (event.type == IMAAdEventType.LOADED) {
// When the SDK notifies us that ads have been loaded, play them.
adsManager.start()
}
}
//Ads manager failed to receive ad request
func adsLoader(_ loader: IMAAdsLoader!, failedWith adErrorData: IMAAdLoadingErrorData!) {
print("Error loading ads: \(String(describing: adErrorData.adError.message))")
audioManager.resume()
}
func adsManager(_ adsManager: IMAAdsManager!, didReceive error: IMAAdError!) {
// Something went wrong with the ads manager after ads were loaded. Log the
// error and play the content.
NSLog("AdsManager error: \(String(describing: error.message))")
audioManager.resume()
}
/*Ads manager received request, initiated avplayer and is now
requesting player be paused in order or the Ads manager to play preroll*/
func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager!) {
// The SDK is going to play ads, so pause the content.
audioManager.pause()
}
/*Ads manager received request, played the preroll and is now
requesting avplayer to resume live stream*/
func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager!) {
// The SDK is done playing ads (at least for now), so resume the content.
audioManager.resume()
}
音频管理器类:
/// Upon setting this property any observers for 'currentItem' as well as any time observers will
/// be removed from the old value where applicable and added to the new value where applicable.
var player: AVPlayer? {
didSet {
oldValue?.removeObserver(self, forKeyPath: "currentItem", context: &AudioManager.ObserveAVPlayerCurrentItem)
oldValue?.removeObserver(self, forKeyPath: "rate", context: &AudioManager.ObserveAVPlayerRate)
guard let player = self.player else { return }
player.addObserver(self, forKeyPath: "currentItem", options: [.initial, .new], context: &AudioManager.ObserveAVPlayerCurrentItem)
player.addObserver(self, forKeyPath: "rate", options: [.initial, .new], context: &AudioManager.ObserveAVPlayerRate)
player.automaticallyWaitsToMinimizeStalling = false
if let tmpObs = timeObserver {
print("Already have timeobserver, removing it")
oldValue?.removeTimeObserver(tmpObs)
timeObserver = nil
}
timeObserver = player.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1,preferredTimescale: 1),
queue: nil,
using: timeObserverCallback) as AnyObject?
}
}