mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
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 long contentDurationMs;
|
||||||
private AdPlaybackState adPlaybackState;
|
private AdPlaybackState adPlaybackState;
|
||||||
|
|
||||||
|
private boolean released;
|
||||||
|
|
||||||
// Fields tracking IMA's state.
|
// Fields tracking IMA's state.
|
||||||
|
|
||||||
/** Whether IMA has sent an ad event to pause content since the last resume content event. */
|
/** 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()));
|
adsId, ImaUtil.getAdGroupTimesUsForCuePoints(adsManager.getAdCuePoints()));
|
||||||
updateAdPlaybackState();
|
updateAdPlaybackState();
|
||||||
}
|
}
|
||||||
if (adDisplayContainer != null) {
|
for (OverlayInfo overlayInfo : adViewProvider.getAdOverlayInfos()) {
|
||||||
for (OverlayInfo overlayInfo : adViewProvider.getAdOverlayInfos()) {
|
adDisplayContainer.registerFriendlyObstruction(
|
||||||
adDisplayContainer.registerFriendlyObstruction(
|
imaFactory.createFriendlyObstruction(
|
||||||
imaFactory.createFriendlyObstruction(
|
overlayInfo.view,
|
||||||
overlayInfo.view,
|
ImaUtil.getFriendlyObstructionPurpose(overlayInfo.purpose),
|
||||||
ImaUtil.getFriendlyObstructionPurpose(overlayInfo.purpose),
|
overlayInfo.reasonDetail));
|
||||||
overlayInfo.reasonDetail));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,9 +326,7 @@ import java.util.Map;
|
|||||||
lastVolumePercent = getPlayerVolumePercent();
|
lastVolumePercent = getPlayerVolumePercent();
|
||||||
lastAdProgress = getAdVideoProgressUpdate();
|
lastAdProgress = getAdVideoProgressUpdate();
|
||||||
lastContentProgress = getContentVideoProgressUpdate();
|
lastContentProgress = getContentVideoProgressUpdate();
|
||||||
if (adDisplayContainer != null) {
|
adDisplayContainer.unregisterAllFriendlyObstructions();
|
||||||
adDisplayContainer.unregisterAllFriendlyObstructions();
|
|
||||||
}
|
|
||||||
player.removeListener(this);
|
player.removeListener(this);
|
||||||
this.player = null;
|
this.player = null;
|
||||||
eventListener = null;
|
eventListener = null;
|
||||||
@ -336,16 +334,18 @@ import java.util.Map;
|
|||||||
|
|
||||||
/** Releases all resources used by the ad tag loader. */
|
/** Releases all resources used by the ad tag loader. */
|
||||||
public void release() {
|
public void release() {
|
||||||
|
if (released) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
released = true;
|
||||||
pendingAdRequestContext = null;
|
pendingAdRequestContext = null;
|
||||||
destroyAdsManager();
|
destroyAdsManager();
|
||||||
if (adsLoader != null) {
|
adsLoader.removeAdsLoadedListener(componentListener);
|
||||||
adsLoader.removeAdsLoadedListener(componentListener);
|
adsLoader.removeAdErrorListener(componentListener);
|
||||||
adsLoader.removeAdErrorListener(componentListener);
|
if (configuration.applicationAdErrorListener != null) {
|
||||||
if (configuration.applicationAdErrorListener != null) {
|
adsLoader.removeAdErrorListener(configuration.applicationAdErrorListener);
|
||||||
adsLoader.removeAdErrorListener(configuration.applicationAdErrorListener);
|
|
||||||
}
|
|
||||||
adsLoader.release();
|
|
||||||
}
|
}
|
||||||
|
adsLoader.release();
|
||||||
imaPausedContent = false;
|
imaPausedContent = false;
|
||||||
imaAdState = IMA_AD_STATE_NONE;
|
imaAdState = IMA_AD_STATE_NONE;
|
||||||
imaAdMediaInfo = null;
|
imaAdMediaInfo = null;
|
||||||
@ -394,27 +394,15 @@ import java.util.Map;
|
|||||||
}
|
}
|
||||||
checkArgument(timeline.getPeriodCount() == 1);
|
checkArgument(timeline.getPeriodCount() == 1);
|
||||||
this.timeline = timeline;
|
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);
|
contentDurationMs = C.usToMs(contentDurationUs);
|
||||||
if (contentDurationUs != C.TIME_UNSET) {
|
if (contentDurationUs != adPlaybackState.contentDurationUs) {
|
||||||
adPlaybackState = adPlaybackState.withContentDurationUs(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();
|
updateAdPlaybackState();
|
||||||
}
|
}
|
||||||
|
long contentPositionMs = getContentPeriodPositionMs(player, timeline, period);
|
||||||
|
maybeInitializeAdsManager(contentPositionMs, contentDurationMs);
|
||||||
handleTimelineOrPositionChanged();
|
handleTimelineOrPositionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,12 +503,33 @@ import java.util.Map;
|
|||||||
return adsLoader;
|
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
|
* Configures ads rendering for starting playback, returning the settings for the IMA SDK or
|
||||||
* {@code null} if no ads should play.
|
* {@code null} if no ads should play.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
private AdsRenderingSettings setupAdsRendering() {
|
private AdsRenderingSettings setupAdsRendering(long contentPositionMs, long contentDurationMs) {
|
||||||
AdsRenderingSettings adsRenderingSettings = imaFactory.createAdsRenderingSettings();
|
AdsRenderingSettings adsRenderingSettings = imaFactory.createAdsRenderingSettings();
|
||||||
adsRenderingSettings.setEnablePreloading(true);
|
adsRenderingSettings.setEnablePreloading(true);
|
||||||
adsRenderingSettings.setMimeTypes(
|
adsRenderingSettings.setMimeTypes(
|
||||||
@ -541,7 +550,6 @@ import java.util.Map;
|
|||||||
|
|
||||||
// Skip ads based on the start position as required.
|
// Skip ads based on the start position as required.
|
||||||
long[] adGroupTimesUs = adPlaybackState.adGroupTimesUs;
|
long[] adGroupTimesUs = adPlaybackState.adGroupTimesUs;
|
||||||
long contentPositionMs = getContentPeriodPositionMs(checkNotNull(player), timeline, period);
|
|
||||||
int adGroupForPositionIndex =
|
int adGroupForPositionIndex =
|
||||||
adPlaybackState.getAdGroupIndexForPositionUs(
|
adPlaybackState.getAdGroupIndexForPositionUs(
|
||||||
C.msToUs(contentPositionMs), C.msToUs(contentDurationMs));
|
C.msToUs(contentPositionMs), C.msToUs(contentDurationMs));
|
||||||
@ -957,7 +965,6 @@ import java.util.Map;
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
checkNotNull(player);
|
|
||||||
imaAdState = IMA_AD_STATE_NONE;
|
imaAdState = IMA_AD_STATE_NONE;
|
||||||
stopUpdatingAdProgress();
|
stopUpdatingAdProgress();
|
||||||
// TODO: Handle the skipped event so the ad can be marked as skipped rather than played.
|
// 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(
|
private static long getContentPeriodPositionMs(
|
||||||
Player player, Timeline timeline, Timeline.Period period) {
|
Player player, Timeline timeline, Timeline.Period period) {
|
||||||
long contentWindowPositionMs = player.getContentPosition();
|
long contentWindowPositionMs = player.getContentPosition();
|
||||||
return contentWindowPositionMs
|
if (timeline.isEmpty()) {
|
||||||
- (timeline.isEmpty()
|
return contentWindowPositionMs;
|
||||||
? 0
|
} else {
|
||||||
: timeline.getPeriod(/* periodIndex= */ 0, period).getPositionInWindowMs());
|
return contentWindowPositionMs
|
||||||
|
- timeline.getPeriod(player.getCurrentPeriodIndex(), period).getPositionInWindowMs();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasMidrollAdGroups(long[] adGroupTimesUs) {
|
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.AdDisplayContainer;
|
||||||
import com.google.ads.interactivemedia.v3.api.AdErrorEvent.AdErrorListener;
|
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.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.AdsManager;
|
||||||
import com.google.ads.interactivemedia.v3.api.AdsRenderingSettings;
|
import com.google.ads.interactivemedia.v3.api.AdsRenderingSettings;
|
||||||
import com.google.ads.interactivemedia.v3.api.AdsRequest;
|
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.ExoPlayerLibraryInfo;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.source.MediaSourceFactory;
|
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.source.ads.AdsMediaSource;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
@ -61,8 +61,7 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link com.google.android.exoplayer2.source.ads.AdsLoader} using the IMA SDK. All methods must be
|
* {@link AdsLoader} using the IMA SDK. All methods must be called on the main thread.
|
||||||
* called on the main thread.
|
|
||||||
*
|
*
|
||||||
* <p>The player instance that will play the loaded ads must be set before playback using {@link
|
* <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
|
* #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
|
* href="https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side/omsdk">IMA
|
||||||
* SDK Open Measurement documentation</a> for more information.
|
* SDK Open Measurement documentation</a> for more information.
|
||||||
*/
|
*/
|
||||||
public final class ImaAdsLoader
|
public final class ImaAdsLoader implements Player.EventListener, AdsLoader {
|
||||||
implements Player.EventListener, com.google.android.exoplayer2.source.ads.AdsLoader {
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ExoPlayerLibraryInfo.registerModule("goog.exo.ima");
|
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
|
* Sets a listener for ad errors that will be passed to {@link
|
||||||
* AdsLoader#addAdErrorListener(AdErrorListener)} and {@link
|
* com.google.ads.interactivemedia.v3.api.AdsLoader#addAdErrorListener(AdErrorListener)} and
|
||||||
* AdsManager#addAdErrorListener(AdErrorListener)}.
|
* {@link AdsManager#addAdErrorListener(AdErrorListener)}.
|
||||||
*
|
*
|
||||||
* @param adErrorListener The ad error listener.
|
* @param adErrorListener The ad error listener.
|
||||||
* @return This builder, for convenience.
|
* @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
|
* Returns the underlying {@link com.google.ads.interactivemedia.v3.api.AdsLoader} wrapped by this
|
||||||
* not been requested yet.
|
* instance, or {@code null} if ads have not been requested yet.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public AdsLoader getAdsLoader() {
|
public com.google.ads.interactivemedia.v3.api.AdsLoader getAdsLoader() {
|
||||||
return adTagLoader != null ? adTagLoader.getAdsLoader() : null;
|
return adTagLoader != null ? adTagLoader.getAdsLoader() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,8 +398,8 @@ public final class ImaAdsLoader
|
|||||||
* AdDisplayContainer#registerFriendlyObstruction(FriendlyObstruction)} will be unregistered
|
* AdDisplayContainer#registerFriendlyObstruction(FriendlyObstruction)} will be unregistered
|
||||||
* automatically when the media source detaches from this instance. It is therefore necessary to
|
* 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
|
* 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
|
* the {@link AdViewProvider} when creating the media source to benefit from automatic
|
||||||
* media source to benefit from automatic registration.
|
* registration.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public AdDisplayContainer getAdDisplayContainer() {
|
public AdDisplayContainer getAdDisplayContainer() {
|
||||||
@ -448,7 +446,7 @@ public final class ImaAdsLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// com.google.android.exoplayer2.source.ads.AdsLoader implementation.
|
// AdsLoader implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPlayer(@Nullable Player player) {
|
public void setPlayer(@Nullable Player player) {
|
||||||
@ -576,7 +574,7 @@ public final class ImaAdsLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AdsLoader createAdsLoader(
|
public com.google.ads.interactivemedia.v3.api.AdsLoader createAdsLoader(
|
||||||
Context context, ImaSdkSettings imaSdkSettings, AdDisplayContainer adDisplayContainer) {
|
Context context, ImaSdkSettings imaSdkSettings, AdDisplayContainer adDisplayContainer) {
|
||||||
return ImaSdkFactory.getInstance()
|
return ImaSdkFactory.getInstance()
|
||||||
.createAdsLoader(context, imaSdkSettings, adDisplayContainer);
|
.createAdsLoader(context, imaSdkSettings, adDisplayContainer);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user