mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Convergence: Continue decoupling UI from Core
Move AdsLoader inner classes that are also required by the UI module into common. PiperOrigin-RevId: 367414679
This commit is contained in:
parent
53166e9a78
commit
199b9d1689
15 changed files with 162 additions and 160 deletions
|
|
@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
@ -38,8 +37,6 @@ import com.google.android.exoplayer2.decoder.DecoderCounters;
|
||||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||||
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
|
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
import com.google.android.exoplayer2.source.MediaSource;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsLoader;
|
|
||||||
import com.google.android.exoplayer2.source.ads.AdsLoader.AdViewProvider;
|
|
||||||
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
|
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
|
||||||
import com.google.android.exoplayer2.testutil.ActionSchedule;
|
import com.google.android.exoplayer2.testutil.ActionSchedule;
|
||||||
import com.google.android.exoplayer2.testutil.ExoHostedTest;
|
import com.google.android.exoplayer2.testutil.ExoHostedTest;
|
||||||
|
|
@ -51,7 +48,6 @@ import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -251,18 +247,7 @@ public final class ImaPlaybackTest {
|
||||||
/* adsId= */ adTagDataSpec.uri,
|
/* adsId= */ adTagDataSpec.uri,
|
||||||
new DefaultMediaSourceFactory(dataSourceFactory),
|
new DefaultMediaSourceFactory(dataSourceFactory),
|
||||||
Assertions.checkNotNull(imaAdsLoader),
|
Assertions.checkNotNull(imaAdsLoader),
|
||||||
new AdViewProvider() {
|
() -> overlayFrameLayout);
|
||||||
|
|
||||||
@Override
|
|
||||||
public ViewGroup getAdViewGroup() {
|
|
||||||
return overlayFrameLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ImmutableList<AdsLoader.OverlayInfo> getAdOverlayInfos() {
|
|
||||||
return ImmutableList.of();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -55,12 +55,12 @@ import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
|
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsLoader.AdViewProvider;
|
|
||||||
import com.google.android.exoplayer2.source.ads.AdsLoader.EventListener;
|
import com.google.android.exoplayer2.source.ads.AdsLoader.EventListener;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsLoader.OverlayInfo;
|
|
||||||
import com.google.android.exoplayer2.source.ads.AdsMediaSource.AdLoadException;
|
import com.google.android.exoplayer2.source.ads.AdsMediaSource.AdLoadException;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionUtil;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionUtil;
|
||||||
|
import com.google.android.exoplayer2.ui.AdOverlayInfo;
|
||||||
|
import com.google.android.exoplayer2.ui.AdViewProvider;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer2.util.Log;
|
import com.google.android.exoplayer2.util.Log;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
|
|
@ -318,7 +318,7 @@ import java.util.Map;
|
||||||
new AdPlaybackState(adsId, getAdGroupTimesUsForCuePoints(adsManager.getAdCuePoints()));
|
new AdPlaybackState(adsId, getAdGroupTimesUsForCuePoints(adsManager.getAdCuePoints()));
|
||||||
updateAdPlaybackState();
|
updateAdPlaybackState();
|
||||||
}
|
}
|
||||||
for (OverlayInfo overlayInfo : adViewProvider.getAdOverlayInfos()) {
|
for (AdOverlayInfo overlayInfo : adViewProvider.getAdOverlayInfos()) {
|
||||||
adDisplayContainer.registerFriendlyObstruction(
|
adDisplayContainer.registerFriendlyObstruction(
|
||||||
imaFactory.createFriendlyObstruction(
|
imaFactory.createFriendlyObstruction(
|
||||||
overlayInfo.view,
|
overlayInfo.view,
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ import com.google.android.exoplayer2.Timeline;
|
||||||
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.AdsLoader;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
|
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
|
||||||
|
import com.google.android.exoplayer2.ui.AdViewProvider;
|
||||||
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;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ import com.google.ads.interactivemedia.v3.api.UiElement;
|
||||||
import com.google.ads.interactivemedia.v3.api.player.VideoAdPlayer;
|
import com.google.ads.interactivemedia.v3.api.player.VideoAdPlayer;
|
||||||
import com.google.ads.interactivemedia.v3.api.player.VideoProgressUpdate;
|
import com.google.ads.interactivemedia.v3.api.player.VideoProgressUpdate;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsLoader.OverlayInfo;
|
import com.google.android.exoplayer2.ui.AdOverlayInfo;
|
||||||
import com.google.android.exoplayer2.upstream.DataSchemeDataSource;
|
import com.google.android.exoplayer2.upstream.DataSchemeDataSource;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
|
|
@ -138,18 +138,18 @@ import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the IMA {@link FriendlyObstructionPurpose} corresponding to the given {@link
|
* Returns the IMA {@link FriendlyObstructionPurpose} corresponding to the given {@link
|
||||||
* OverlayInfo#purpose}.
|
* AdOverlayInfo#purpose}.
|
||||||
*/
|
*/
|
||||||
public static FriendlyObstructionPurpose getFriendlyObstructionPurpose(
|
public static FriendlyObstructionPurpose getFriendlyObstructionPurpose(
|
||||||
@OverlayInfo.Purpose int purpose) {
|
@AdOverlayInfo.Purpose int purpose) {
|
||||||
switch (purpose) {
|
switch (purpose) {
|
||||||
case OverlayInfo.PURPOSE_CONTROLS:
|
case AdOverlayInfo.PURPOSE_CONTROLS:
|
||||||
return FriendlyObstructionPurpose.VIDEO_CONTROLS;
|
return FriendlyObstructionPurpose.VIDEO_CONTROLS;
|
||||||
case OverlayInfo.PURPOSE_CLOSE_AD:
|
case AdOverlayInfo.PURPOSE_CLOSE_AD:
|
||||||
return FriendlyObstructionPurpose.CLOSE_AD;
|
return FriendlyObstructionPurpose.CLOSE_AD;
|
||||||
case OverlayInfo.PURPOSE_NOT_VISIBLE:
|
case AdOverlayInfo.PURPOSE_NOT_VISIBLE:
|
||||||
return FriendlyObstructionPurpose.NOT_VISIBLE;
|
return FriendlyObstructionPurpose.NOT_VISIBLE;
|
||||||
case OverlayInfo.PURPOSE_OTHER:
|
case AdOverlayInfo.PURPOSE_OTHER:
|
||||||
default:
|
default:
|
||||||
return FriendlyObstructionPurpose.OTHER;
|
return FriendlyObstructionPurpose.OTHER;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,8 @@ import com.google.android.exoplayer2.source.ads.AdsMediaSource.AdLoadException;
|
||||||
import com.google.android.exoplayer2.testutil.FakeMediaSource;
|
import com.google.android.exoplayer2.testutil.FakeMediaSource;
|
||||||
import com.google.android.exoplayer2.testutil.FakeTimeline;
|
import com.google.android.exoplayer2.testutil.FakeTimeline;
|
||||||
import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition;
|
import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition;
|
||||||
|
import com.google.android.exoplayer2.ui.AdOverlayInfo;
|
||||||
|
import com.google.android.exoplayer2.ui.AdViewProvider;
|
||||||
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;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
|
|
@ -129,8 +131,8 @@ public final class ImaAdsLoaderTest {
|
||||||
private TimelineWindowDefinition[] timelineWindowDefinitions;
|
private TimelineWindowDefinition[] timelineWindowDefinitions;
|
||||||
private AdsMediaSource adsMediaSource;
|
private AdsMediaSource adsMediaSource;
|
||||||
private ViewGroup adViewGroup;
|
private ViewGroup adViewGroup;
|
||||||
private AdsLoader.AdViewProvider adViewProvider;
|
private AdViewProvider adViewProvider;
|
||||||
private AdsLoader.AdViewProvider audioAdsAdViewProvider;
|
private AdViewProvider audioAdsAdViewProvider;
|
||||||
private AdEvent.AdEventListener adEventListener;
|
private AdEvent.AdEventListener adEventListener;
|
||||||
private ContentProgressProvider contentProgressProvider;
|
private ContentProgressProvider contentProgressProvider;
|
||||||
private VideoAdPlayer videoAdPlayer;
|
private VideoAdPlayer videoAdPlayer;
|
||||||
|
|
@ -145,30 +147,19 @@ public final class ImaAdsLoaderTest {
|
||||||
adViewGroup = new FrameLayout(getApplicationContext());
|
adViewGroup = new FrameLayout(getApplicationContext());
|
||||||
View adOverlayView = new View(getApplicationContext());
|
View adOverlayView = new View(getApplicationContext());
|
||||||
adViewProvider =
|
adViewProvider =
|
||||||
new AdsLoader.AdViewProvider() {
|
new AdViewProvider() {
|
||||||
@Override
|
@Override
|
||||||
public ViewGroup getAdViewGroup() {
|
public ViewGroup getAdViewGroup() {
|
||||||
return adViewGroup;
|
return adViewGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableList<AdsLoader.OverlayInfo> getAdOverlayInfos() {
|
public ImmutableList<AdOverlayInfo> getAdOverlayInfos() {
|
||||||
return ImmutableList.of(
|
return ImmutableList.of(
|
||||||
new AdsLoader.OverlayInfo(adOverlayView, AdsLoader.OverlayInfo.PURPOSE_CLOSE_AD));
|
new AdOverlayInfo(adOverlayView, AdOverlayInfo.PURPOSE_CLOSE_AD));
|
||||||
}
|
|
||||||
};
|
|
||||||
audioAdsAdViewProvider =
|
|
||||||
new AdsLoader.AdViewProvider() {
|
|
||||||
@Override
|
|
||||||
public ViewGroup getAdViewGroup() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ImmutableList<AdsLoader.OverlayInfo> getAdOverlayInfos() {
|
|
||||||
return ImmutableList.of();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
audioAdsAdViewProvider = () -> null;
|
||||||
imaAdsLoader =
|
imaAdsLoader =
|
||||||
new ImaAdsLoader.Builder(getApplicationContext())
|
new ImaAdsLoader.Builder(getApplicationContext())
|
||||||
.setImaFactory(mockImaFactory)
|
.setImaFactory(mockImaFactory)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.google.android.exoplayer2.ui;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import androidx.annotation.IntDef;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
/** Provides information about an overlay view shown on top of an ad view group. */
|
||||||
|
public final class AdOverlayInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The purpose of the overlay. One of {@link #PURPOSE_CONTROLS}, {@link #PURPOSE_CLOSE_AD}, {@link
|
||||||
|
* #PURPOSE_OTHER} or {@link #PURPOSE_NOT_VISIBLE}.
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef({PURPOSE_CONTROLS, PURPOSE_CLOSE_AD, PURPOSE_OTHER, PURPOSE_NOT_VISIBLE})
|
||||||
|
public @interface Purpose {}
|
||||||
|
/** Purpose for playback controls overlaying the player. */
|
||||||
|
public static final int PURPOSE_CONTROLS = 0;
|
||||||
|
/** Purpose for ad close buttons overlaying the player. */
|
||||||
|
public static final int PURPOSE_CLOSE_AD = 1;
|
||||||
|
/** Purpose for other overlays. */
|
||||||
|
public static final int PURPOSE_OTHER = 2;
|
||||||
|
/** Purpose for overlays that are not visible. */
|
||||||
|
public static final int PURPOSE_NOT_VISIBLE = 3;
|
||||||
|
|
||||||
|
/** The overlay view. */
|
||||||
|
public final View view;
|
||||||
|
/** The purpose of the overlay view. */
|
||||||
|
@Purpose public final int purpose;
|
||||||
|
/** An optional, detailed reason that the overlay view is needed. */
|
||||||
|
@Nullable public final String reasonDetail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new overlay info.
|
||||||
|
*
|
||||||
|
* @param view The view that is overlaying the player.
|
||||||
|
* @param purpose The purpose of the view.
|
||||||
|
*/
|
||||||
|
public AdOverlayInfo(View view, @Purpose int purpose) {
|
||||||
|
this(view, purpose, /* detailedReason= */ null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new overlay info.
|
||||||
|
*
|
||||||
|
* @param view The view that is overlaying the player.
|
||||||
|
* @param purpose The purpose of the view.
|
||||||
|
* @param detailedReason An optional, detailed reason that the view is on top of the player.
|
||||||
|
*/
|
||||||
|
public AdOverlayInfo(View view, @Purpose int purpose, @Nullable String detailedReason) {
|
||||||
|
this.view = view;
|
||||||
|
this.purpose = purpose;
|
||||||
|
this.reasonDetail = detailedReason;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.google.android.exoplayer2.ui;
|
||||||
|
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/** Provides information about views for the ad playback UI. */
|
||||||
|
public interface AdViewProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link ViewGroup} on top of the player that will show any ad UI, or {@code null} if
|
||||||
|
* playing audio-only ads. Any views on top of the returned view group must be described by {@link
|
||||||
|
* AdOverlayInfo AdOverlayInfos} returned by {@link #getAdOverlayInfos()}, for accurate
|
||||||
|
* viewability measurement.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
ViewGroup getAdViewGroup();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of {@link AdOverlayInfo} instances describing views that are on top of the ad
|
||||||
|
* view group, but that are essential for controlling playback and should be excluded from ad
|
||||||
|
* viewability measurements.
|
||||||
|
*
|
||||||
|
* <p>Each view must be either a fully transparent overlay (for capturing touch events), or a
|
||||||
|
* small piece of transient UI that is essential to the user experience of playback (such as a
|
||||||
|
* button to pause/resume playback or a transient full-screen or cast button). For more
|
||||||
|
* information see the documentation for your ads loader.
|
||||||
|
*/
|
||||||
|
default List<AdOverlayInfo> getAdOverlayInfos() {
|
||||||
|
return ImmutableList.of();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -29,8 +29,8 @@ import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
|
||||||
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
|
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
|
||||||
import com.google.android.exoplayer2.offline.StreamKey;
|
import com.google.android.exoplayer2.offline.StreamKey;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsLoader;
|
import com.google.android.exoplayer2.source.ads.AdsLoader;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsLoader.AdViewProvider;
|
|
||||||
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
|
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
|
||||||
|
import com.google.android.exoplayer2.ui.AdViewProvider;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||||
|
|
|
||||||
|
|
@ -15,20 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.ads;
|
package com.google.android.exoplayer2.source.ads;
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import androidx.annotation.IntDef;
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsMediaSource.AdLoadException;
|
import com.google.android.exoplayer2.source.ads.AdsMediaSource.AdLoadException;
|
||||||
|
import com.google.android.exoplayer2.ui.AdViewProvider;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.annotation.Documented;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for loaders of ads, which can be used with {@link AdsMediaSource}.
|
* Interface for loaders of ads, which can be used with {@link AdsMediaSource}.
|
||||||
|
|
@ -78,94 +71,6 @@ public interface AdsLoader {
|
||||||
default void onAdTapped() {}
|
default void onAdTapped() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Provides information about views for the ad playback UI. */
|
|
||||||
interface AdViewProvider {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link ViewGroup} on top of the player that will show any ad UI, or {@code null}
|
|
||||||
* if playing audio-only ads. Any views on top of the returned view group must be described by
|
|
||||||
* {@link OverlayInfo OverlayInfos} returned by {@link #getAdOverlayInfos()}, for accurate
|
|
||||||
* viewability measurement.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
ViewGroup getAdViewGroup();
|
|
||||||
|
|
||||||
/** @deprecated Use {@link #getAdOverlayInfos()} instead. */
|
|
||||||
@Deprecated
|
|
||||||
default View[] getAdOverlayViews() {
|
|
||||||
return new View[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of {@link OverlayInfo} instances describing views that are on top of the ad
|
|
||||||
* view group, but that are essential for controlling playback and should be excluded from ad
|
|
||||||
* viewability measurements by the {@link AdsLoader} (if it supports this).
|
|
||||||
*
|
|
||||||
* <p>Each view must be either a fully transparent overlay (for capturing touch events), or a
|
|
||||||
* small piece of transient UI that is essential to the user experience of playback (such as a
|
|
||||||
* button to pause/resume playback or a transient full-screen or cast button). For more
|
|
||||||
* information see the documentation for your ads loader.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
default List<OverlayInfo> getAdOverlayInfos() {
|
|
||||||
ImmutableList.Builder<OverlayInfo> listBuilder = new ImmutableList.Builder<>();
|
|
||||||
// Call through to deprecated version.
|
|
||||||
for (View view : getAdOverlayViews()) {
|
|
||||||
listBuilder.add(new OverlayInfo(view, OverlayInfo.PURPOSE_CONTROLS));
|
|
||||||
}
|
|
||||||
return listBuilder.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Provides information about an overlay view shown on top of an ad view group. */
|
|
||||||
final class OverlayInfo {
|
|
||||||
|
|
||||||
@Documented
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
|
||||||
@IntDef({PURPOSE_CONTROLS, PURPOSE_CLOSE_AD, PURPOSE_OTHER, PURPOSE_NOT_VISIBLE})
|
|
||||||
public @interface Purpose {}
|
|
||||||
/** Purpose for playback controls overlaying the player. */
|
|
||||||
public static final int PURPOSE_CONTROLS = 0;
|
|
||||||
/** Purpose for ad close buttons overlaying the player. */
|
|
||||||
public static final int PURPOSE_CLOSE_AD = 1;
|
|
||||||
/** Purpose for other overlays. */
|
|
||||||
public static final int PURPOSE_OTHER = 2;
|
|
||||||
/** Purpose for overlays that are not visible. */
|
|
||||||
public static final int PURPOSE_NOT_VISIBLE = 3;
|
|
||||||
|
|
||||||
/** The overlay view. */
|
|
||||||
public final View view;
|
|
||||||
/** The purpose of the overlay view. */
|
|
||||||
@Purpose public final int purpose;
|
|
||||||
/** An optional, detailed reason that the overlay view is needed. */
|
|
||||||
@Nullable public final String reasonDetail;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new overlay info.
|
|
||||||
*
|
|
||||||
* @param view The view that is overlaying the player.
|
|
||||||
* @param purpose The purpose of the view.
|
|
||||||
*/
|
|
||||||
public OverlayInfo(View view, @Purpose int purpose) {
|
|
||||||
this(view, purpose, /* detailedReason= */ null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new overlay info.
|
|
||||||
*
|
|
||||||
* @param view The view that is overlaying the player.
|
|
||||||
* @param purpose The purpose of the view.
|
|
||||||
* @param detailedReason An optional, detailed reason that the view is on top of the player. See
|
|
||||||
* the documentation for the {@link AdsLoader} implementation for more information on this
|
|
||||||
* string's formatting.
|
|
||||||
*/
|
|
||||||
public OverlayInfo(View view, @Purpose int purpose, @Nullable String detailedReason) {
|
|
||||||
this.view = view;
|
|
||||||
this.purpose = purpose;
|
|
||||||
this.reasonDetail = detailedReason;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Methods called by the application.
|
// Methods called by the application.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ import com.google.android.exoplayer2.source.MediaSource;
|
||||||
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
||||||
import com.google.android.exoplayer2.source.MediaSourceEventListener;
|
import com.google.android.exoplayer2.source.MediaSourceEventListener;
|
||||||
import com.google.android.exoplayer2.source.MediaSourceFactory;
|
import com.google.android.exoplayer2.source.MediaSourceFactory;
|
||||||
|
import com.google.android.exoplayer2.ui.AdViewProvider;
|
||||||
import com.google.android.exoplayer2.upstream.Allocator;
|
import com.google.android.exoplayer2.upstream.Allocator;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer2.upstream.TransferListener;
|
import com.google.android.exoplayer2.upstream.TransferListener;
|
||||||
|
|
@ -128,7 +129,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
||||||
private final MediaSource contentMediaSource;
|
private final MediaSource contentMediaSource;
|
||||||
private final MediaSourceFactory adMediaSourceFactory;
|
private final MediaSourceFactory adMediaSourceFactory;
|
||||||
private final AdsLoader adsLoader;
|
private final AdsLoader adsLoader;
|
||||||
private final AdsLoader.AdViewProvider adViewProvider;
|
private final AdViewProvider adViewProvider;
|
||||||
private final DataSpec adTagDataSpec;
|
private final DataSpec adTagDataSpec;
|
||||||
private final Object adsId;
|
private final Object adsId;
|
||||||
private final Handler mainHandler;
|
private final Handler mainHandler;
|
||||||
|
|
@ -160,7 +161,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
||||||
Object adsId,
|
Object adsId,
|
||||||
MediaSourceFactory adMediaSourceFactory,
|
MediaSourceFactory adMediaSourceFactory,
|
||||||
AdsLoader adsLoader,
|
AdsLoader adsLoader,
|
||||||
AdsLoader.AdViewProvider adViewProvider) {
|
AdViewProvider adViewProvider) {
|
||||||
this.contentMediaSource = contentMediaSource;
|
this.contentMediaSource = contentMediaSource;
|
||||||
this.adMediaSourceFactory = adMediaSourceFactory;
|
this.adMediaSourceFactory = adMediaSourceFactory;
|
||||||
this.adsLoader = adsLoader;
|
this.adsLoader = adsLoader;
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.MediaItem;
|
import com.google.android.exoplayer2.MediaItem;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsLoader;
|
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.ui.AdViewProvider;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
@ -205,7 +206,7 @@ public final class DefaultMediaSourceFactoryTest {
|
||||||
DefaultMediaSourceFactory defaultMediaSourceFactory =
|
DefaultMediaSourceFactory defaultMediaSourceFactory =
|
||||||
new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext())
|
new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext())
|
||||||
.setAdsLoaderProvider(ignoredAdsConfiguration -> mock(AdsLoader.class))
|
.setAdsLoaderProvider(ignoredAdsConfiguration -> mock(AdsLoader.class))
|
||||||
.setAdViewProvider(mock(AdsLoader.AdViewProvider.class));
|
.setAdViewProvider(mock(AdViewProvider.class));
|
||||||
|
|
||||||
MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem);
|
MediaSource mediaSource = defaultMediaSourceFactory.createMediaSource(mediaItem);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,9 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
||||||
import com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller;
|
import com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller;
|
||||||
import com.google.android.exoplayer2.source.MediaSourceFactory;
|
import com.google.android.exoplayer2.source.MediaSourceFactory;
|
||||||
import com.google.android.exoplayer2.source.SinglePeriodTimeline;
|
import com.google.android.exoplayer2.source.SinglePeriodTimeline;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsLoader.AdViewProvider;
|
|
||||||
import com.google.android.exoplayer2.source.ads.AdsLoader.EventListener;
|
import com.google.android.exoplayer2.source.ads.AdsLoader.EventListener;
|
||||||
import com.google.android.exoplayer2.testutil.FakeMediaSource;
|
import com.google.android.exoplayer2.testutil.FakeMediaSource;
|
||||||
|
import com.google.android.exoplayer2.ui.AdViewProvider;
|
||||||
import com.google.android.exoplayer2.upstream.Allocator;
|
import com.google.android.exoplayer2.upstream.Allocator;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@ import com.google.android.exoplayer2.metadata.Metadata;
|
||||||
import com.google.android.exoplayer2.metadata.flac.PictureFrame;
|
import com.google.android.exoplayer2.metadata.flac.PictureFrame;
|
||||||
import com.google.android.exoplayer2.metadata.id3.ApicFrame;
|
import com.google.android.exoplayer2.metadata.id3.ApicFrame;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsLoader;
|
|
||||||
import com.google.android.exoplayer2.text.Cue;
|
import com.google.android.exoplayer2.text.Cue;
|
||||||
import com.google.android.exoplayer2.text.TextOutput;
|
import com.google.android.exoplayer2.text.TextOutput;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||||
|
|
@ -264,7 +263,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||||
* PlayerView. This will cause the specified layout to be inflated instead of {@code
|
* PlayerView. This will cause the specified layout to be inflated instead of {@code
|
||||||
* exo_player_view.xml} for only the instance on which the attribute is set.
|
* exo_player_view.xml} for only the instance on which the attribute is set.
|
||||||
*/
|
*/
|
||||||
public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider {
|
public class PlayerView extends FrameLayout implements AdViewProvider {
|
||||||
|
|
||||||
// LINT.IfChange
|
// LINT.IfChange
|
||||||
/**
|
/**
|
||||||
|
|
@ -1233,18 +1232,17 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AdsLoader.OverlayInfo> getAdOverlayInfos() {
|
public List<AdOverlayInfo> getAdOverlayInfos() {
|
||||||
List<AdsLoader.OverlayInfo> overlayViews = new ArrayList<>();
|
List<AdOverlayInfo> overlayViews = new ArrayList<>();
|
||||||
if (overlayFrameLayout != null) {
|
if (overlayFrameLayout != null) {
|
||||||
overlayViews.add(
|
overlayViews.add(
|
||||||
new AdsLoader.OverlayInfo(
|
new AdOverlayInfo(
|
||||||
overlayFrameLayout,
|
overlayFrameLayout,
|
||||||
AdsLoader.OverlayInfo.PURPOSE_NOT_VISIBLE,
|
AdOverlayInfo.PURPOSE_NOT_VISIBLE,
|
||||||
/* detailedReason= */ "Transparent overlay does not impact viewability"));
|
/* detailedReason= */ "Transparent overlay does not impact viewability"));
|
||||||
}
|
}
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
overlayViews.add(
|
overlayViews.add(new AdOverlayInfo(controller, AdOverlayInfo.PURPOSE_CONTROLS));
|
||||||
new AdsLoader.OverlayInfo(controller, AdsLoader.OverlayInfo.PURPOSE_CONTROLS));
|
|
||||||
}
|
}
|
||||||
return ImmutableList.copyOf(overlayViews);
|
return ImmutableList.copyOf(overlayViews);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,6 @@ import com.google.android.exoplayer2.metadata.Metadata;
|
||||||
import com.google.android.exoplayer2.metadata.flac.PictureFrame;
|
import com.google.android.exoplayer2.metadata.flac.PictureFrame;
|
||||||
import com.google.android.exoplayer2.metadata.id3.ApicFrame;
|
import com.google.android.exoplayer2.metadata.id3.ApicFrame;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.source.ads.AdsLoader;
|
|
||||||
import com.google.android.exoplayer2.text.Cue;
|
import com.google.android.exoplayer2.text.Cue;
|
||||||
import com.google.android.exoplayer2.text.TextOutput;
|
import com.google.android.exoplayer2.text.TextOutput;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||||
|
|
@ -266,7 +265,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||||
* attribute on a StyledPlayerView. This will cause the specified layout to be inflated instead of
|
* attribute on a StyledPlayerView. This will cause the specified layout to be inflated instead of
|
||||||
* {@code exo_styled_player_view.xml} for only the instance on which the attribute is set.
|
* {@code exo_styled_player_view.xml} for only the instance on which the attribute is set.
|
||||||
*/
|
*/
|
||||||
public class StyledPlayerView extends FrameLayout implements AdsLoader.AdViewProvider {
|
public class StyledPlayerView extends FrameLayout implements AdViewProvider {
|
||||||
|
|
||||||
// LINT.IfChange
|
// LINT.IfChange
|
||||||
/**
|
/**
|
||||||
|
|
@ -1251,18 +1250,17 @@ public class StyledPlayerView extends FrameLayout implements AdsLoader.AdViewPro
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AdsLoader.OverlayInfo> getAdOverlayInfos() {
|
public List<AdOverlayInfo> getAdOverlayInfos() {
|
||||||
List<AdsLoader.OverlayInfo> overlayViews = new ArrayList<>();
|
List<AdOverlayInfo> overlayViews = new ArrayList<>();
|
||||||
if (overlayFrameLayout != null) {
|
if (overlayFrameLayout != null) {
|
||||||
overlayViews.add(
|
overlayViews.add(
|
||||||
new AdsLoader.OverlayInfo(
|
new AdOverlayInfo(
|
||||||
overlayFrameLayout,
|
overlayFrameLayout,
|
||||||
AdsLoader.OverlayInfo.PURPOSE_NOT_VISIBLE,
|
AdOverlayInfo.PURPOSE_NOT_VISIBLE,
|
||||||
/* detailedReason= */ "Transparent overlay does not impact viewability"));
|
/* detailedReason= */ "Transparent overlay does not impact viewability"));
|
||||||
}
|
}
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
overlayViews.add(
|
overlayViews.add(new AdOverlayInfo(controller, AdOverlayInfo.PURPOSE_CONTROLS));
|
||||||
new AdsLoader.OverlayInfo(controller, AdsLoader.OverlayInfo.PURPOSE_CONTROLS));
|
|
||||||
}
|
}
|
||||||
return ImmutableList.copyOf(overlayViews);
|
return ImmutableList.copyOf(overlayViews);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue