Skip to content

Commit

Permalink
Add focusSkipButtonWhenAvailable to focus UI on ATV
Browse files Browse the repository at this point in the history
For TV devices the skip button needs to have the focus to be accessible with
the remote control. This property makes this configurable while being set to
true by default.

PiperOrigin-RevId: 501077608
  • Loading branch information
marcbaechinger authored and rohitjoins committed Jan 17, 2023
1 parent 9a9da0a commit 9882a20
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 5 deletions.
3 changes: 3 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ Release notes
* IMA extension
* Remove player listener of the `ImaServerSideAdInsertionMediaSource` on
the application thread to avoid threading issues.
* Add a property `focusSkipButtonWhenAvailable` to the
`ImaServerSideAdInsertionMediaSource.AdsLoader.Builder` to request
focusing the skip button on TV devices and set it to true by default.
* Bump IMA SDK version to 3.29.0.

### 1.0.0-beta03 (2022-11-22)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import androidx.media3.common.util.Util;
import androidx.media3.datasource.TransferListener;
import androidx.media3.exoplayer.drm.DrmSessionManagerProvider;
import androidx.media3.exoplayer.ima.ImaUtil.ServerSideAdInsertionConfiguration;
import androidx.media3.exoplayer.source.CompositeMediaSource;
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
import androidx.media3.exoplayer.source.ForwardingTimeline;
Expand Down Expand Up @@ -193,6 +194,7 @@ public static final class Builder {
@Nullable private AdErrorEvent.AdErrorListener adErrorListener;
private State state;
private ImmutableList<CompanionAdSlot> companionAdSlots;
private boolean focusSkipButtonWhenAvailable;

/**
* Creates an instance.
Expand All @@ -205,6 +207,7 @@ public Builder(Context context, AdViewProvider adViewProvider) {
this.adViewProvider = adViewProvider;
companionAdSlots = ImmutableList.of();
state = new State(ImmutableMap.of());
focusSkipButtonWhenAvailable = true;
}

/**
Expand Down Expand Up @@ -274,20 +277,37 @@ public AdsLoader.Builder setAdsLoaderState(State state) {
return this;
}

/**
* Sets whether to focus the skip button (when available) on Android TV devices. The default
* setting is {@code true}.
*
* @param focusSkipButtonWhenAvailable Whether to focus the skip button (when available) on
* Android TV devices.
* @return This builder, for convenience.
* @see AdsRenderingSettings#setFocusSkipButtonWhenAvailable(boolean)
*/
@CanIgnoreReturnValue
public AdsLoader.Builder setFocusSkipButtonWhenAvailable(
boolean focusSkipButtonWhenAvailable) {
this.focusSkipButtonWhenAvailable = focusSkipButtonWhenAvailable;
return this;
}

/** Returns a new {@link AdsLoader}. */
public AdsLoader build() {
@Nullable ImaSdkSettings imaSdkSettings = this.imaSdkSettings;
if (imaSdkSettings == null) {
imaSdkSettings = ImaSdkFactory.getInstance().createImaSdkSettings();
imaSdkSettings.setLanguage(Util.getSystemLanguageCodes()[0]);
}
ImaUtil.ServerSideAdInsertionConfiguration configuration =
new ImaUtil.ServerSideAdInsertionConfiguration(
ServerSideAdInsertionConfiguration configuration =
new ServerSideAdInsertionConfiguration(
adViewProvider,
imaSdkSettings,
adEventListener,
adErrorListener,
companionAdSlots,
focusSkipButtonWhenAvailable,
imaSdkSettings.isDebugMode());
return new AdsLoader(context, configuration, state);
}
Expand Down Expand Up @@ -354,7 +374,7 @@ private static State fromBundle(Bundle bundle) {
}
}

private final ImaUtil.ServerSideAdInsertionConfiguration configuration;
private final ServerSideAdInsertionConfiguration configuration;
private final Context context;
private final Map<ImaServerSideAdInsertionMediaSource, MediaSourceResourceHolder>
mediaSourceResources;
Expand All @@ -363,7 +383,7 @@ private static State fromBundle(Bundle bundle) {
@Nullable private Player player;

private AdsLoader(
Context context, ImaUtil.ServerSideAdInsertionConfiguration configuration, State state) {
Context context, ServerSideAdInsertionConfiguration configuration, State state) {
this.context = context.getApplicationContext();
this.configuration = configuration;
mediaSourceResources = new HashMap<>();
Expand Down Expand Up @@ -504,6 +524,7 @@ public void prepareSourceInternal(@Nullable TransferListener mediaTransferListen
StreamManagerLoadable streamManagerLoadable =
new StreamManagerLoadable(
sdkAdsLoader,
adsLoader.configuration,
streamRequest,
streamPlayer,
applicationAdErrorListener,
Expand Down Expand Up @@ -932,6 +953,7 @@ private static class StreamManagerLoadable
implements Loadable, AdsLoadedListener, AdErrorListener {

private final com.google.ads.interactivemedia.v3.api.AdsLoader adsLoader;
private final ServerSideAdInsertionConfiguration serverSideAdInsertionConfiguration;
private final StreamRequest request;
private final StreamPlayer streamPlayer;
@Nullable private final AdErrorListener adErrorListener;
Expand All @@ -948,11 +970,13 @@ private static class StreamManagerLoadable
/** Creates an instance. */
private StreamManagerLoadable(
com.google.ads.interactivemedia.v3.api.AdsLoader adsLoader,
ServerSideAdInsertionConfiguration serverSideAdInsertionConfiguration,
StreamRequest request,
StreamPlayer streamPlayer,
@Nullable AdErrorListener adErrorListener,
int loadVideoTimeoutMs) {
this.adsLoader = adsLoader;
this.serverSideAdInsertionConfiguration = serverSideAdInsertionConfiguration;
this.request = request;
this.streamPlayer = streamPlayer;
this.adErrorListener = adErrorListener;
Expand Down Expand Up @@ -1029,6 +1053,8 @@ public void onAdsManagerLoaded(AdsManagerLoadedEvent event) {
AdsRenderingSettings adsRenderingSettings =
ImaSdkFactory.getInstance().createAdsRenderingSettings();
adsRenderingSettings.setLoadVideoTimeout(loadVideoTimeoutMs);
adsRenderingSettings.setFocusSkipButtonWhenAvailable(
serverSideAdInsertionConfiguration.focusSkipButtonWhenAvailable);
// After initialization completed the streamUri will be reported to the streamPlayer.
streamManager.init(adsRenderingSettings);
this.streamManager = streamManager;
Expand Down Expand Up @@ -1261,7 +1287,7 @@ private static boolean isCurrentAdPlaying(

private static StreamDisplayContainer createStreamDisplayContainer(
ImaSdkFactory imaSdkFactory,
ImaUtil.ServerSideAdInsertionConfiguration config,
ServerSideAdInsertionConfiguration config,
StreamPlayer streamPlayer) {
StreamDisplayContainer container =
ImaSdkFactory.createStreamDisplayContainer(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ public static final class ServerSideAdInsertionConfiguration {
@Nullable public final AdEvent.AdEventListener applicationAdEventListener;
@Nullable public final AdErrorEvent.AdErrorListener applicationAdErrorListener;
public final ImmutableList<CompanionAdSlot> companionAdSlots;
public final boolean focusSkipButtonWhenAvailable;
public final boolean debugModeEnabled;

public ServerSideAdInsertionConfiguration(
Expand All @@ -174,12 +175,14 @@ public ServerSideAdInsertionConfiguration(
@Nullable AdEvent.AdEventListener applicationAdEventListener,
@Nullable AdErrorEvent.AdErrorListener applicationAdErrorListener,
List<CompanionAdSlot> companionAdSlots,
boolean focusSkipButtonWhenAvailable,
boolean debugModeEnabled) {
this.imaSdkSettings = imaSdkSettings;
this.adViewProvider = adViewProvider;
this.applicationAdEventListener = applicationAdEventListener;
this.applicationAdErrorListener = applicationAdErrorListener;
this.companionAdSlots = ImmutableList.copyOf(companionAdSlots);
this.focusSkipButtonWhenAvailable = focusSkipButtonWhenAvailable;
this.debugModeEnabled = debugModeEnabled;
}
}
Expand Down

0 comments on commit 9882a20

Please sign in to comment.