/** * Sets the slots for displaying companion ads. Individual slots can be created using {@link * ImaSdkFactory#createCompanionAdSlot()}. * * @param companionSlots Slots for displaying companion ads. * @see AdDisplayContainer#setCompanionSlots(Collection) */ public void setCompanionSlots(Collection<CompanionAdSlot> companionSlots) { adDisplayContainer.setCompanionSlots(companionSlots); }
private static boolean isAdGroupLoadError(AdError adError) { // TODO: Find out what other errors need to be handled (if any), and whether each one relates to // a single ad, ad group or the whole timeline. return adError.getErrorCode() == AdErrorCode.VAST_LINEAR_ASSET_MISMATCH; }
@Override public com.google.ads.interactivemedia.v3.api.AdsLoader createAdsLoader( Context context, ImaSdkSettings imaSdkSettings) { return ImaSdkFactory.getInstance().createAdsLoader(context, imaSdkSettings); } }
/** * Requests ads, if they have not already been requested. Must be called on the main thread. * * <p>Ads will be requested automatically when the player is prepared if this method has not been * called, so it is only necessary to call this method if you want to request ads before preparing * the player. * * @param adUiViewGroup A {@link ViewGroup} on top of the player that will show any ad UI. */ public void requestAds(ViewGroup adUiViewGroup) { if (adPlaybackState != null || adsManager != null || pendingAdRequestContext != null) { // Ads have already been requested. return; } adDisplayContainer.setAdContainer(adUiViewGroup); pendingAdRequestContext = new Object(); AdsRequest request = imaFactory.createAdsRequest(); if (adTagUri != null) { request.setAdTagUrl(adTagUri.toString()); } else /* adsResponse != null */ { request.setAdsResponse(adsResponse); } if (vastLoadTimeoutMs != TIMEOUT_UNSET) { request.setVastLoadTimeout(vastLoadTimeoutMs); } request.setAdDisplayContainer(adDisplayContainer); request.setContentProgressProvider(this); request.setUserRequestContext(pendingAdRequestContext); adsLoader.requestAds(request); }
@Override public AdDisplayContainer createAdDisplayContainer() { return ImaSdkFactory.getInstance().createAdDisplayContainer(); }
@Override public AdsRequest createAdsRequest() { return ImaSdkFactory.getInstance().createAdsRequest(); }
@Override public void onAdsManagerLoaded(AdsManagerLoadedEvent adsManagerLoadedEvent) { AdsManager adsManager = adsManagerLoadedEvent.getAdsManager(); if (!Util.areEqual(pendingAdRequestContext, adsManagerLoadedEvent.getUserRequestContext())) { adsManager.destroy(); return; } pendingAdRequestContext = null; this.adsManager = adsManager; adsManager.addAdErrorListener(this); adsManager.addAdEventListener(this); if (adEventListener != null) { adsManager.addAdEventListener(adEventListener); } if (player != null) { // If a player is attached already, start playback immediately. try { startAdPlayback(); } catch (Exception e) { maybeNotifyInternalError("onAdsManagerLoaded", e); } } }
@Override public void release() { pendingAdRequestContext = null; if (adsManager != null) { adsManager.destroy(); adsManager = null; } adsLoader.removeAdsLoadedListener(/* adsLoadedListener= */ this); adsLoader.removeAdErrorListener(/* adErrorListener= */ this); imaPausedContent = false; imaAdState = IMA_AD_STATE_NONE; pendingAdLoadError = null; adPlaybackState = AdPlaybackState.NONE; updateAdPlaybackState(); }
@Override public AdsRenderingSettings createAdsRenderingSettings() { return ImaSdkFactory.getInstance().createAdsRenderingSettings(); }
@Override public ImaSdkSettings createImaSdkSettings() { return ImaSdkFactory.getInstance().createImaSdkSettings(); }
@Override public void attachPlayer(ExoPlayer player, EventListener eventListener, ViewGroup adUiViewGroup) { Assertions.checkArgument(player.getApplicationLooper() == Looper.getMainLooper()); this.player = player; this.eventListener = eventListener; lastVolumePercentage = 0; lastAdProgress = null; lastContentProgress = null; adDisplayContainer.setAdContainer(adUiViewGroup); player.addListener(this); maybeNotifyPendingAdLoadError(); if (adPlaybackState != null) { // Pass the ad playback state to the player, and resume ads if necessary. eventListener.onAdPlaybackState(adPlaybackState); if (imaPausedContent && player.getPlayWhenReady()) { adsManager.resume(); } } else if (adsManager != null) { // Ads have loaded but the ads manager is not initialized. startAdPlayback(); } else { // Ads haven't loaded yet, so request them. requestAds(adUiViewGroup); } }
@Test public void testAttachPlayer_setsAdUiViewGroup() { setupPlayback(CONTENT_TIMELINE, PREROLL_ADS_DURATIONS_US, PREROLL_CUE_POINTS_SECONDS); imaAdsLoader.attachPlayer(fakeExoPlayer, adsLoaderListener, adUiViewGroup); verify(adDisplayContainer, atLeastOnce()).setAdContainer(adUiViewGroup); }
@Test public void testBuilder_overridesPlayerType() { when(imaSdkSettings.getPlayerType()).thenReturn("test player type"); setupPlayback(CONTENT_TIMELINE, PREROLL_ADS_DURATIONS_US, PREROLL_CUE_POINTS_SECONDS); verify(imaSdkSettings).setPlayerType("google/exo.ext.ima"); }
private void setupPlayback(Timeline contentTimeline, long[][] adDurationsUs, Float[] cuePoints) { fakeExoPlayer = new FakePlayer(); adsLoaderListener = new TestAdsLoaderListener(fakeExoPlayer, contentTimeline, adDurationsUs); when(adsManager.getAdCuePoints()).thenReturn(Arrays.asList(cuePoints)); imaAdsLoader = new ImaAdsLoader.Builder(RuntimeEnvironment.application) .setImaFactory(testImaFactory) .setImaSdkSettings(imaSdkSettings) .buildForAdTag(TEST_URI); }
@Override public void onAdEvent(AdEvent adEvent) { AdEventType adEventType = adEvent.getType(); if (DEBUG) { Log.d(TAG, "onAdEvent: " + adEventType); } if (adsManager == null) { Log.w(TAG, "Ignoring AdEvent after release: " + adEvent); return; } try { handleAdEvent(adEvent); } catch (Exception e) { maybeNotifyInternalError("onAdEvent", e); } }
@Override public void onAdError(AdErrorEvent adErrorEvent) { AdError error = adErrorEvent.getError(); if (DEBUG) { Log.d(TAG, "onAdError", error); } if (adsManager == null) { // No ads were loaded, so allow playback to start without any ads. pendingAdRequestContext = null; adPlaybackState = new AdPlaybackState(); updateAdPlaybackState(); } else if (isAdGroupLoadError(error)) { try { handleAdGroupLoadError(error); } catch (Exception e) { maybeNotifyInternalError("onAdError", e); } } if (pendingAdLoadError == null) { pendingAdLoadError = AdLoadException.createForAllAds(error); } maybeNotifyPendingAdLoadError(); }
@Override public Object getUserRequestContext() { return adsRequest.getUserRequestContext(); } });
@Override public void requestAds(AdsRequest adsRequest) { for (AdsLoadedListener listener : adsLoadedListeners) { listener.onAdsManagerLoaded( new AdsManagerLoadedEvent() { @Override public AdsManager getAdsManager() { return adsManager; } @Override public StreamManager getStreamManager() { throw new UnsupportedOperationException(); } @Override public Object getUserRequestContext() { return adsRequest.getUserRequestContext(); } }); } }
private void checkForContentComplete() { if (contentDurationMs != C.TIME_UNSET && pendingContentPositionMs == C.TIME_UNSET && player.getContentPosition() + END_OF_CONTENT_POSITION_THRESHOLD_MS >= contentDurationMs && !sentContentComplete) { adsLoader.contentComplete(); if (DEBUG) { Log.d(TAG, "adsLoader.contentComplete"); } sentContentComplete = true; // After sending content complete IMA will not poll the content position, so set the expected // ad group index. expectedAdGroupIndex = adPlaybackState.getAdGroupIndexForPositionUs(C.msToUs(contentDurationMs)); } }
@Override public void detachPlayer() { if (adsManager != null && imaPausedContent) { adPlaybackState = adPlaybackState.withAdResumePositionUs( playingAd ? C.msToUs(player.getCurrentPosition()) : 0); adsManager.pause(); } lastVolumePercentage = getVolume(); lastAdProgress = getAdProgress(); lastContentProgress = getContentProgress(); player.removeListener(this); player = null; eventListener = null; }