From 9128244dc32f9d3e2b623350c297110ea782cfca Mon Sep 17 00:00:00 2001 From: tonihei Date: Wed, 26 Apr 2023 14:35:55 +0100 Subject: [PATCH] Use Util method for common UI play/pause button logic. This ensures the logic is consistent and can also be easily used from custom UIs. PiperOrigin-RevId: 527249127 --- RELEASENOTES.md | 4 + api.txt | 4 + .../androidx/media3/common/util/Util.java | 84 +++++++++++++++++++ .../session/MediaSessionLegacyStub.java | 30 +------ .../media3/ui/LegacyPlayerControlView.java | 67 ++++----------- .../androidx/media3/ui/PlayerControlView.java | 60 +++---------- .../media3/ui/PlayerNotificationManager.java | 36 ++------ .../ui/leanback/LeanbackPlayerAdapter.java | 16 +--- 8 files changed, 135 insertions(+), 166 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index aa9b3bdc97..5da70c7f6e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -49,6 +49,10 @@ * Fix issue where `MediaController` doesn't update its available commands when connected to a legacy `MediaSessionCompat` that updates its actions. +* UI: + * Add Util methods `shouldShowPlayButton` and + `handlePlayPauseButtonAction` to write custom UI elements with a + play/pause button. * Audio: * Fix bug where some playbacks fail when tunneling is enabled and `AudioProcessors` are active, e.g. for gapless trimming diff --git a/api.txt b/api.txt index 1981a65991..005870d989 100644 --- a/api.txt +++ b/api.txt @@ -1233,11 +1233,15 @@ package androidx.media3.common.util { method public static boolean checkCleartextTrafficPermitted(androidx.media3.common.MediaItem...); method @Nullable public static String getAdaptiveMimeTypeForContentType(@androidx.media3.common.C.ContentType int); method @Nullable public static java.util.UUID getDrmUuid(String); + method public static boolean handlePauseButtonAction(@Nullable androidx.media3.common.Player); + method public static boolean handlePlayButtonAction(@Nullable androidx.media3.common.Player); + method public static boolean handlePlayPauseButtonAction(@Nullable androidx.media3.common.Player); method @androidx.media3.common.C.ContentType public static int inferContentType(android.net.Uri); method @androidx.media3.common.C.ContentType public static int inferContentTypeForExtension(String); method @androidx.media3.common.C.ContentType public static int inferContentTypeForUriAndMimeType(android.net.Uri, @Nullable String); method public static boolean maybeRequestReadExternalStoragePermission(android.app.Activity, android.net.Uri...); method public static boolean maybeRequestReadExternalStoragePermission(android.app.Activity, androidx.media3.common.MediaItem...); + method @org.checkerframework.checker.nullness.qual.EnsuresNonNullIf(result=false, expression="#1") public static boolean shouldShowPlayButton(@Nullable androidx.media3.common.Player); } } diff --git a/libraries/common/src/main/java/androidx/media3/common/util/Util.java b/libraries/common/src/main/java/androidx/media3/common/util/Util.java index 91f1183cb4..ef82b4e062 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/Util.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/Util.java @@ -17,6 +17,8 @@ package androidx.media3.common.util; import static android.content.Context.UI_MODE_SERVICE; import static androidx.media3.common.C.UNLIMITED_PENDING_FRAME_COUNT; +import static androidx.media3.common.Player.COMMAND_PLAY_PAUSE; +import static androidx.media3.common.Player.COMMAND_PREPARE; import static androidx.media3.common.Player.COMMAND_SEEK_BACK; import static androidx.media3.common.Player.COMMAND_SEEK_FORWARD; import static androidx.media3.common.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM; @@ -124,6 +126,7 @@ import java.util.zip.Inflater; import org.checkerframework.checker.initialization.qual.UnknownInitialization; import org.checkerframework.checker.nullness.compatqual.NullableType; import org.checkerframework.checker.nullness.qual.EnsuresNonNull; +import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.checker.nullness.qual.PolyNull; /** Miscellaneous utility methods. */ @@ -2933,6 +2936,87 @@ public final class Util { return Integer.toString(i, Character.MAX_RADIX); } + /** + * 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. + * + *

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. + */ + @EnsuresNonNullIf(result = false, expression = "#1") + public static boolean shouldShowPlayButton(@Nullable Player player) { + return player == null + || !player.getPlayWhenReady() + || player.getPlaybackState() == Player.STATE_IDLE + || player.getPlaybackState() == Player.STATE_ENDED; + } + + /** + * Updates the player to handle an interaction with a play button. + * + *

This method assumes the play button is enabled if {@link #shouldShowPlayButton} returns + * true. + * + * @param player The {@link Player}. May be null. + * @return Whether a player method was triggered to handle this action. + */ + public static boolean handlePlayButtonAction(@Nullable Player player) { + if (player == null) { + return false; + } + @Player.State int state = player.getPlaybackState(); + boolean methodTriggered = false; + if (state == Player.STATE_IDLE && player.isCommandAvailable(COMMAND_PREPARE)) { + player.prepare(); + methodTriggered = true; + } else if (state == Player.STATE_ENDED + && player.isCommandAvailable(COMMAND_SEEK_TO_DEFAULT_POSITION)) { + player.seekToDefaultPosition(); + methodTriggered = true; + } + if (player.isCommandAvailable(COMMAND_PLAY_PAUSE)) { + player.play(); + methodTriggered = true; + } + return methodTriggered; + } + + /** + * Updates the player to handle an interaction with a pause button. + * + *

This method assumes the pause button is enabled if {@link #shouldShowPlayButton} returns + * false. + * + * @param player The {@link Player}. May be null. + * @return Whether a player method was triggered to handle this action. + */ + public static boolean handlePauseButtonAction(@Nullable Player player) { + if (player != null && player.isCommandAvailable(COMMAND_PLAY_PAUSE)) { + player.pause(); + return true; + } + return false; + } + + /** + * Updates the player to handle an interaction with a play or pause button. + * + *

This method assumes that the UI element enables a play button if {@link + * #shouldShowPlayButton} returns true and a pause button otherwise. + * + * @param player The {@link Player}. May be null. + * @return Whether a player method was triggered to handle this action. + */ + public static boolean handlePlayPauseButtonAction(@Nullable Player player) { + if (shouldShowPlayButton(player)) { + return handlePlayButtonAction(player); + } else { + return handlePauseButtonAction(player); + } + } + @Nullable private static String getSystemProperty(String name) { try { diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java index 87e60129ca..e39293a3c5 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java @@ -31,8 +31,6 @@ import static androidx.media3.common.Player.COMMAND_SET_REPEAT_MODE; import static androidx.media3.common.Player.COMMAND_SET_SHUFFLE_MODE; import static androidx.media3.common.Player.COMMAND_SET_SPEED_AND_PITCH; import static androidx.media3.common.Player.COMMAND_STOP; -import static androidx.media3.common.Player.STATE_ENDED; -import static androidx.media3.common.Player.STATE_IDLE; import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkStateNotNull; import static androidx.media3.common.util.Util.castNonNull; @@ -342,22 +340,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; mediaPlayPauseKeyHandler.clearPendingMediaPlayPauseKey(); dispatchSessionTaskWithPlayerCommand( COMMAND_PLAY_PAUSE, - (controller) -> { - PlayerWrapper playerWrapper = sessionImpl.getPlayerWrapper(); - @Player.State int playbackState = playerWrapper.getPlaybackState(); - if (!playerWrapper.getPlayWhenReady() - || playbackState == STATE_ENDED - || playbackState == STATE_IDLE) { - if (playbackState == STATE_IDLE) { - playerWrapper.prepareIfCommandAvailable(); - } else if (playbackState == STATE_ENDED) { - playerWrapper.seekToDefaultPositionIfCommandAvailable(); - } - playerWrapper.play(); - } else { - playerWrapper.pause(); - } - }, + controller -> Util.handlePlayPauseButtonAction(sessionImpl.getPlayerWrapper()), remoteUserInfo); } @@ -397,15 +380,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; dispatchSessionTaskWithPlayerCommand( COMMAND_PLAY_PAUSE, controller -> { - PlayerWrapper playerWrapper = sessionImpl.getPlayerWrapper(); - @Player.State int playbackState = playerWrapper.getPlaybackState(); - if (playbackState == Player.STATE_IDLE) { - playerWrapper.prepareIfCommandAvailable(); - } else if (playbackState == Player.STATE_ENDED) { - playerWrapper.seekToDefaultPositionIfCommandAvailable(); - } if (sessionImpl.onPlayRequested()) { - playerWrapper.play(); + Util.handlePlayButtonAction(sessionImpl.getPlayerWrapper()); } }, sessionCompat.getCurrentControllerInfo()); @@ -438,7 +414,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; public void onPause() { dispatchSessionTaskWithPlayerCommand( COMMAND_PLAY_PAUSE, - controller -> sessionImpl.getPlayerWrapper().pause(), + controller -> Util.handlePauseButtonAction(sessionImpl.getPlayerWrapper()), sessionCompat.getCurrentControllerInfo()); } diff --git a/libraries/ui/src/main/java/androidx/media3/ui/LegacyPlayerControlView.java b/libraries/ui/src/main/java/androidx/media3/ui/LegacyPlayerControlView.java index b0be016e63..3a7649a027 100644 --- a/libraries/ui/src/main/java/androidx/media3/ui/LegacyPlayerControlView.java +++ b/libraries/ui/src/main/java/androidx/media3/ui/LegacyPlayerControlView.java @@ -54,7 +54,6 @@ import androidx.media3.common.C; import androidx.media3.common.MediaLibraryInfo; import androidx.media3.common.Player; import androidx.media3.common.Player.Events; -import androidx.media3.common.Player.State; import androidx.media3.common.Timeline; import androidx.media3.common.util.Assertions; import androidx.media3.common.util.RepeatModeUtil; @@ -840,22 +839,22 @@ public class LegacyPlayerControlView extends FrameLayout { } boolean requestPlayPauseFocus = false; boolean requestPlayPauseAccessibilityFocus = false; - boolean shouldShowPauseButton = shouldShowPauseButton(); + boolean shouldShowPlayButton = Util.shouldShowPlayButton(player); if (playButton != null) { - requestPlayPauseFocus |= shouldShowPauseButton && playButton.isFocused(); + requestPlayPauseFocus |= !shouldShowPlayButton && playButton.isFocused(); requestPlayPauseAccessibilityFocus |= Util.SDK_INT < 21 ? requestPlayPauseFocus - : (shouldShowPauseButton && Api21.isAccessibilityFocused(playButton)); - playButton.setVisibility(shouldShowPauseButton ? GONE : VISIBLE); + : (!shouldShowPlayButton && Api21.isAccessibilityFocused(playButton)); + playButton.setVisibility(shouldShowPlayButton ? VISIBLE : GONE); } if (pauseButton != null) { - requestPlayPauseFocus |= !shouldShowPauseButton && pauseButton.isFocused(); + requestPlayPauseFocus |= shouldShowPlayButton && pauseButton.isFocused(); requestPlayPauseAccessibilityFocus |= Util.SDK_INT < 21 ? requestPlayPauseFocus - : (!shouldShowPauseButton && Api21.isAccessibilityFocused(pauseButton)); - pauseButton.setVisibility(shouldShowPauseButton ? VISIBLE : GONE); + : (shouldShowPlayButton && Api21.isAccessibilityFocused(pauseButton)); + pauseButton.setVisibility(shouldShowPlayButton ? GONE : VISIBLE); } if (requestPlayPauseFocus) { requestPlayPauseFocus(); @@ -1081,19 +1080,19 @@ public class LegacyPlayerControlView extends FrameLayout { } private void requestPlayPauseFocus() { - boolean shouldShowPauseButton = shouldShowPauseButton(); - if (!shouldShowPauseButton && playButton != null) { + boolean shouldShowPlayButton = Util.shouldShowPlayButton(player); + if (shouldShowPlayButton && playButton != null) { playButton.requestFocus(); - } else if (shouldShowPauseButton && pauseButton != null) { + } else if (!shouldShowPlayButton && pauseButton != null) { pauseButton.requestFocus(); } } private void requestPlayPauseAccessibilityFocus() { - boolean shouldShowPauseButton = shouldShowPauseButton(); - if (!shouldShowPauseButton && playButton != null) { + boolean shouldShowPlayButton = Util.shouldShowPlayButton(player); + if (shouldShowPlayButton && playButton != null) { playButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); - } else if (shouldShowPauseButton && pauseButton != null) { + } else if (!shouldShowPlayButton && pauseButton != null) { pauseButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); } } @@ -1200,13 +1199,13 @@ public class LegacyPlayerControlView extends FrameLayout { switch (keyCode) { case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: case KeyEvent.KEYCODE_HEADSETHOOK: - dispatchPlayPause(player); + Util.handlePlayPauseButtonAction(player); break; case KeyEvent.KEYCODE_MEDIA_PLAY: - dispatchPlay(player); + Util.handlePlayButtonAction(player); break; case KeyEvent.KEYCODE_MEDIA_PAUSE: - dispatchPause(player); + Util.handlePauseButtonAction(player); break; case KeyEvent.KEYCODE_MEDIA_NEXT: player.seekToNext(); @@ -1222,36 +1221,6 @@ public class LegacyPlayerControlView extends FrameLayout { return true; } - private boolean shouldShowPauseButton() { - return player != null - && player.getPlaybackState() != Player.STATE_ENDED - && player.getPlaybackState() != Player.STATE_IDLE - && player.getPlayWhenReady(); - } - - private void dispatchPlayPause(Player player) { - @State int state = player.getPlaybackState(); - if (state == Player.STATE_IDLE || state == Player.STATE_ENDED || !player.getPlayWhenReady()) { - dispatchPlay(player); - } else { - dispatchPause(player); - } - } - - private void dispatchPlay(Player player) { - @State int state = player.getPlaybackState(); - if (state == Player.STATE_IDLE) { - player.prepare(); - } else if (state == Player.STATE_ENDED) { - seekTo(player, player.getCurrentMediaItemIndex(), C.TIME_UNSET); - } - player.play(); - } - - private void dispatchPause(Player player) { - player.pause(); - } - @SuppressLint("InlinedApi") private static boolean isHandledMediaKey(int keyCode) { return keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD @@ -1361,9 +1330,9 @@ public class LegacyPlayerControlView extends FrameLayout { } else if (rewindButton == view) { player.seekBack(); } else if (playButton == view) { - dispatchPlay(player); + Util.handlePlayButtonAction(player); } else if (pauseButton == view) { - dispatchPause(player); + Util.handlePauseButtonAction(player); } else if (repeatToggleButton == view) { player.setRepeatMode( RepeatModeUtil.getNextRepeatMode(player.getRepeatMode(), repeatToggleModes)); diff --git a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java index d5168952d9..edec2cbfac 100644 --- a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java +++ b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java @@ -19,11 +19,9 @@ import static androidx.media3.common.Player.COMMAND_GET_CURRENT_MEDIA_ITEM; import static androidx.media3.common.Player.COMMAND_GET_TIMELINE; import static androidx.media3.common.Player.COMMAND_GET_TRACKS; import static androidx.media3.common.Player.COMMAND_PLAY_PAUSE; -import static androidx.media3.common.Player.COMMAND_PREPARE; import static androidx.media3.common.Player.COMMAND_SEEK_BACK; import static androidx.media3.common.Player.COMMAND_SEEK_FORWARD; import static androidx.media3.common.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM; -import static androidx.media3.common.Player.COMMAND_SEEK_TO_DEFAULT_POSITION; import static androidx.media3.common.Player.COMMAND_SEEK_TO_MEDIA_ITEM; import static androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT; import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS; @@ -75,7 +73,6 @@ import androidx.media3.common.Format; import androidx.media3.common.MediaLibraryInfo; import androidx.media3.common.Player; import androidx.media3.common.Player.Events; -import androidx.media3.common.Player.State; import androidx.media3.common.Timeline; import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackSelectionOverride; @@ -978,17 +975,17 @@ public class PlayerControlView extends FrameLayout { return; } if (playPauseButton != null) { - boolean shouldShowPauseButton = shouldShowPauseButton(); + boolean shouldShowPlayButton = Util.shouldShowPlayButton(player); @DrawableRes int drawableRes = - shouldShowPauseButton - ? R.drawable.exo_styled_controls_pause - : R.drawable.exo_styled_controls_play; + shouldShowPlayButton + ? R.drawable.exo_styled_controls_play + : R.drawable.exo_styled_controls_pause; @StringRes int stringRes = - shouldShowPauseButton - ? R.string.exo_controls_pause_description - : R.string.exo_controls_play_description; + shouldShowPlayButton + ? R.string.exo_controls_play_description + : R.string.exo_controls_pause_description; ((ImageView) playPauseButton) .setImageDrawable(getDrawable(getContext(), resources, drawableRes)); playPauseButton.setContentDescription(resources.getString(stringRes)); @@ -1477,13 +1474,13 @@ public class PlayerControlView extends FrameLayout { switch (keyCode) { case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: case KeyEvent.KEYCODE_HEADSETHOOK: - dispatchPlayPause(player); + Util.handlePlayPauseButtonAction(player); break; case KeyEvent.KEYCODE_MEDIA_PLAY: - dispatchPlay(player); + Util.handlePlayButtonAction(player); break; case KeyEvent.KEYCODE_MEDIA_PAUSE: - dispatchPause(player); + Util.handlePauseButtonAction(player); break; case KeyEvent.KEYCODE_MEDIA_NEXT: if (player.isCommandAvailable(COMMAND_SEEK_TO_NEXT)) { @@ -1539,41 +1536,6 @@ public class PlayerControlView extends FrameLayout { || !player.getCurrentTimeline().isEmpty()); } - private boolean shouldShowPauseButton() { - return player != null - && player.getPlaybackState() != Player.STATE_ENDED - && player.getPlaybackState() != Player.STATE_IDLE - && player.getPlayWhenReady(); - } - - private void dispatchPlayPause(Player player) { - @State int state = player.getPlaybackState(); - if (state == Player.STATE_IDLE || state == Player.STATE_ENDED || !player.getPlayWhenReady()) { - dispatchPlay(player); - } else { - dispatchPause(player); - } - } - - private void dispatchPlay(Player player) { - @State int state = player.getPlaybackState(); - if (state == Player.STATE_IDLE && player.isCommandAvailable(COMMAND_PREPARE)) { - player.prepare(); - } else if (state == Player.STATE_ENDED - && player.isCommandAvailable(COMMAND_SEEK_TO_DEFAULT_POSITION)) { - player.seekToDefaultPosition(); - } - if (player.isCommandAvailable(COMMAND_PLAY_PAUSE)) { - player.play(); - } - } - - private void dispatchPause(Player player) { - if (player.isCommandAvailable(COMMAND_PLAY_PAUSE)) { - player.pause(); - } - } - @SuppressLint("InlinedApi") private static boolean isHandledMediaKey(int keyCode) { return keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD @@ -1743,7 +1705,7 @@ public class PlayerControlView extends FrameLayout { player.seekBack(); } } else if (playPauseButton == view) { - dispatchPlayPause(player); + Util.handlePlayPauseButtonAction(player); } else if (repeatToggleButton == view) { if (player.isCommandAvailable(COMMAND_SET_REPEAT_MODE)) { player.setRepeatMode( diff --git a/libraries/ui/src/main/java/androidx/media3/ui/PlayerNotificationManager.java b/libraries/ui/src/main/java/androidx/media3/ui/PlayerNotificationManager.java index f420489d61..f3860ce962 100644 --- a/libraries/ui/src/main/java/androidx/media3/ui/PlayerNotificationManager.java +++ b/libraries/ui/src/main/java/androidx/media3/ui/PlayerNotificationManager.java @@ -18,11 +18,8 @@ package androidx.media3.ui; import static androidx.media3.common.Player.COMMAND_CHANGE_MEDIA_ITEMS; import static androidx.media3.common.Player.COMMAND_GET_CURRENT_MEDIA_ITEM; import static androidx.media3.common.Player.COMMAND_GET_TIMELINE; -import static androidx.media3.common.Player.COMMAND_PLAY_PAUSE; -import static androidx.media3.common.Player.COMMAND_PREPARE; import static androidx.media3.common.Player.COMMAND_SEEK_BACK; import static androidx.media3.common.Player.COMMAND_SEEK_FORWARD; -import static androidx.media3.common.Player.COMMAND_SEEK_TO_DEFAULT_POSITION; import static androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT; import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS; import static androidx.media3.common.Player.COMMAND_STOP; @@ -1334,10 +1331,10 @@ public class PlayerNotificationManager { stringActions.add(ACTION_REWIND); } if (usePlayPauseActions) { - if (shouldShowPauseButton(player)) { - stringActions.add(ACTION_PAUSE); - } else { + if (Util.shouldShowPlayButton(player)) { stringActions.add(ACTION_PLAY); + } else { + stringActions.add(ACTION_PAUSE); } } if (useFastForwardAction && enableFastForward) { @@ -1382,10 +1379,10 @@ public class PlayerNotificationManager { if (leftSideActionIndex != -1) { actionIndices[actionCounter++] = leftSideActionIndex; } - boolean shouldShowPauseButton = shouldShowPauseButton(player); - if (pauseActionIndex != -1 && shouldShowPauseButton) { + boolean shouldShowPlayButton = Util.shouldShowPlayButton(player); + if (pauseActionIndex != -1 && !shouldShowPlayButton) { actionIndices[actionCounter++] = pauseActionIndex; - } else if (playActionIndex != -1 && !shouldShowPauseButton) { + } else if (playActionIndex != -1 && shouldShowPlayButton) { actionIndices[actionCounter++] = playActionIndex; } if (rightSideActionIndex != -1) { @@ -1401,12 +1398,6 @@ public class PlayerNotificationManager { && player.getPlayWhenReady(); } - private boolean shouldShowPauseButton(Player player) { - return player.getPlaybackState() != Player.STATE_ENDED - && player.getPlaybackState() != Player.STATE_IDLE - && player.getPlayWhenReady(); - } - private void postStartOrUpdateNotification() { if (!mainHandler.hasMessages(MSG_START_OR_UPDATE_NOTIFICATION)) { mainHandler.sendEmptyMessage(MSG_START_OR_UPDATE_NOTIFICATION); @@ -1547,20 +1538,9 @@ public class PlayerNotificationManager { } String action = intent.getAction(); if (ACTION_PLAY.equals(action)) { - if (player.getPlaybackState() == Player.STATE_IDLE - && player.isCommandAvailable(COMMAND_PREPARE)) { - player.prepare(); - } else if (player.getPlaybackState() == Player.STATE_ENDED - && player.isCommandAvailable(COMMAND_SEEK_TO_DEFAULT_POSITION)) { - player.seekToDefaultPosition(); - } - if (player.isCommandAvailable(COMMAND_PLAY_PAUSE)) { - player.play(); - } + Util.handlePlayButtonAction(player); } else if (ACTION_PAUSE.equals(action)) { - if (player.isCommandAvailable(COMMAND_PLAY_PAUSE)) { - player.pause(); - } + Util.handlePauseButtonAction(player); } else if (ACTION_PREVIOUS.equals(action)) { if (player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)) { player.seekToPrevious(); diff --git a/libraries/ui_leanback/src/main/java/androidx/media3/ui/leanback/LeanbackPlayerAdapter.java b/libraries/ui_leanback/src/main/java/androidx/media3/ui/leanback/LeanbackPlayerAdapter.java index 475ace994a..ea0335e035 100644 --- a/libraries/ui_leanback/src/main/java/androidx/media3/ui/leanback/LeanbackPlayerAdapter.java +++ b/libraries/ui_leanback/src/main/java/androidx/media3/ui/leanback/LeanbackPlayerAdapter.java @@ -121,10 +121,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab @Override public boolean isPlaying() { - int playbackState = player.getPlaybackState(); - return playbackState != Player.STATE_IDLE - && playbackState != Player.STATE_ENDED - && player.getPlayWhenReady(); + return !Util.shouldShowPlayButton(player); } @Override @@ -142,13 +139,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab @SuppressWarnings("nullness:dereference.of.nullable") @Override public void play() { - if (player.getPlaybackState() == Player.STATE_IDLE) { - player.prepare(); - } else if (player.getPlaybackState() == Player.STATE_ENDED) { - player.seekToDefaultPosition(player.getCurrentMediaItemIndex()); - } - if (player.isCommandAvailable(Player.COMMAND_PLAY_PAUSE)) { - player.play(); + if (Util.handlePlayButtonAction(player)) { getCallback().onPlayStateChanged(this); } } @@ -157,8 +148,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab @SuppressWarnings("nullness:dereference.of.nullable") @Override public void pause() { - if (player.isCommandAvailable(Player.COMMAND_PLAY_PAUSE)) { - player.pause(); + if (Util.handlePauseButtonAction(player)) { getCallback().onPlayStateChanged(this); } }