您可以啟用類似電視的體驗,讓您能夠在廣告中間加入即時串流。
「部分廣告插播」功能可讓您模擬類似電視的體驗,如果用戶端在midroll中啟動即時串流,則會在midroll中啟動。 它類似於切換電視頻道,廣告也順暢運作。
例如,如果使用者在90秒廣告插播(3個30秒廣告)的中間加入,在第二個廣告中加入10秒(亦即,在廣告插播中加入40秒),則會發生下列情況:
預設情況下不啟用此行為。 若要在您的應用程式中啟用此功能,請執行下列動作。
使用AdvertisingMetadata類別的方法setEnableLivePreroll停用即時預覽。
advertisingMetadata.setEnableLivePreroll(String.valueOf(false))
開啟「部分插入廣告插入」偏好設定。 使用MediaPlayer介面中的新方法setPartialAdBreakPref來開啟此功能。 使用getPartialAdBreakPref方法來尋找此偏好設定的目前狀態。
MediaPlayer mediaPlayer = DefaultMediaPlayer.create(getActivity().getApplicationContext());
mediaPlayer.setPartialAdBreakPref(true);
這項功能需要您實作自訂廣告原則選擇器以自訂行為。 如果您尚未自訂AdvertisingFactory類別的實作,請新增新的AdvertisingFactory實作。 覆寫createAdPolicySelector方法。 此方法會傳回AdPolicySelector實作的新例項。
以下提供範例實作供您參考。 下列範例實作可從com.adobe.mediacore套件使用。 但是,它已簡化,以方便參考,不建議按原樣使用。
廣告政策選擇器範例
package com.adobe.mediacore;
import com.adobe.mediacore.logging.Log;
import com.adobe.mediacore.logging.Logger;
import com.adobe.mediacore.metadata.*;
import com.adobe.mediacore.timeline.advertising.*;
import java.util.ArrayList;
import java.util.List;
public class PartialAdBreakAdPolicySelector implements AdPolicySelector {
private static final String LOG_TAG = "[PSDK]::" + DefaultAdPolicySelector.class.getSimpleName();
private final Logger _logger = Log.getLogger(LOG_TAG);
private final MediaPlayerItem _mediaPlayerItem;
private final AdBreakAsWatched _adBreakAsWatchedPolicy;
public PartialAdBreakAdPolicySelector(MediaPlayerItem mediaPlayerItem) {
_mediaPlayerItem = mediaPlayerItem;
_adBreakAsWatchedPolicy = extractAdBreakAsWatchedPolicy(_mediaPlayerItem);
}
@Override
public AdBreakPolicy selectPolicyForAdBreak(AdPolicyInfo adPolicyInfo) {
_logger.i(LOG_TAG + "#selectPolicyForAdBreak", "currentTime=" + adPolicyInfo.getCurrentTime() + " seekToTime="
+ adPolicyInfo.getSeekToTime() + " rate=" + adPolicyInfo.getRate() + " adPolicyMode=" + adPolicyInfo.getMode());
if (adPolicyInfo.getAdBreakPlacements().size() > 0) {
AdBreakPlacement adBreakTimelineItem = adPolicyInfo.getAdBreakPlacements().get(0);
if (adPolicyInfo.getMode() == AdPolicyMode.SEEK && adBreakTimelineItem.getAdBreak().isWatched()) {
return AdBreakPolicy.SKIP;
}
}
AdSignalingMode adSignalingMode = AdSignalingMode.DEFAULT;
if (_mediaPlayerItem != null) {
MetadataNode metadata = (MetadataNode) _mediaPlayerItem.getResource().getMetadata();
if (metadata != null) {
AdvertisingMetadata advertisingMetadata = (AdvertisingMetadata) metadata.getNode(DefaultMetadataKeys.ADVERTISING_METADATA.getValue());
if (advertisingMetadata != null) {
adSignalingMode = advertisingMetadata.getSignalingMode();
}
}
}
// can't remove main content due to a ave bug, need to check if stream is live or ad signaling mode is manifest cue
if (_mediaPlayerItem.isLive() || adSignalingMode == AdSignalingMode.MANIFEST_CUES) {
return AdBreakPolicy.PLAY;
}
return AdBreakPolicy.REMOVE_AFTER_PLAY;
}
@Override
public List<AdBreakPlacement> selectAdBreaksToPlay(AdPolicyInfo adPolicyInfo) {
_logger.i(LOG_TAG + "#selectAdBreaksToPlay", "currentTime=" + adPolicyInfo.getCurrentTime() + " seekToTime="
+ adPolicyInfo.getSeekToTime() + " rate=" + adPolicyInfo.getRate() + " adPolicyMode=" + adPolicyInfo.getMode());
List<AdBreakPlacement> adBreakPlacements = adPolicyInfo.getAdBreakPlacements();
if (adBreakPlacements != null) {
int size = adBreakPlacements.size();
List<AdBreakPlacement> adBreaks = new ArrayList<AdBreakPlacement>();
if (size > 0 && adPolicyInfo.getCurrentTime() <= adPolicyInfo.getSeekToTime()) {
AdBreakPlacement adBreak = adBreakPlacements.get(size - 1);
if (!adBreak.getAdBreak().isWatched()) {
adBreaks.add(adBreak);
return adBreaks;
}
}
}
return null;
}
@Override
public AdPolicy selectPolicyForSeekIntoAd(AdPolicyInfo adPolicyInfo) {
_logger.i(LOG_TAG + "#selectPolicyForSeekIntoAd", "currentTime=" + adPolicyInfo.getCurrentTime() + " seekToTime="
+ adPolicyInfo.getSeekToTime() + " rate=" + adPolicyInfo.getRate() + " adPolicyMode=" + adPolicyInfo.getMode());
// If you really want to allow seek during ads (you likely do not).
return AdPolicy.PLAY;
}
@Override
public AdBreakAsWatched selectWatchedPolicyForAdBreak(AdPolicyInfo adPolicyInfo) {
_logger.i(LOG_TAG + "#selectWatchedPolicyForAdBreak", "currentTime=" + adPolicyInfo.getCurrentTime() + " seekToTime="
+ adPolicyInfo.getSeekToTime() + " rate=" + adPolicyInfo.getRate() + " adPolicyMode=" + adPolicyInfo.getMode());
return _adBreakAsWatchedPolicy;
}
/**
* Extract the ad break watched policy for the specified media player item.
*
* @param item Associated media player item.
* @return a valid ad break watched policy.
*/
private AdBreakAsWatched extractAdBreakAsWatchedPolicy(MediaPlayerItem item) {
AdBreakAsWatched adBreakWatchedPolicy = AdBreakAsWatched.AD_BREAK_AS_WATCHED_ON_BEGIN;
if (item != null) {
MetadataNode metadata = (MetadataNode) item.getResource().getMetadata();
if (metadata != null) {
AdvertisingMetadata advertisingMetadata = (AdvertisingMetadata) metadata.getNode(DefaultMetadataKeys.ADVERTISING_METADATA.getValue());
if (advertisingMetadata != null) {
adBreakWatchedPolicy = advertisingMetadata.getAdBreakAsWatched();
}
}
}
return adBreakWatchedPolicy;
}
}
範例廣告廠
private AdvertisingFactory createPartialAdBreakFactory() {
return new AdvertisingFactory() {
@Override
public AdPolicySelector
createAdPolicySelector(MediaPlayerItem mediaPlayerItem) {
return new PartialAdBreakAdPolicySelector(mediaPlayerItem);
}
// Rest of the interface methods can be overridden as per your
// customization needs
// As shown next
@Override
public AdPolicySelector
createAdPolicySelector(MediaPlayerItem mediaPlayerItem) {
return new PartialAdBreakAdPolicySelector(mediaPlayerItem);
}
// . . .
}
}
向媒體播放器註冊我們的AdvertisingFactory
AdvertisingFactory advertisingFactory = createPartialAdBreakFactory();
if (advertisingFactory != null) {
mediaPlayer.registerAdClientFactory(advertisingFactory);
}
覆寫createAdPolicySelector方法
@Override
public AdPolicySelector
createAdPolicySelector(MediaPlayerItem mediaPlayerItem) {
return new PartialAdBreakAdPolicySelector(mediaPlayerItem);
}