在 IMA v3.30.0 及更低版本中,IMA SDK 可以处理所有广告播放逻辑, 而应用专注于播放内容视频。这种方法称为 “SDK 自有广告播放”。
如果您希望在视频播放器中播放广告,请使用 SDK 并为此提供了一个接口我们将此方法称为“自定义 广告播放”本指南的其余部分会介绍具体的实现方法
前提条件
- 基本的 IMA 集成。
我们建议您参阅 高级示例 如果您还没有基本的 IMA 集成。此示例已实现了自定义广告播放。剩余部分 本指南将会介绍通过 Google Cloud 控制台自定义广告播放 IMA 广告。
VideoAdPlayer 接口
自定义广告播放要求您的应用实现
VideoAdPlayer
界面。SDK 使用此接口通知您的应用播放广告
视频。您的应用还会使用此接口向 SDK 告知主要视频广告
事件。请按照以下步骤实现该接口。
创建 VideoAdPlayer
第一步是创建一个匿名 VideoAdPlayer
类
在 requestAds()
中:
private VideoAdPlayer videoAdPlayer;
...
private void requestAds(String adTagUrl) {
videoAdPlayer = new VideoAdPlayer() {
};
}
添加视频方法
接下来,添加指示视频播放器播放、加载、停止和暂停广告的方法 视频。我们还在此处添加了释放播放器并获取音量的方法:
videoAdPlayer = new VideoAdPlayer() {
@Override
public void playAd() {
if (mIsAdDisplayed) {
videoPlayer.resume();
} else {
isAdDisplayed = true;
videoPlayer.play();
}
}
@Override
public void loadAd(String url) {
isAdDisplayed = true;
videoPlayer.setVideoPath(url);
}
@Override
public void stopAd() {
videoPlayer.stopPlayback();
}
@Override
public void pauseAd() {
videoPlayer.pause();
}
@Override
public void release() {
// any clean up that needs to be done
}
@Override
public int getVolume() {
return videoPlayer.getVolume();
}
};
这些方法是视频播放器自身类似于 方法。请注意,这些方法会设置一个内部变量 来跟踪广告是否展示。在自定义广告播放中, 视频播放器会同时播放内容视频和视频广告,因此您需要确保 当前显示的曲目
广告播放进度
VideoAdPlayer
接口实现了另一个接口,
AdProgressProvider
,因此您还必须实现它。它只有
一种方法,即 getAdProgress()
,SDK 使用该方法来获取
。将其添加到您的匿名 VideoAdPlayer
类放在其他方法之后:
VideoAdPlayer videoAdPlayer = new VideoAdPlayer() {
...
@Override
public VideoProgressUpdate getAdProgress() {
if (!isAdDisplayed || videoPlayer.getDuration() <= 0) {
return VideoProgressUpdate.VIDEO_TIME_NOT_READY;
}
return new VideoProgressUpdate(videoPlayer.getCurrentPosition(),
videoPlayer.getDuration());
}
};
getAdProgress()
会返回一个 VideoProgressUpdate
类型,该类型
必须包含视频的当前位置和时长。如果播放器
未播放广告,或广告时长不可用,请将其返回
VideoProgressUpdate.VIDEO_TIME_NOT_READY
,如示例中所示。
管理视频回调
自定义广告播放要求您的应用向 SDK 告知主要
视频事件。从 SDK 的角度来看,这些是
由 VideoAdPlayer.VideoAdPlayerCallback
接口描述。
在进入回调方法本身之前,您需要
能够应 SDK 的请求添加和移除回调。这是
使用 addCallback()
和 removeCallback()
在 VideoAdPlayer
中完成以下操作:
private List<VideoAdPlayerCallback> adCallbacks = new ArrayList<>(1);
VideoAdPlayer videoAdPlayer = new VideoAdPlayer() {
...
@Override
public void addCallback(VideoAdPlayerCallback videoAdPlayerCallback) {
adCallbacks.add(videoAdPlayerCallback);
}
@Override
public void removeCallback(VideoAdPlayerCallback videoAdPlayerCallback) {
adCallbacks.remove(videoAdPlayerCallback);
}
};
此实现为要调用的回调使用 List<>
List<>.add()
和 remove()
方法。
调用回调
现在,SDK 已经可以指示应用添加和移除回调, 定义调用回调的位置。您的应用需要调用 在发生主要视频事件(例如播放、暂停)时, 或继续播放视频,或者视频完整播放或出错时。
为此,请展开 SampleVideoPlayer
以获取这些对象的监听器
从 VideoFragment
添加的视频事件。让
在 SampleVideoPlayer
中使用单独的监听器来调用这些广告回调
因为SampleVideoPlayer
对广告一无所知,
因此您必须将其视频事件转发到可以处理广告的设备。
public interface OnVideoEventsListener {
void onPlay();
void onResume();
void onPause();
void onError();
}
private final List<OnVideoEventsListener> onVideoEventsListeners = new ArrayList<>(1);
public void addVideoEventsListener(OnVideoEventsListener listener) {
onVideoEventsListeners.add(listener);
}
启动、暂停和恢复
创建新的枚举以跟踪播放状态并添加新的替换项
对于 SampleVideoPlayer
中的 start()
和 pause()
方法:
private enum PlaybackState {
STOPPED, PAUSED, PLAYING
}
private PlaybackState playbackState = PlaybackState.STOPPED;
@Override
public void start() {
super.start();
switch (playbackState) {
case STOPPED:
for (OnVideoEventsListener listener : onVideoEventsListeners) {
listener.onPlay();
}
break;
case PAUSED:
for (OnVideoEventsListener listener : onVideoEventsListeners) {
listener.onResume();
}
break;
default:
// Already playing; do nothing.
break;
}
playbackState = PlaybackState.PLAYING;
}
@Override
public void pause() {
super.pause();
playbackState = PlaybackState.PAUSED;
for (OnVideoEventsListener listener : onVideoEventsListeners) {
listener.onPause();
}
}
处理错误
替换您在 init()
中设置的视频播放器匿名错误监听器:
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
playbackState = PlaybackState.STOPPED;
for (OnVideoEventsListener listener : onVideoEventsListeners) {
listener.onError();
}
// Returning true signals to MediaPlayer that the error was handled.
// This prevents the completion handler from being called.
return true;
}
实现监听器
返回 VideoFragment
并添加匿名 OnVideoEventsListener
添加到您的 SampleVideoPlayer
实例:
mVideoPlayer.addVideoEventsListener(new OnVideoEventsListener() {
@Override
public void onPlay() {
if (isAdDisplayed) {
for (VideoAdPlayerCallback callback : adCallbacks) {
callback.onPlay();
}
}
}
@Override
public void onResume() {
if (isAdDisplayed) {
for (VideoAdPlayerCallback callback : adCallbacks) {
callback.onResume();
}
}
}
@Override
public void onPause() {
if (isAdDisplayed) {
for (VideoAdPlayerCallback callback : adCallbacks) {
callback.onPause();
}
}
}
@Override
public void onError() {
if (isAdDisplayed) {
for (VideoAdPlayerCallback callback : adCallbacks) {
callback.onError();
}
}
}
});
更改 OnVideoCompletedListener
的 onVideoCompleted()
方法
来处理广告视频完整播放的情况:
public void onVideoCompleted() {
// Handle completed event for playing post-rolls.
if (isAdDisplayed) {
for (VideoAdPlayerCallback callback : adCallbacks) {
callback.onEnded();
}
} else {
if (adsLoader != null) {
adsLoader.contentComplete();
}
}
在内容和广告之间切换
此示例使用同一个视频播放器实例来同时播放 因此您需要添加一些逻辑 内容和广告。然后,您可以重新加载 内容视频返回到广告开始播放的位置。添加两项 函数:
private int savedContentPosition = 0;
private void pauseContent() {
savedContentPosition = videoPlayer.getCurrentPosition();
videoPlayer.stopPlayback();
isAdDisplayed = true;
}
private void resumeContent() {
videoPlayer.setVideoPath(getString(R.string.content_url));
videoPlayer.seekTo(mSavedContentPosition);
videoPlayer.play();
isAdDisplayed = false;
}
当 CONTENT_PAUSE_REQUESTED
和
在以下位置收到了 CONTENT_RESUME_REQUESTED
个事件:
VideoFragment.onAdEvent()
:
case CONTENT_PAUSE_REQUESTED:
pauseContent();
break;
case CONTENT_RESUME_REQUESTED:
resumeContent();
break;
启用自定义广告播放功能
最后一步是告知 SDK 您要使用自定义广告播放功能。
为此,请将 VideoAdPlayer
传递给 AdDisplayContainer
:
adDisplayContainer.setPlayer(videoAdPlayer);
有必要将播放器传递给 setPlayer()
。否则,
SDK 使用 SDK 拥有的播放机制。
大功告成。以上就是将自定义广告播放添加到 IMA 实现。您可以将自己的实现与 高级示例 。