Skip to content

Commit

Permalink
Show play button during playback suppression by default
Browse files Browse the repository at this point in the history
This changes the default logic of shouldShowPlayButton to show a play
button while the playback is temporarily suppressed. This helps to
provide better UI feedback to the fact that playback stopped and
provides a quick way for users to override the suppression and attempt
to restart playback.

Some apps may want to keep the legacy behavior depending on their app's
needs. Hence, we also add a config parameter to set this behavior both
in MediaSession and our default UI components.

Issue: #11213
PiperOrigin-RevId: 557129171
  • Loading branch information
tonihei authored and tianyif committed Aug 20, 2023
1 parent 9cf8eb8 commit 2b66c41
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3043,23 +3043,41 @@ public static String intToStringMaxRadix(int i) {
* <p>Use {@link #handlePlayPauseButtonAction}, {@link #handlePlayButtonAction} or {@link
* #handlePauseButtonAction} to handle the interaction with the play or pause button UI element.
*
* @param player The {@link Player}. May be null.
* @param player The {@link Player}. May be {@code null}.
*/
@EnsuresNonNullIf(result = false, expression = "#1")
public static boolean shouldShowPlayButton(@Nullable Player player) {
return shouldShowPlayButton(player, /* playIfSuppressed= */ true);
}

/**
* Returns whether a play button should be presented on a UI element for playback control. If
* {@code false}, a pause button should be shown instead.
*
* <p>Use {@link #handlePlayPauseButtonAction}, {@link #handlePlayButtonAction} or {@link
* #handlePauseButtonAction} to handle the interaction with the play or pause button UI element.
*
* @param player The {@link Player}. May be {@code null}.
* @param playIfSuppressed Whether to show a play button if playback is {@linkplain
* Player#getPlaybackSuppressionReason() suppressed}.
*/
@EnsuresNonNullIf(result = false, expression = "#1")
public static boolean shouldShowPlayButton(@Nullable Player player, boolean playIfSuppressed) {
return player == null
|| !player.getPlayWhenReady()
|| player.getPlaybackState() == Player.STATE_IDLE
|| player.getPlaybackState() == Player.STATE_ENDED;
|| player.getPlaybackState() == Player.STATE_ENDED
|| (playIfSuppressed
&& player.getPlaybackSuppressionReason() != Player.PLAYBACK_SUPPRESSION_REASON_NONE);
}

/**
* Updates the player to handle an interaction with a play button.
*
* <p>This method assumes the play button is enabled if {@link #shouldShowPlayButton} returns
* true.
* {@code true}.
*
* @param player The {@link Player}. May be null.
* @param player The {@link Player}. May be {@code null}.
* @return Whether a player method was triggered to handle this action.
*/
public static boolean handlePlayButtonAction(@Nullable Player player) {
Expand Down Expand Up @@ -3087,9 +3105,9 @@ public static boolean handlePlayButtonAction(@Nullable Player player) {
* Updates the player to handle an interaction with a pause button.
*
* <p>This method assumes the pause button is enabled if {@link #shouldShowPlayButton} returns
* false.
* {@code false}.
*
* @param player The {@link Player}. May be null.
* @param player The {@link Player}. May be {@code null}.
* @return Whether a player method was triggered to handle this action.
*/
public static boolean handlePauseButtonAction(@Nullable Player player) {
Expand All @@ -3104,13 +3122,29 @@ public static boolean handlePauseButtonAction(@Nullable Player player) {
* Updates the player to handle an interaction with a play or pause button.
*
* <p>This method assumes that the UI element enables a play button if {@link
* #shouldShowPlayButton} returns true and a pause button otherwise.
* #shouldShowPlayButton} returns {@code true} and a pause button otherwise.
*
* @param player The {@link Player}. May be null.
* @param player The {@link Player}. May be {@code null}.
* @return Whether a player method was triggered to handle this action.
*/
public static boolean handlePlayPauseButtonAction(@Nullable Player player) {
if (shouldShowPlayButton(player)) {
return handlePlayPauseButtonAction(player, /* playIfSuppressed= */ true);
}

/**
* Updates the player to handle an interaction with a play or pause button.
*
* <p>This method assumes that the UI element enables a play button if {@link
* #shouldShowPlayButton(Player, boolean)} returns {@code true} and a pause button otherwise.
*
* @param player The {@link Player}. May be {@code null}.
* @param playIfSuppressed Whether to trigger a play action if playback is {@linkplain
* Player#getPlaybackSuppressionReason() suppressed}.
* @return Whether a player method was triggered to handle this action.
*/
public static boolean handlePlayPauseButtonAction(
@Nullable Player player, boolean playIfSuppressed) {
if (shouldShowPlayButton(player, playIfSuppressed)) {
return handlePlayButtonAction(player);
} else {
return handlePauseButtonAction(player);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ public interface ProgressUpdateListener {

private boolean isAttachedToWindow;
private boolean showMultiWindowTimeBar;
private boolean showPlayButtonIfSuppressed;
private boolean multiWindowTimeBar;
private boolean scrubbing;
private int showTimeoutMs;
Expand Down Expand Up @@ -375,6 +376,7 @@ public PlayerControlView(
@Nullable AttributeSet playbackAttrs) {
super(context, attrs, defStyleAttr);
int controllerLayoutId = R.layout.exo_player_control_view;
showPlayButtonIfSuppressed = true;
showTimeoutMs = DEFAULT_SHOW_TIMEOUT_MS;
repeatToggleModes = DEFAULT_REPEAT_TOGGLE_MODES;
timeBarMinUpdateIntervalMs = DEFAULT_TIME_BAR_MIN_UPDATE_INTERVAL_MS;
Expand Down Expand Up @@ -562,6 +564,20 @@ public void setShowMultiWindowTimeBar(boolean showMultiWindowTimeBar) {
updateTimeline();
}

/**
* Sets whether a play button is shown if playback is {@linkplain
* Player#getPlaybackSuppressionReason() suppressed}.
*
* <p>The default is {@code true}.
*
* @param showPlayButtonIfSuppressed Whether to show a play button if playback is {@linkplain
* Player#getPlaybackSuppressionReason() suppressed}.
*/
public void setShowPlayButtonIfPlaybackIsSuppressed(boolean showPlayButtonIfSuppressed) {
this.showPlayButtonIfSuppressed = showPlayButtonIfSuppressed;
updatePlayPauseButton();
}

/**
* Sets the millisecond positions of extra ad markers relative to the start of the window (or
* timeline, if in multi-window mode) and whether each extra ad has been played or not. The
Expand Down Expand Up @@ -833,7 +849,7 @@ private void updatePlayPauseButton() {
}
boolean requestPlayPauseFocus = false;
boolean requestPlayPauseAccessibilityFocus = false;
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player);
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player, showPlayButtonIfSuppressed);
if (playButton != null) {
requestPlayPauseFocus |= !shouldShowPlayButton && playButton.isFocused();
requestPlayPauseAccessibilityFocus |=
Expand Down Expand Up @@ -1074,7 +1090,7 @@ private void updateProgress() {
}

private void requestPlayPauseFocus() {
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player);
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player, showPlayButtonIfSuppressed);
if (shouldShowPlayButton && playButton != null) {
playButton.requestFocus();
} else if (!shouldShowPlayButton && pauseButton != null) {
Expand All @@ -1083,7 +1099,7 @@ private void requestPlayPauseFocus() {
}

private void requestPlayPauseAccessibilityFocus() {
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player);
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player, showPlayButtonIfSuppressed);
if (shouldShowPlayButton && playButton != null) {
playButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
} else if (!shouldShowPlayButton && pauseButton != null) {
Expand Down Expand Up @@ -1193,7 +1209,7 @@ public boolean dispatchMediaKeyEvent(KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
case KeyEvent.KEYCODE_HEADSETHOOK:
Util.handlePlayPauseButtonAction(player);
Util.handlePlayPauseButtonAction(player, showPlayButtonIfSuppressed);
break;
case KeyEvent.KEYCODE_MEDIA_PLAY:
Util.handlePlayButtonAction(player);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,7 @@ public void onBitmap(final Bitmap bitmap) {
private boolean useRewindActionInCompactView;
private boolean useFastForwardActionInCompactView;
private boolean usePlayPauseActions;
private boolean showPlayButtonIfSuppressed;
private boolean useStopAction;
private int badgeIconType;
private boolean colorized;
Expand Down Expand Up @@ -766,6 +767,7 @@ protected PlayerNotificationManager(
usePreviousAction = true;
useNextAction = true;
usePlayPauseActions = true;
showPlayButtonIfSuppressed = true;
useRewindAction = true;
useFastForwardAction = true;
colorized = true;
Expand Down Expand Up @@ -975,6 +977,22 @@ public final void setUsePlayPauseActions(boolean usePlayPauseActions) {
}
}

/**
* Sets whether a play button is shown if playback is {@linkplain
* Player#getPlaybackSuppressionReason() suppressed}.
*
* <p>The default is {@code true}.
*
* @param showPlayButtonIfSuppressed Whether to show a play button if playback is {@linkplain
* Player#getPlaybackSuppressionReason() suppressed}.
*/
public void setShowPlayButtonIfPlaybackIsSuppressed(boolean showPlayButtonIfSuppressed) {
if (this.showPlayButtonIfSuppressed != showPlayButtonIfSuppressed) {
this.showPlayButtonIfSuppressed = showPlayButtonIfSuppressed;
invalidate();
}
}

/**
* Sets whether the stop action should be used.
*
Expand Down Expand Up @@ -1343,7 +1361,7 @@ protected List<String> getActions(Player player) {
stringActions.add(ACTION_REWIND);
}
if (usePlayPauseActions) {
if (Util.shouldShowPlayButton(player)) {
if (Util.shouldShowPlayButton(player, showPlayButtonIfSuppressed)) {
stringActions.add(ACTION_PLAY);
} else {
stringActions.add(ACTION_PAUSE);
Expand Down Expand Up @@ -1391,7 +1409,7 @@ protected int[] getActionIndicesForCompactView(List<String> actionNames, Player
if (leftSideActionIndex != -1) {
actionIndices[actionCounter++] = leftSideActionIndex;
}
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player);
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player, showPlayButtonIfSuppressed);
if (pauseActionIndex != -1 && !shouldShowPlayButton) {
actionIndices[actionCounter++] = pauseActionIndex;
} else if (playActionIndex != -1 && shouldShowPlayButton) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,20 @@ public void setShowMultiWindowTimeBar(boolean showMultiWindowTimeBar) {
controller.setShowMultiWindowTimeBar(showMultiWindowTimeBar);
}

/**
* Sets whether a play button is shown if playback is {@linkplain
* Player#getPlaybackSuppressionReason() suppressed}.
*
* <p>The default is {@code true}.
*
* @param showPlayButtonIfSuppressed Whether to show a play button if playback is {@linkplain
* Player#getPlaybackSuppressionReason() suppressed}.
*/
public void setShowPlayButtonIfPlaybackIsSuppressed(boolean showPlayButtonIfSuppressed) {
Assertions.checkStateNotNull(controller);
controller.setShowPlayButtonIfPlaybackIsSuppressed(showPlayButtonIfSuppressed);
}

/**
* Sets the millisecond positions of extra ad markers relative to the start of the window (or
* timeline, if in multi-window mode) and whether each extra ad has been played or not. The
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ public interface OnFullScreenModeChangedListener {
private boolean isFullScreen;
private boolean isAttachedToWindow;
private boolean showMultiWindowTimeBar;
private boolean showPlayButtonIfSuppressed;
private boolean multiWindowTimeBar;
private boolean scrubbing;
private int showTimeoutMs;
Expand Down Expand Up @@ -377,6 +378,7 @@ public StyledPlayerControlView(
@Nullable AttributeSet playbackAttrs) {
super(context, attrs, defStyleAttr);
int controllerLayoutId = R.layout.exo_styled_player_control_view;
showPlayButtonIfSuppressed = true;
showTimeoutMs = DEFAULT_SHOW_TIMEOUT_MS;
repeatToggleModes = DEFAULT_REPEAT_TOGGLE_MODES;
timeBarMinUpdateIntervalMs = DEFAULT_TIME_BAR_MIN_UPDATE_INTERVAL_MS;
Expand Down Expand Up @@ -685,6 +687,20 @@ public void setShowMultiWindowTimeBar(boolean showMultiWindowTimeBar) {
updateTimeline();
}

/**
* Sets whether a play button is shown if playback is {@linkplain
* Player#getPlaybackSuppressionReason() suppressed}.
*
* <p>The default is {@code true}.
*
* @param showPlayButtonIfSuppressed Whether to show a play button if playback is {@linkplain
* Player#getPlaybackSuppressionReason() suppressed}.
*/
public void setShowPlayButtonIfPlaybackIsSuppressed(boolean showPlayButtonIfSuppressed) {
this.showPlayButtonIfSuppressed = showPlayButtonIfSuppressed;
updatePlayPauseButton();
}

/**
* Sets the millisecond positions of extra ad markers relative to the start of the window (or
* timeline, if in multi-window mode) and whether each extra ad has been played or not. The
Expand Down Expand Up @@ -992,7 +1008,7 @@ private void updatePlayPauseButton() {
return;
}
if (playPauseButton != null) {
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player);
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player, showPlayButtonIfSuppressed);
@DrawableRes
int drawableRes =
shouldShowPlayButton
Expand Down Expand Up @@ -1491,7 +1507,7 @@ public boolean dispatchMediaKeyEvent(KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
case KeyEvent.KEYCODE_HEADSETHOOK:
Util.handlePlayPauseButtonAction(player);
Util.handlePlayPauseButtonAction(player, showPlayButtonIfSuppressed);
break;
case KeyEvent.KEYCODE_MEDIA_PLAY:
Util.handlePlayButtonAction(player);
Expand Down Expand Up @@ -1722,7 +1738,7 @@ public void onClick(View view) {
player.seekBack();
}
} else if (playPauseButton == view) {
Util.handlePlayPauseButtonAction(player);
Util.handlePlayPauseButtonAction(player, showPlayButtonIfSuppressed);
} else if (repeatToggleButton == view) {
if (player.isCommandAvailable(COMMAND_SET_REPEAT_MODE)) {
player.setRepeatMode(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,20 @@ public void setShowMultiWindowTimeBar(boolean showMultiWindowTimeBar) {
controller.setShowMultiWindowTimeBar(showMultiWindowTimeBar);
}

/**
* Sets whether a play button is shown if playback is {@linkplain
* Player#getPlaybackSuppressionReason() suppressed}.
*
* <p>The default is {@code true}.
*
* @param showPlayButtonIfSuppressed Whether to show a play button if playback is {@linkplain
* Player#getPlaybackSuppressionReason() suppressed}.
*/
public void setShowPlayButtonIfPlaybackIsSuppressed(boolean showPlayButtonIfSuppressed) {
Assertions.checkStateNotNull(controller);
controller.setShowPlayButtonIfPlaybackIsSuppressed(showPlayButtonIfSuppressed);
}

/**
* Sets the millisecond positions of extra ad markers relative to the start of the window (or
* timeline, if in multi-window mode) and whether each extra ad has been played or not. The
Expand Down

0 comments on commit 2b66c41

Please sign in to comment.