在應用程式中整合 Android 版 IMA SDK 最簡單快速的方法,就是讓 SDK 處理所有廣告放送邏輯,而應用程式則著重於播放內容影片。這個方法稱為「SDK 擁有的廣告播放」,是開始使用中的預設選項。
不過,如果您也想在影片播放器中播放影片,SDK 會提供相關介面。這種做法將稱為「自訂廣告播放」,本指南的其餘部分將介紹其實作方式。
必要條件
- 基本的 IMA 整合。
如果您目前沒有基本的 IMA 整合,建議您先參考 GitHub 的進階範例。本範例已導入自訂廣告播放功能。本指南的其餘部分將說明使用 IMA 廣告播放自訂廣告所需的功能。
與 VideoAdPlayer 介面
應用程式必須導入 VideoAdPlayer
介面,才能自訂廣告播放。SDK 會使用這個介面通知應用程式播放影片。您的應用程式也會使用這個介面,將主要影片廣告事件告知 SDK。請按照下列步驟實作介面。
建立 VideoAdPlayer
首先,請在 requestAds()
中建立匿名的 VideoAdPlayer
類別:
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 的要求中新增及移除回呼。請在 VideoAdPlayer
中使用 addCallback()
和 removeCallback()
執行此操作:
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 導入作業的所有步驟。如果發生問題,您可以比較自己的實作與 GitHub 上的進階範例。