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
This commit is contained in:
parent
97272c139c
commit
9128244dc3
@ -49,6 +49,10 @@
|
|||||||
* Fix issue where `MediaController` doesn't update its available commands
|
* Fix issue where `MediaController` doesn't update its available commands
|
||||||
when connected to a legacy `MediaSessionCompat` that updates its
|
when connected to a legacy `MediaSessionCompat` that updates its
|
||||||
actions.
|
actions.
|
||||||
|
* UI:
|
||||||
|
* Add Util methods `shouldShowPlayButton` and
|
||||||
|
`handlePlayPauseButtonAction` to write custom UI elements with a
|
||||||
|
play/pause button.
|
||||||
* Audio:
|
* Audio:
|
||||||
* Fix bug where some playbacks fail when tunneling is enabled and
|
* Fix bug where some playbacks fail when tunneling is enabled and
|
||||||
`AudioProcessors` are active, e.g. for gapless trimming
|
`AudioProcessors` are active, e.g. for gapless trimming
|
||||||
|
4
api.txt
4
api.txt
@ -1233,11 +1233,15 @@ package androidx.media3.common.util {
|
|||||||
method public static boolean checkCleartextTrafficPermitted(androidx.media3.common.MediaItem...);
|
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 String getAdaptiveMimeTypeForContentType(@androidx.media3.common.C.ContentType int);
|
||||||
method @Nullable public static java.util.UUID getDrmUuid(String);
|
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 inferContentType(android.net.Uri);
|
||||||
method @androidx.media3.common.C.ContentType public static int inferContentTypeForExtension(String);
|
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 @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, android.net.Uri...);
|
||||||
method public static boolean maybeRequestReadExternalStoragePermission(android.app.Activity, androidx.media3.common.MediaItem...);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@ package androidx.media3.common.util;
|
|||||||
|
|
||||||
import static android.content.Context.UI_MODE_SERVICE;
|
import static android.content.Context.UI_MODE_SERVICE;
|
||||||
import static androidx.media3.common.C.UNLIMITED_PENDING_FRAME_COUNT;
|
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_BACK;
|
||||||
import static androidx.media3.common.Player.COMMAND_SEEK_FORWARD;
|
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_IN_CURRENT_MEDIA_ITEM;
|
||||||
@ -124,6 +126,7 @@ import java.util.zip.Inflater;
|
|||||||
import org.checkerframework.checker.initialization.qual.UnknownInitialization;
|
import org.checkerframework.checker.initialization.qual.UnknownInitialization;
|
||||||
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||||
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
|
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
|
||||||
|
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
|
||||||
import org.checkerframework.checker.nullness.qual.PolyNull;
|
import org.checkerframework.checker.nullness.qual.PolyNull;
|
||||||
|
|
||||||
/** Miscellaneous utility methods. */
|
/** Miscellaneous utility methods. */
|
||||||
@ -2933,6 +2936,87 @@ public final class Util {
|
|||||||
return Integer.toString(i, Character.MAX_RADIX);
|
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.
|
||||||
|
*
|
||||||
|
* <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.
|
||||||
|
*/
|
||||||
|
@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.
|
||||||
|
*
|
||||||
|
* <p>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.
|
||||||
|
*
|
||||||
|
* <p>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.
|
||||||
|
*
|
||||||
|
* <p>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
|
@Nullable
|
||||||
private static String getSystemProperty(String name) {
|
private static String getSystemProperty(String name) {
|
||||||
try {
|
try {
|
||||||
|
@ -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_SHUFFLE_MODE;
|
||||||
import static androidx.media3.common.Player.COMMAND_SET_SPEED_AND_PITCH;
|
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.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.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
import static androidx.media3.common.util.Util.castNonNull;
|
import static androidx.media3.common.util.Util.castNonNull;
|
||||||
@ -342,22 +340,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
mediaPlayPauseKeyHandler.clearPendingMediaPlayPauseKey();
|
mediaPlayPauseKeyHandler.clearPendingMediaPlayPauseKey();
|
||||||
dispatchSessionTaskWithPlayerCommand(
|
dispatchSessionTaskWithPlayerCommand(
|
||||||
COMMAND_PLAY_PAUSE,
|
COMMAND_PLAY_PAUSE,
|
||||||
(controller) -> {
|
controller -> Util.handlePlayPauseButtonAction(sessionImpl.getPlayerWrapper()),
|
||||||
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();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
remoteUserInfo);
|
remoteUserInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,15 +380,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
dispatchSessionTaskWithPlayerCommand(
|
dispatchSessionTaskWithPlayerCommand(
|
||||||
COMMAND_PLAY_PAUSE,
|
COMMAND_PLAY_PAUSE,
|
||||||
controller -> {
|
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()) {
|
if (sessionImpl.onPlayRequested()) {
|
||||||
playerWrapper.play();
|
Util.handlePlayButtonAction(sessionImpl.getPlayerWrapper());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sessionCompat.getCurrentControllerInfo());
|
sessionCompat.getCurrentControllerInfo());
|
||||||
@ -438,7 +414,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
public void onPause() {
|
public void onPause() {
|
||||||
dispatchSessionTaskWithPlayerCommand(
|
dispatchSessionTaskWithPlayerCommand(
|
||||||
COMMAND_PLAY_PAUSE,
|
COMMAND_PLAY_PAUSE,
|
||||||
controller -> sessionImpl.getPlayerWrapper().pause(),
|
controller -> Util.handlePauseButtonAction(sessionImpl.getPlayerWrapper()),
|
||||||
sessionCompat.getCurrentControllerInfo());
|
sessionCompat.getCurrentControllerInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,6 @@ import androidx.media3.common.C;
|
|||||||
import androidx.media3.common.MediaLibraryInfo;
|
import androidx.media3.common.MediaLibraryInfo;
|
||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.Player.Events;
|
import androidx.media3.common.Player.Events;
|
||||||
import androidx.media3.common.Player.State;
|
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.util.Assertions;
|
import androidx.media3.common.util.Assertions;
|
||||||
import androidx.media3.common.util.RepeatModeUtil;
|
import androidx.media3.common.util.RepeatModeUtil;
|
||||||
@ -840,22 +839,22 @@ public class LegacyPlayerControlView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
boolean requestPlayPauseFocus = false;
|
boolean requestPlayPauseFocus = false;
|
||||||
boolean requestPlayPauseAccessibilityFocus = false;
|
boolean requestPlayPauseAccessibilityFocus = false;
|
||||||
boolean shouldShowPauseButton = shouldShowPauseButton();
|
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player);
|
||||||
if (playButton != null) {
|
if (playButton != null) {
|
||||||
requestPlayPauseFocus |= shouldShowPauseButton && playButton.isFocused();
|
requestPlayPauseFocus |= !shouldShowPlayButton && playButton.isFocused();
|
||||||
requestPlayPauseAccessibilityFocus |=
|
requestPlayPauseAccessibilityFocus |=
|
||||||
Util.SDK_INT < 21
|
Util.SDK_INT < 21
|
||||||
? requestPlayPauseFocus
|
? requestPlayPauseFocus
|
||||||
: (shouldShowPauseButton && Api21.isAccessibilityFocused(playButton));
|
: (!shouldShowPlayButton && Api21.isAccessibilityFocused(playButton));
|
||||||
playButton.setVisibility(shouldShowPauseButton ? GONE : VISIBLE);
|
playButton.setVisibility(shouldShowPlayButton ? VISIBLE : GONE);
|
||||||
}
|
}
|
||||||
if (pauseButton != null) {
|
if (pauseButton != null) {
|
||||||
requestPlayPauseFocus |= !shouldShowPauseButton && pauseButton.isFocused();
|
requestPlayPauseFocus |= shouldShowPlayButton && pauseButton.isFocused();
|
||||||
requestPlayPauseAccessibilityFocus |=
|
requestPlayPauseAccessibilityFocus |=
|
||||||
Util.SDK_INT < 21
|
Util.SDK_INT < 21
|
||||||
? requestPlayPauseFocus
|
? requestPlayPauseFocus
|
||||||
: (!shouldShowPauseButton && Api21.isAccessibilityFocused(pauseButton));
|
: (shouldShowPlayButton && Api21.isAccessibilityFocused(pauseButton));
|
||||||
pauseButton.setVisibility(shouldShowPauseButton ? VISIBLE : GONE);
|
pauseButton.setVisibility(shouldShowPlayButton ? GONE : VISIBLE);
|
||||||
}
|
}
|
||||||
if (requestPlayPauseFocus) {
|
if (requestPlayPauseFocus) {
|
||||||
requestPlayPauseFocus();
|
requestPlayPauseFocus();
|
||||||
@ -1081,19 +1080,19 @@ public class LegacyPlayerControlView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void requestPlayPauseFocus() {
|
private void requestPlayPauseFocus() {
|
||||||
boolean shouldShowPauseButton = shouldShowPauseButton();
|
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player);
|
||||||
if (!shouldShowPauseButton && playButton != null) {
|
if (shouldShowPlayButton && playButton != null) {
|
||||||
playButton.requestFocus();
|
playButton.requestFocus();
|
||||||
} else if (shouldShowPauseButton && pauseButton != null) {
|
} else if (!shouldShowPlayButton && pauseButton != null) {
|
||||||
pauseButton.requestFocus();
|
pauseButton.requestFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void requestPlayPauseAccessibilityFocus() {
|
private void requestPlayPauseAccessibilityFocus() {
|
||||||
boolean shouldShowPauseButton = shouldShowPauseButton();
|
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player);
|
||||||
if (!shouldShowPauseButton && playButton != null) {
|
if (shouldShowPlayButton && playButton != null) {
|
||||||
playButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
|
playButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
|
||||||
} else if (shouldShowPauseButton && pauseButton != null) {
|
} else if (!shouldShowPlayButton && pauseButton != null) {
|
||||||
pauseButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
|
pauseButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1200,13 +1199,13 @@ public class LegacyPlayerControlView extends FrameLayout {
|
|||||||
switch (keyCode) {
|
switch (keyCode) {
|
||||||
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||||
case KeyEvent.KEYCODE_HEADSETHOOK:
|
case KeyEvent.KEYCODE_HEADSETHOOK:
|
||||||
dispatchPlayPause(player);
|
Util.handlePlayPauseButtonAction(player);
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
||||||
dispatchPlay(player);
|
Util.handlePlayButtonAction(player);
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
||||||
dispatchPause(player);
|
Util.handlePauseButtonAction(player);
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||||
player.seekToNext();
|
player.seekToNext();
|
||||||
@ -1222,36 +1221,6 @@ public class LegacyPlayerControlView extends FrameLayout {
|
|||||||
return true;
|
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")
|
@SuppressLint("InlinedApi")
|
||||||
private static boolean isHandledMediaKey(int keyCode) {
|
private static boolean isHandledMediaKey(int keyCode) {
|
||||||
return keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD
|
return keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD
|
||||||
@ -1361,9 +1330,9 @@ public class LegacyPlayerControlView extends FrameLayout {
|
|||||||
} else if (rewindButton == view) {
|
} else if (rewindButton == view) {
|
||||||
player.seekBack();
|
player.seekBack();
|
||||||
} else if (playButton == view) {
|
} else if (playButton == view) {
|
||||||
dispatchPlay(player);
|
Util.handlePlayButtonAction(player);
|
||||||
} else if (pauseButton == view) {
|
} else if (pauseButton == view) {
|
||||||
dispatchPause(player);
|
Util.handlePauseButtonAction(player);
|
||||||
} else if (repeatToggleButton == view) {
|
} else if (repeatToggleButton == view) {
|
||||||
player.setRepeatMode(
|
player.setRepeatMode(
|
||||||
RepeatModeUtil.getNextRepeatMode(player.getRepeatMode(), repeatToggleModes));
|
RepeatModeUtil.getNextRepeatMode(player.getRepeatMode(), repeatToggleModes));
|
||||||
|
@ -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_TIMELINE;
|
||||||
import static androidx.media3.common.Player.COMMAND_GET_TRACKS;
|
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_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_BACK;
|
||||||
import static androidx.media3.common.Player.COMMAND_SEEK_FORWARD;
|
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_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_MEDIA_ITEM;
|
||||||
import static androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT;
|
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_SEEK_TO_PREVIOUS;
|
||||||
@ -75,7 +73,6 @@ import androidx.media3.common.Format;
|
|||||||
import androidx.media3.common.MediaLibraryInfo;
|
import androidx.media3.common.MediaLibraryInfo;
|
||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.Player.Events;
|
import androidx.media3.common.Player.Events;
|
||||||
import androidx.media3.common.Player.State;
|
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.TrackSelectionOverride;
|
import androidx.media3.common.TrackSelectionOverride;
|
||||||
@ -978,17 +975,17 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (playPauseButton != null) {
|
if (playPauseButton != null) {
|
||||||
boolean shouldShowPauseButton = shouldShowPauseButton();
|
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player);
|
||||||
@DrawableRes
|
@DrawableRes
|
||||||
int drawableRes =
|
int drawableRes =
|
||||||
shouldShowPauseButton
|
shouldShowPlayButton
|
||||||
? R.drawable.exo_styled_controls_pause
|
? R.drawable.exo_styled_controls_play
|
||||||
: R.drawable.exo_styled_controls_play;
|
: R.drawable.exo_styled_controls_pause;
|
||||||
@StringRes
|
@StringRes
|
||||||
int stringRes =
|
int stringRes =
|
||||||
shouldShowPauseButton
|
shouldShowPlayButton
|
||||||
? R.string.exo_controls_pause_description
|
? R.string.exo_controls_play_description
|
||||||
: R.string.exo_controls_play_description;
|
: R.string.exo_controls_pause_description;
|
||||||
((ImageView) playPauseButton)
|
((ImageView) playPauseButton)
|
||||||
.setImageDrawable(getDrawable(getContext(), resources, drawableRes));
|
.setImageDrawable(getDrawable(getContext(), resources, drawableRes));
|
||||||
playPauseButton.setContentDescription(resources.getString(stringRes));
|
playPauseButton.setContentDescription(resources.getString(stringRes));
|
||||||
@ -1477,13 +1474,13 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
switch (keyCode) {
|
switch (keyCode) {
|
||||||
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||||
case KeyEvent.KEYCODE_HEADSETHOOK:
|
case KeyEvent.KEYCODE_HEADSETHOOK:
|
||||||
dispatchPlayPause(player);
|
Util.handlePlayPauseButtonAction(player);
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
||||||
dispatchPlay(player);
|
Util.handlePlayButtonAction(player);
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
||||||
dispatchPause(player);
|
Util.handlePauseButtonAction(player);
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||||
if (player.isCommandAvailable(COMMAND_SEEK_TO_NEXT)) {
|
if (player.isCommandAvailable(COMMAND_SEEK_TO_NEXT)) {
|
||||||
@ -1539,41 +1536,6 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
|| !player.getCurrentTimeline().isEmpty());
|
|| !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")
|
@SuppressLint("InlinedApi")
|
||||||
private static boolean isHandledMediaKey(int keyCode) {
|
private static boolean isHandledMediaKey(int keyCode) {
|
||||||
return keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD
|
return keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD
|
||||||
@ -1743,7 +1705,7 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
player.seekBack();
|
player.seekBack();
|
||||||
}
|
}
|
||||||
} else if (playPauseButton == view) {
|
} else if (playPauseButton == view) {
|
||||||
dispatchPlayPause(player);
|
Util.handlePlayPauseButtonAction(player);
|
||||||
} else if (repeatToggleButton == view) {
|
} else if (repeatToggleButton == view) {
|
||||||
if (player.isCommandAvailable(COMMAND_SET_REPEAT_MODE)) {
|
if (player.isCommandAvailable(COMMAND_SET_REPEAT_MODE)) {
|
||||||
player.setRepeatMode(
|
player.setRepeatMode(
|
||||||
|
@ -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_CHANGE_MEDIA_ITEMS;
|
||||||
import static androidx.media3.common.Player.COMMAND_GET_CURRENT_MEDIA_ITEM;
|
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_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_BACK;
|
||||||
import static androidx.media3.common.Player.COMMAND_SEEK_FORWARD;
|
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_NEXT;
|
||||||
import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS;
|
import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS;
|
||||||
import static androidx.media3.common.Player.COMMAND_STOP;
|
import static androidx.media3.common.Player.COMMAND_STOP;
|
||||||
@ -1334,10 +1331,10 @@ public class PlayerNotificationManager {
|
|||||||
stringActions.add(ACTION_REWIND);
|
stringActions.add(ACTION_REWIND);
|
||||||
}
|
}
|
||||||
if (usePlayPauseActions) {
|
if (usePlayPauseActions) {
|
||||||
if (shouldShowPauseButton(player)) {
|
if (Util.shouldShowPlayButton(player)) {
|
||||||
stringActions.add(ACTION_PAUSE);
|
|
||||||
} else {
|
|
||||||
stringActions.add(ACTION_PLAY);
|
stringActions.add(ACTION_PLAY);
|
||||||
|
} else {
|
||||||
|
stringActions.add(ACTION_PAUSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (useFastForwardAction && enableFastForward) {
|
if (useFastForwardAction && enableFastForward) {
|
||||||
@ -1382,10 +1379,10 @@ public class PlayerNotificationManager {
|
|||||||
if (leftSideActionIndex != -1) {
|
if (leftSideActionIndex != -1) {
|
||||||
actionIndices[actionCounter++] = leftSideActionIndex;
|
actionIndices[actionCounter++] = leftSideActionIndex;
|
||||||
}
|
}
|
||||||
boolean shouldShowPauseButton = shouldShowPauseButton(player);
|
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player);
|
||||||
if (pauseActionIndex != -1 && shouldShowPauseButton) {
|
if (pauseActionIndex != -1 && !shouldShowPlayButton) {
|
||||||
actionIndices[actionCounter++] = pauseActionIndex;
|
actionIndices[actionCounter++] = pauseActionIndex;
|
||||||
} else if (playActionIndex != -1 && !shouldShowPauseButton) {
|
} else if (playActionIndex != -1 && shouldShowPlayButton) {
|
||||||
actionIndices[actionCounter++] = playActionIndex;
|
actionIndices[actionCounter++] = playActionIndex;
|
||||||
}
|
}
|
||||||
if (rightSideActionIndex != -1) {
|
if (rightSideActionIndex != -1) {
|
||||||
@ -1401,12 +1398,6 @@ public class PlayerNotificationManager {
|
|||||||
&& player.getPlayWhenReady();
|
&& player.getPlayWhenReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldShowPauseButton(Player player) {
|
|
||||||
return player.getPlaybackState() != Player.STATE_ENDED
|
|
||||||
&& player.getPlaybackState() != Player.STATE_IDLE
|
|
||||||
&& player.getPlayWhenReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void postStartOrUpdateNotification() {
|
private void postStartOrUpdateNotification() {
|
||||||
if (!mainHandler.hasMessages(MSG_START_OR_UPDATE_NOTIFICATION)) {
|
if (!mainHandler.hasMessages(MSG_START_OR_UPDATE_NOTIFICATION)) {
|
||||||
mainHandler.sendEmptyMessage(MSG_START_OR_UPDATE_NOTIFICATION);
|
mainHandler.sendEmptyMessage(MSG_START_OR_UPDATE_NOTIFICATION);
|
||||||
@ -1547,20 +1538,9 @@ public class PlayerNotificationManager {
|
|||||||
}
|
}
|
||||||
String action = intent.getAction();
|
String action = intent.getAction();
|
||||||
if (ACTION_PLAY.equals(action)) {
|
if (ACTION_PLAY.equals(action)) {
|
||||||
if (player.getPlaybackState() == Player.STATE_IDLE
|
Util.handlePlayButtonAction(player);
|
||||||
&& 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();
|
|
||||||
}
|
|
||||||
} else if (ACTION_PAUSE.equals(action)) {
|
} else if (ACTION_PAUSE.equals(action)) {
|
||||||
if (player.isCommandAvailable(COMMAND_PLAY_PAUSE)) {
|
Util.handlePauseButtonAction(player);
|
||||||
player.pause();
|
|
||||||
}
|
|
||||||
} else if (ACTION_PREVIOUS.equals(action)) {
|
} else if (ACTION_PREVIOUS.equals(action)) {
|
||||||
if (player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)) {
|
if (player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)) {
|
||||||
player.seekToPrevious();
|
player.seekToPrevious();
|
||||||
|
@ -121,10 +121,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlaying() {
|
public boolean isPlaying() {
|
||||||
int playbackState = player.getPlaybackState();
|
return !Util.shouldShowPlayButton(player);
|
||||||
return playbackState != Player.STATE_IDLE
|
|
||||||
&& playbackState != Player.STATE_ENDED
|
|
||||||
&& player.getPlayWhenReady();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -142,13 +139,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab
|
|||||||
@SuppressWarnings("nullness:dereference.of.nullable")
|
@SuppressWarnings("nullness:dereference.of.nullable")
|
||||||
@Override
|
@Override
|
||||||
public void play() {
|
public void play() {
|
||||||
if (player.getPlaybackState() == Player.STATE_IDLE) {
|
if (Util.handlePlayButtonAction(player)) {
|
||||||
player.prepare();
|
|
||||||
} else if (player.getPlaybackState() == Player.STATE_ENDED) {
|
|
||||||
player.seekToDefaultPosition(player.getCurrentMediaItemIndex());
|
|
||||||
}
|
|
||||||
if (player.isCommandAvailable(Player.COMMAND_PLAY_PAUSE)) {
|
|
||||||
player.play();
|
|
||||||
getCallback().onPlayStateChanged(this);
|
getCallback().onPlayStateChanged(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,8 +148,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab
|
|||||||
@SuppressWarnings("nullness:dereference.of.nullable")
|
@SuppressWarnings("nullness:dereference.of.nullable")
|
||||||
@Override
|
@Override
|
||||||
public void pause() {
|
public void pause() {
|
||||||
if (player.isCommandAvailable(Player.COMMAND_PLAY_PAUSE)) {
|
if (Util.handlePauseButtonAction(player)) {
|
||||||
player.pause();
|
|
||||||
getCallback().onPlayStateChanged(this);
|
getCallback().onPlayStateChanged(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user