Clean up AdTagLoader and ImaAdsLoader
In preparation for adding support for ads in playlists: - Make releasing a no-op if the instance was already released - Remove null checks on non-null `adDisplayContainer` and `adsLoader` - Move initializing the ads manager into a private method as it will need to be called from two places soon. - Misc other cleanup. Issue: #3750 PiperOrigin-RevId: 341021493
This commit is contained in:
parent
764e5e8141
commit
ae4cf9f1da
@ -152,6 +152,8 @@ import java.util.Map;
|
||||
private long contentDurationMs;
|
||||
private AdPlaybackState adPlaybackState;
|
||||
|
||||
private boolean released;
|
||||
|
||||
// Fields tracking IMA's state.
|
||||
|
||||
/** Whether IMA has sent an ad event to pause content since the last resume content event. */
|
||||
@ -300,14 +302,12 @@ import java.util.Map;
|
||||
adsId, ImaUtil.getAdGroupTimesUsForCuePoints(adsManager.getAdCuePoints()));
|
||||
updateAdPlaybackState();
|
||||
}
|
||||
if (adDisplayContainer != null) {
|
||||
for (OverlayInfo overlayInfo : adViewProvider.getAdOverlayInfos()) {
|
||||
adDisplayContainer.registerFriendlyObstruction(
|
||||
imaFactory.createFriendlyObstruction(
|
||||
overlayInfo.view,
|
||||
ImaUtil.getFriendlyObstructionPurpose(overlayInfo.purpose),
|
||||
overlayInfo.reasonDetail));
|
||||
}
|
||||
for (OverlayInfo overlayInfo : adViewProvider.getAdOverlayInfos()) {
|
||||
adDisplayContainer.registerFriendlyObstruction(
|
||||
imaFactory.createFriendlyObstruction(
|
||||
overlayInfo.view,
|
||||
ImaUtil.getFriendlyObstructionPurpose(overlayInfo.purpose),
|
||||
overlayInfo.reasonDetail));
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,9 +326,7 @@ import java.util.Map;
|
||||
lastVolumePercent = getPlayerVolumePercent();
|
||||
lastAdProgress = getAdVideoProgressUpdate();
|
||||
lastContentProgress = getContentVideoProgressUpdate();
|
||||
if (adDisplayContainer != null) {
|
||||
adDisplayContainer.unregisterAllFriendlyObstructions();
|
||||
}
|
||||
adDisplayContainer.unregisterAllFriendlyObstructions();
|
||||
player.removeListener(this);
|
||||
this.player = null;
|
||||
eventListener = null;
|
||||
@ -336,16 +334,18 @@ import java.util.Map;
|
||||
|
||||
/** Releases all resources used by the ad tag loader. */
|
||||
public void release() {
|
||||
if (released) {
|
||||
return;
|
||||
}
|
||||
released = true;
|
||||
pendingAdRequestContext = null;
|
||||
destroyAdsManager();
|
||||
if (adsLoader != null) {
|
||||
adsLoader.removeAdsLoadedListener(componentListener);
|
||||
adsLoader.removeAdErrorListener(componentListener);
|
||||
if (configuration.applicationAdErrorListener != null) {
|
||||
adsLoader.removeAdErrorListener(configuration.applicationAdErrorListener);
|
||||
}
|
||||
adsLoader.release();
|
||||
adsLoader.removeAdsLoadedListener(componentListener);
|
||||
adsLoader.removeAdErrorListener(componentListener);
|
||||
if (configuration.applicationAdErrorListener != null) {
|
||||
adsLoader.removeAdErrorListener(configuration.applicationAdErrorListener);
|
||||
}
|
||||
adsLoader.release();
|
||||
imaPausedContent = false;
|
||||
imaAdState = IMA_AD_STATE_NONE;
|
||||
imaAdMediaInfo = null;
|
||||
@ -394,27 +394,15 @@ import java.util.Map;
|
||||
}
|
||||
checkArgument(timeline.getPeriodCount() == 1);
|
||||
this.timeline = timeline;
|
||||
long contentDurationUs = timeline.getPeriod(/* periodIndex= */ 0, period).durationUs;
|
||||
Player player = checkNotNull(this.player);
|
||||
long contentDurationUs = timeline.getPeriod(player.getCurrentPeriodIndex(), period).durationUs;
|
||||
contentDurationMs = C.usToMs(contentDurationUs);
|
||||
if (contentDurationUs != C.TIME_UNSET) {
|
||||
if (contentDurationUs != adPlaybackState.contentDurationUs) {
|
||||
adPlaybackState = adPlaybackState.withContentDurationUs(contentDurationUs);
|
||||
}
|
||||
@Nullable AdsManager adsManager = this.adsManager;
|
||||
if (!isAdsManagerInitialized && adsManager != null) {
|
||||
isAdsManagerInitialized = true;
|
||||
@Nullable AdsRenderingSettings adsRenderingSettings = setupAdsRendering();
|
||||
if (adsRenderingSettings == null) {
|
||||
// There are no ads to play.
|
||||
destroyAdsManager();
|
||||
} else {
|
||||
adsManager.init(adsRenderingSettings);
|
||||
adsManager.start();
|
||||
if (configuration.debugModeEnabled) {
|
||||
Log.d(TAG, "Initialized with ads rendering settings: " + adsRenderingSettings);
|
||||
}
|
||||
}
|
||||
updateAdPlaybackState();
|
||||
}
|
||||
long contentPositionMs = getContentPeriodPositionMs(player, timeline, period);
|
||||
maybeInitializeAdsManager(contentPositionMs, contentDurationMs);
|
||||
handleTimelineOrPositionChanged();
|
||||
}
|
||||
|
||||
@ -515,12 +503,33 @@ import java.util.Map;
|
||||
return adsLoader;
|
||||
}
|
||||
|
||||
private void maybeInitializeAdsManager(long contentPositionMs, long contentDurationMs) {
|
||||
@Nullable AdsManager adsManager = this.adsManager;
|
||||
if (!isAdsManagerInitialized && adsManager != null) {
|
||||
isAdsManagerInitialized = true;
|
||||
@Nullable
|
||||
AdsRenderingSettings adsRenderingSettings =
|
||||
setupAdsRendering(contentPositionMs, contentDurationMs);
|
||||
if (adsRenderingSettings == null) {
|
||||
// There are no ads to play.
|
||||
destroyAdsManager();
|
||||
} else {
|
||||
adsManager.init(adsRenderingSettings);
|
||||
adsManager.start();
|
||||
if (configuration.debugModeEnabled) {
|
||||
Log.d(TAG, "Initialized with ads rendering settings: " + adsRenderingSettings);
|
||||
}
|
||||
}
|
||||
updateAdPlaybackState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures ads rendering for starting playback, returning the settings for the IMA SDK or
|
||||
* {@code null} if no ads should play.
|
||||
*/
|
||||
@Nullable
|
||||
private AdsRenderingSettings setupAdsRendering() {
|
||||
private AdsRenderingSettings setupAdsRendering(long contentPositionMs, long contentDurationMs) {
|
||||
AdsRenderingSettings adsRenderingSettings = imaFactory.createAdsRenderingSettings();
|
||||
adsRenderingSettings.setEnablePreloading(true);
|
||||
adsRenderingSettings.setMimeTypes(
|
||||
@ -541,7 +550,6 @@ import java.util.Map;
|
||||
|
||||
// Skip ads based on the start position as required.
|
||||
long[] adGroupTimesUs = adPlaybackState.adGroupTimesUs;
|
||||
long contentPositionMs = getContentPeriodPositionMs(checkNotNull(player), timeline, period);
|
||||
int adGroupForPositionIndex =
|
||||
adPlaybackState.getAdGroupIndexForPositionUs(
|
||||
C.msToUs(contentPositionMs), C.msToUs(contentDurationMs));
|
||||
@ -957,7 +965,6 @@ import java.util.Map;
|
||||
}
|
||||
return;
|
||||
}
|
||||
checkNotNull(player);
|
||||
imaAdState = IMA_AD_STATE_NONE;
|
||||
stopUpdatingAdProgress();
|
||||
// TODO: Handle the skipped event so the ad can be marked as skipped rather than played.
|
||||
@ -1155,10 +1162,12 @@ import java.util.Map;
|
||||
private static long getContentPeriodPositionMs(
|
||||
Player player, Timeline timeline, Timeline.Period period) {
|
||||
long contentWindowPositionMs = player.getContentPosition();
|
||||
return contentWindowPositionMs
|
||||
- (timeline.isEmpty()
|
||||
? 0
|
||||
: timeline.getPeriod(/* periodIndex= */ 0, period).getPositionInWindowMs());
|
||||
if (timeline.isEmpty()) {
|
||||
return contentWindowPositionMs;
|
||||
} else {
|
||||
return contentWindowPositionMs
|
||||
- timeline.getPeriod(player.getCurrentPeriodIndex(), period).getPositionInWindowMs();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasMidrollAdGroups(long[] adGroupTimesUs) {
|
||||
|
@ -31,7 +31,6 @@ import androidx.annotation.VisibleForTesting;
|
||||
import com.google.ads.interactivemedia.v3.api.AdDisplayContainer;
|
||||
import com.google.ads.interactivemedia.v3.api.AdErrorEvent.AdErrorListener;
|
||||
import com.google.ads.interactivemedia.v3.api.AdEvent.AdEventListener;
|
||||
import com.google.ads.interactivemedia.v3.api.AdsLoader;
|
||||
import com.google.ads.interactivemedia.v3.api.AdsManager;
|
||||
import com.google.ads.interactivemedia.v3.api.AdsRenderingSettings;
|
||||
import com.google.ads.interactivemedia.v3.api.AdsRequest;
|
||||
@ -46,6 +45,7 @@ import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.source.MediaSourceFactory;
|
||||
import com.google.android.exoplayer2.source.ads.AdsLoader;
|
||||
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
|
||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
@ -61,8 +61,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* {@link com.google.android.exoplayer2.source.ads.AdsLoader} using the IMA SDK. All methods must be
|
||||
* called on the main thread.
|
||||
* {@link AdsLoader} using the IMA SDK. All methods must be called on the main thread.
|
||||
*
|
||||
* <p>The player instance that will play the loaded ads must be set before playback using {@link
|
||||
* #setPlayer(Player)}. If the ads loader is no longer required, it must be released by calling
|
||||
@ -83,8 +82,7 @@ import java.util.Set;
|
||||
* href="https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side/omsdk">IMA
|
||||
* SDK Open Measurement documentation</a> for more information.
|
||||
*/
|
||||
public final class ImaAdsLoader
|
||||
implements Player.EventListener, com.google.android.exoplayer2.source.ads.AdsLoader {
|
||||
public final class ImaAdsLoader implements Player.EventListener, AdsLoader {
|
||||
|
||||
static {
|
||||
ExoPlayerLibraryInfo.registerModule("goog.exo.ima");
|
||||
@ -154,8 +152,8 @@ public final class ImaAdsLoader
|
||||
|
||||
/**
|
||||
* Sets a listener for ad errors that will be passed to {@link
|
||||
* AdsLoader#addAdErrorListener(AdErrorListener)} and {@link
|
||||
* AdsManager#addAdErrorListener(AdErrorListener)}.
|
||||
* com.google.ads.interactivemedia.v3.api.AdsLoader#addAdErrorListener(AdErrorListener)} and
|
||||
* {@link AdsManager#addAdErrorListener(AdErrorListener)}.
|
||||
*
|
||||
* @param adErrorListener The ad error listener.
|
||||
* @return This builder, for convenience.
|
||||
@ -384,11 +382,11 @@ public final class ImaAdsLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the underlying {@link AdsLoader} wrapped by this instance, or {@code null} if ads have
|
||||
* not been requested yet.
|
||||
* Returns the underlying {@link com.google.ads.interactivemedia.v3.api.AdsLoader} wrapped by this
|
||||
* instance, or {@code null} if ads have not been requested yet.
|
||||
*/
|
||||
@Nullable
|
||||
public AdsLoader getAdsLoader() {
|
||||
public com.google.ads.interactivemedia.v3.api.AdsLoader getAdsLoader() {
|
||||
return adTagLoader != null ? adTagLoader.getAdsLoader() : null;
|
||||
}
|
||||
|
||||
@ -400,8 +398,8 @@ public final class ImaAdsLoader
|
||||
* AdDisplayContainer#registerFriendlyObstruction(FriendlyObstruction)} will be unregistered
|
||||
* automatically when the media source detaches from this instance. It is therefore necessary to
|
||||
* re-register views each time the ads loader is reused. Alternatively, provide overlay views via
|
||||
* the {@link com.google.android.exoplayer2.source.ads.AdsLoader.AdViewProvider} when creating the
|
||||
* media source to benefit from automatic registration.
|
||||
* the {@link AdViewProvider} when creating the media source to benefit from automatic
|
||||
* registration.
|
||||
*/
|
||||
@Nullable
|
||||
public AdDisplayContainer getAdDisplayContainer() {
|
||||
@ -448,7 +446,7 @@ public final class ImaAdsLoader
|
||||
}
|
||||
}
|
||||
|
||||
// com.google.android.exoplayer2.source.ads.AdsLoader implementation.
|
||||
// AdsLoader implementation.
|
||||
|
||||
@Override
|
||||
public void setPlayer(@Nullable Player player) {
|
||||
@ -576,7 +574,7 @@ public final class ImaAdsLoader
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdsLoader createAdsLoader(
|
||||
public com.google.ads.interactivemedia.v3.api.AdsLoader createAdsLoader(
|
||||
Context context, ImaSdkSettings imaSdkSettings, AdDisplayContainer adDisplayContainer) {
|
||||
return ImaSdkFactory.getInstance()
|
||||
.createAdsLoader(context, imaSdkSettings, adDisplayContainer);
|
||||
|
Loading…
x
Reference in New Issue
Block a user