Add missing command checks in UI module

The commands are partly checked already before enabling
features or calling player methods, but the checks were
still missing in many places.

#minor-release

PiperOrigin-RevId: 504589888
This commit is contained in:
tonihei 2023-01-25 17:56:13 +00:00 committed by christosts
parent e8ffc7b6f8
commit e2ece2f5bc
6 changed files with 208 additions and 68 deletions

View File

@ -15,6 +15,8 @@
*/
package androidx.media3.ui;
import static androidx.media3.common.Player.COMMAND_GET_MEDIA_ITEMS_METADATA;
import android.app.PendingIntent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@ -48,6 +50,9 @@ public final class DefaultMediaDescriptionAdapter implements MediaDescriptionAda
@Override
public CharSequence getCurrentContentTitle(Player player) {
if (!player.isCommandAvailable(COMMAND_GET_MEDIA_ITEMS_METADATA)) {
return "";
}
@Nullable CharSequence displayTitle = player.getMediaMetadata().displayTitle;
if (!TextUtils.isEmpty(displayTitle)) {
return displayTitle;
@ -66,6 +71,9 @@ public final class DefaultMediaDescriptionAdapter implements MediaDescriptionAda
@Nullable
@Override
public CharSequence getCurrentContentText(Player player) {
if (!player.isCommandAvailable(COMMAND_GET_MEDIA_ITEMS_METADATA)) {
return null;
}
@Nullable CharSequence artist = player.getMediaMetadata().artist;
if (!TextUtils.isEmpty(artist)) {
return artist;
@ -77,6 +85,9 @@ public final class DefaultMediaDescriptionAdapter implements MediaDescriptionAda
@Nullable
@Override
public Bitmap getCurrentLargeIcon(Player player, BitmapCallback callback) {
if (!player.isCommandAvailable(COMMAND_GET_MEDIA_ITEMS_METADATA)) {
return null;
}
@Nullable byte[] data = player.getMediaMetadata().artworkData;
if (data == null) {
return null;

View File

@ -15,11 +15,22 @@
*/
package androidx.media3.ui;
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;
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_SET_TRACK_SELECTION_PARAMETERS;
import static androidx.media3.common.Player.EVENT_AVAILABLE_COMMANDS_CHANGED;
import static androidx.media3.common.Player.EVENT_IS_PLAYING_CHANGED;
import static androidx.media3.common.Player.EVENT_PLAYBACK_PARAMETERS_CHANGED;
@ -35,6 +46,7 @@ import static androidx.media3.common.Player.EVENT_TRACKS_CHANGED;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Util.castNonNull;
import static androidx.media3.common.util.Util.getDrawable;
import static androidx.media3.common.util.Util.msToUs;
import android.annotation.SuppressLint;
import android.content.Context;
@ -798,7 +810,7 @@ public class PlayerControlView extends FrameLayout {
*/
public void setRepeatToggleModes(@RepeatModeUtil.RepeatToggleModes int repeatToggleModes) {
this.repeatToggleModes = repeatToggleModes;
if (player != null) {
if (player != null && player.isCommandAvailable(COMMAND_SET_REPEAT_MODE)) {
@Player.RepeatMode int currentMode = player.getRepeatMode();
if (repeatToggleModes == RepeatModeUtil.REPEAT_TOGGLE_MODE_NONE
&& currentMode != Player.REPEAT_MODE_OFF) {
@ -1062,7 +1074,7 @@ public class PlayerControlView extends FrameLayout {
}
@Nullable Player player = this.player;
if (player == null) {
if (player == null || !player.isCommandAvailable(COMMAND_SET_REPEAT_MODE)) {
updateButton(/* enabled= */ false, repeatToggleButton);
repeatToggleButton.setImageDrawable(repeatOffButtonDrawable);
repeatToggleButton.setContentDescription(repeatOffButtonContentDescription);
@ -1096,7 +1108,7 @@ public class PlayerControlView extends FrameLayout {
@Nullable Player player = this.player;
if (!controlViewLayoutManager.getShowButton(shuffleButton)) {
updateButton(/* enabled= */ false, shuffleButton);
} else if (player == null) {
} else if (player == null || !player.isCommandAvailable(COMMAND_SET_SHUFFLE_MODE)) {
updateButton(/* enabled= */ false, shuffleButton);
shuffleButton.setImageDrawable(shuffleOffButtonDrawable);
shuffleButton.setContentDescription(shuffleOffContentDescription);
@ -1120,8 +1132,8 @@ public class PlayerControlView extends FrameLayout {
textTrackSelectionAdapter.clear();
audioTrackSelectionAdapter.clear();
if (player == null
|| !player.isCommandAvailable(Player.COMMAND_GET_TRACKS)
|| !player.isCommandAvailable(Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
|| !player.isCommandAvailable(COMMAND_GET_TRACKS)
|| !player.isCommandAvailable(COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
return;
}
Tracks tracks = player.getCurrentTracks();
@ -1162,12 +1174,14 @@ public class PlayerControlView extends FrameLayout {
if (player == null) {
return;
}
multiWindowTimeBar =
showMultiWindowTimeBar && canShowMultiWindowTimeBar(player.getCurrentTimeline(), window);
multiWindowTimeBar = showMultiWindowTimeBar && canShowMultiWindowTimeBar(player, window);
currentWindowOffset = 0;
long durationUs = 0;
int adGroupCount = 0;
Timeline timeline = player.getCurrentTimeline();
Timeline timeline =
player.isCommandAvailable(COMMAND_GET_TIMELINE)
? player.getCurrentTimeline()
: Timeline.EMPTY;
if (!timeline.isEmpty()) {
int currentWindowIndex = player.getCurrentMediaItemIndex();
int firstWindowIndex = multiWindowTimeBar ? 0 : currentWindowIndex;
@ -1209,6 +1223,11 @@ public class PlayerControlView extends FrameLayout {
}
durationUs += window.durationUs;
}
} else if (player.isCommandAvailable(COMMAND_GET_CURRENT_MEDIA_ITEM)) {
long playerDurationMs = player.getContentDuration();
if (playerDurationMs != C.TIME_UNSET) {
durationUs = msToUs(playerDurationMs);
}
}
long durationMs = Util.usToMs(durationUs);
if (durationView != null) {
@ -1236,7 +1255,7 @@ public class PlayerControlView extends FrameLayout {
@Nullable Player player = this.player;
long position = 0;
long bufferedPosition = 0;
if (player != null) {
if (player != null && player.isCommandAvailable(COMMAND_GET_CURRENT_MEDIA_ITEM)) {
position = currentWindowOffset + player.getContentPosition();
bufferedPosition = currentWindowOffset + player.getContentBufferedPosition();
}
@ -1314,7 +1333,7 @@ public class PlayerControlView extends FrameLayout {
}
private void setPlaybackSpeed(float speed) {
if (player == null) {
if (player == null || !player.isCommandAvailable(COMMAND_SET_SPEED_AND_PITCH)) {
return;
}
player.setPlaybackParameters(player.getPlaybackParameters().withSpeed(speed));
@ -1335,11 +1354,12 @@ public class PlayerControlView extends FrameLayout {
}
private void seekToTimeBarPosition(Player player, long positionMs) {
int windowIndex;
Timeline timeline = player.getCurrentTimeline();
if (multiWindowTimeBar && !timeline.isEmpty()) {
if (multiWindowTimeBar
&& player.isCommandAvailable(COMMAND_GET_TIMELINE)
&& player.isCommandAvailable(COMMAND_SEEK_TO_MEDIA_ITEM)) {
Timeline timeline = player.getCurrentTimeline();
int windowCount = timeline.getWindowCount();
windowIndex = 0;
int windowIndex = 0;
while (true) {
long windowDurationMs = timeline.getWindow(windowIndex, window).getDurationMs();
if (positionMs < windowDurationMs) {
@ -1352,17 +1372,13 @@ public class PlayerControlView extends FrameLayout {
positionMs -= windowDurationMs;
windowIndex++;
}
} else {
windowIndex = player.getCurrentMediaItemIndex();
player.seekTo(windowIndex, positionMs);
} else if (player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)) {
player.seekTo(positionMs);
}
seekTo(player, windowIndex, positionMs);
updateProgress();
}
private void seekTo(Player player, int windowIndex, long positionMs) {
player.seekTo(windowIndex, positionMs);
}
private void onFullScreenButtonClicked(View v) {
if (onFullScreenModeChangedListener == null) {
return;
@ -1440,10 +1456,12 @@ public class PlayerControlView extends FrameLayout {
}
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
if (player.getPlaybackState() != Player.STATE_ENDED) {
if (player.getPlaybackState() != Player.STATE_ENDED
&& player.isCommandAvailable(COMMAND_SEEK_FORWARD)) {
player.seekForward();
}
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_REWIND) {
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_REWIND
&& player.isCommandAvailable(COMMAND_SEEK_BACK)) {
player.seekBack();
} else if (event.getRepeatCount() == 0) {
switch (keyCode) {
@ -1458,10 +1476,14 @@ public class PlayerControlView extends FrameLayout {
dispatchPause(player);
break;
case KeyEvent.KEYCODE_MEDIA_NEXT:
player.seekToNext();
if (player.isCommandAvailable(COMMAND_SEEK_TO_NEXT)) {
player.seekToNext();
}
break;
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
player.seekToPrevious();
if (player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)) {
player.seekToPrevious();
}
break;
default:
break;
@ -1501,7 +1523,10 @@ public class PlayerControlView extends FrameLayout {
}
private boolean shouldEnablePlayPauseButton() {
return player != null && !player.getCurrentTimeline().isEmpty();
return player != null
&& player.isCommandAvailable(COMMAND_PLAY_PAUSE)
&& (!player.isCommandAvailable(COMMAND_GET_TIMELINE)
|| !player.getCurrentTimeline().isEmpty());
}
private boolean shouldShowPauseButton() {
@ -1522,16 +1547,21 @@ public class PlayerControlView extends FrameLayout {
private void dispatchPlay(Player player) {
@State int state = player.getPlaybackState();
if (state == Player.STATE_IDLE) {
if (state == Player.STATE_IDLE && player.isCommandAvailable(COMMAND_PREPARE)) {
player.prepare();
} else if (state == Player.STATE_ENDED) {
seekTo(player, player.getCurrentMediaItemIndex(), C.TIME_UNSET);
} else if (state == Player.STATE_ENDED
&& player.isCommandAvailable(COMMAND_SEEK_TO_DEFAULT_POSITION)) {
player.seekToDefaultPosition();
}
if (player.isCommandAvailable(COMMAND_PLAY_PAUSE)) {
player.play();
}
player.play();
}
private void dispatchPause(Player player) {
player.pause();
if (player.isCommandAvailable(COMMAND_PLAY_PAUSE)) {
player.pause();
}
}
@SuppressLint("InlinedApi")
@ -1547,13 +1577,18 @@ public class PlayerControlView extends FrameLayout {
}
/**
* Returns whether the specified {@code timeline} can be shown on a multi-window time bar.
* Returns whether the specified {@code player} can be shown on a multi-window time bar.
*
* @param timeline The {@link Timeline} to check.
* @param player The {@link Player} to check.
* @param window A scratch {@link Timeline.Window} instance.
* @return Whether the specified timeline can be shown on a multi-window time bar.
*/
private static boolean canShowMultiWindowTimeBar(Timeline timeline, Timeline.Window window) {
private static boolean canShowMultiWindowTimeBar(Player player, Timeline.Window window) {
if (!player.isCommandAvailable(COMMAND_GET_TIMELINE)
|| !player.isCommandAvailable(COMMAND_SEEK_TO_MEDIA_ITEM)) {
return false;
}
Timeline timeline = player.getCurrentTimeline();
if (timeline.getWindowCount() > MAX_WINDOWS_FOR_MULTI_WINDOW_TIME_BAR) {
return false;
}
@ -1674,22 +1709,33 @@ public class PlayerControlView extends FrameLayout {
}
controlViewLayoutManager.resetHideCallbacks();
if (nextButton == view) {
player.seekToNext();
if (player.isCommandAvailable(COMMAND_SEEK_TO_NEXT)) {
player.seekToNext();
}
} else if (previousButton == view) {
player.seekToPrevious();
if (player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)) {
player.seekToPrevious();
}
} else if (fastForwardButton == view) {
if (player.getPlaybackState() != Player.STATE_ENDED) {
if (player.getPlaybackState() != Player.STATE_ENDED
&& player.isCommandAvailable(COMMAND_SEEK_FORWARD)) {
player.seekForward();
}
} else if (rewindButton == view) {
player.seekBack();
if (player.isCommandAvailable(COMMAND_SEEK_BACK)) {
player.seekBack();
}
} else if (playPauseButton == view) {
dispatchPlayPause(player);
} else if (repeatToggleButton == view) {
player.setRepeatMode(
RepeatModeUtil.getNextRepeatMode(player.getRepeatMode(), repeatToggleModes));
if (player.isCommandAvailable(COMMAND_SET_REPEAT_MODE)) {
player.setRepeatMode(
RepeatModeUtil.getNextRepeatMode(player.getRepeatMode(), repeatToggleModes));
}
} else if (shuffleButton == view) {
player.setShuffleModeEnabled(!player.getShuffleModeEnabled());
if (player.isCommandAvailable(COMMAND_SET_SHUFFLE_MODE)) {
player.setShuffleModeEnabled(!player.getShuffleModeEnabled());
}
} else if (settingsButton == view) {
controlViewLayoutManager.removeHideCallbacks();
displaySettingsWindow(settingsAdapter, settingsButton);
@ -1892,7 +1938,8 @@ public class PlayerControlView extends FrameLayout {
holder.checkView.setVisibility(isTrackSelectionOff ? VISIBLE : INVISIBLE);
holder.itemView.setOnClickListener(
v -> {
if (player != null) {
if (player != null
&& player.isCommandAvailable(COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
TrackSelectionParameters trackSelectionParameters =
player.getTrackSelectionParameters();
player.setTrackSelectionParameters(
@ -1933,7 +1980,8 @@ public class PlayerControlView extends FrameLayout {
holder.checkView.setVisibility(hasSelectionOverride ? INVISIBLE : VISIBLE);
holder.itemView.setOnClickListener(
v -> {
if (player == null) {
if (player == null
|| !player.isCommandAvailable(COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
return;
}
TrackSelectionParameters trackSelectionParameters =
@ -2036,6 +2084,9 @@ public class PlayerControlView extends FrameLayout {
holder.checkView.setVisibility(explicitlySelected ? VISIBLE : INVISIBLE);
holder.itemView.setOnClickListener(
v -> {
if (!player.isCommandAvailable(COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
return;
}
TrackSelectionParameters trackSelectionParameters =
player.getTrackSelectionParameters();
player.setTrackSelectionParameters(

View File

@ -15,10 +15,17 @@
*/
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;
import static androidx.media3.common.Player.EVENT_IS_PLAYING_CHANGED;
import static androidx.media3.common.Player.EVENT_MEDIA_METADATA_CHANGED;
import static androidx.media3.common.Player.EVENT_PLAYBACK_PARAMETERS_CHANGED;
@ -1205,7 +1212,9 @@ public class PlayerNotificationManager {
@Nullable NotificationCompat.Builder builder,
boolean ongoing,
@Nullable Bitmap largeIcon) {
if (player.getPlaybackState() == Player.STATE_IDLE && player.getCurrentTimeline().isEmpty()) {
if (player.getPlaybackState() == Player.STATE_IDLE
&& player.isCommandAvailable(COMMAND_GET_TIMELINE)
&& player.getCurrentTimeline().isEmpty()) {
builderActions = null;
return null;
}
@ -1259,6 +1268,7 @@ public class PlayerNotificationManager {
// Changing "showWhen" causes notification flicker if SDK_INT < 21.
if (Util.SDK_INT >= 21
&& useChronometer
&& player.isCommandAvailable(COMMAND_GET_CURRENT_MEDIA_ITEM)
&& player.isPlaying()
&& !player.isPlayingAd()
&& !player.isCurrentMediaItemDynamic()
@ -1537,24 +1547,43 @@ public class PlayerNotificationManager {
}
String action = intent.getAction();
if (ACTION_PLAY.equals(action)) {
if (player.getPlaybackState() == Player.STATE_IDLE) {
if (player.getPlaybackState() == Player.STATE_IDLE
&& player.isCommandAvailable(COMMAND_PREPARE)) {
player.prepare();
} else if (player.getPlaybackState() == Player.STATE_ENDED) {
player.seekToDefaultPosition(player.getCurrentMediaItemIndex());
} else if (player.getPlaybackState() == Player.STATE_ENDED
&& player.isCommandAvailable(COMMAND_SEEK_TO_DEFAULT_POSITION)) {
player.seekToDefaultPosition();
}
if (player.isCommandAvailable(COMMAND_PLAY_PAUSE)) {
player.play();
}
player.play();
} else if (ACTION_PAUSE.equals(action)) {
player.pause();
if (player.isCommandAvailable(COMMAND_PLAY_PAUSE)) {
player.pause();
}
} else if (ACTION_PREVIOUS.equals(action)) {
player.seekToPrevious();
if (player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)) {
player.seekToPrevious();
}
} else if (ACTION_REWIND.equals(action)) {
player.seekBack();
if (player.isCommandAvailable(COMMAND_SEEK_BACK)) {
player.seekBack();
}
} else if (ACTION_FAST_FORWARD.equals(action)) {
player.seekForward();
if (player.isCommandAvailable(COMMAND_SEEK_FORWARD)) {
player.seekForward();
}
} else if (ACTION_NEXT.equals(action)) {
player.seekToNext();
if (player.isCommandAvailable(COMMAND_SEEK_TO_NEXT)) {
player.seekToNext();
}
} else if (ACTION_STOP.equals(action)) {
player.stop(/* reset= */ true);
if (player.isCommandAvailable(COMMAND_STOP)) {
player.stop();
}
if (player.isCommandAvailable(COMMAND_CHANGE_MEDIA_ITEMS)) {
player.clearMediaItems();
}
} else if (ACTION_DISMISS.equals(action)) {
stopNotification(/* dismissedByUser= */ true);
} else if (action != null

View File

@ -15,7 +15,11 @@
*/
package androidx.media3.ui;
import static androidx.media3.common.Player.COMMAND_GET_CURRENT_MEDIA_ITEM;
import static androidx.media3.common.Player.COMMAND_GET_MEDIA_ITEMS_METADATA;
import static androidx.media3.common.Player.COMMAND_GET_TEXT;
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_SET_VIDEO_SURFACE;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Util.getDrawable;
@ -527,10 +531,12 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
@Nullable Player oldPlayer = this.player;
if (oldPlayer != null) {
oldPlayer.removeListener(componentListener);
if (surfaceView instanceof TextureView) {
oldPlayer.clearVideoTextureView((TextureView) surfaceView);
} else if (surfaceView instanceof SurfaceView) {
oldPlayer.clearVideoSurfaceView((SurfaceView) surfaceView);
if (oldPlayer.isCommandAvailable(COMMAND_SET_VIDEO_SURFACE)) {
if (surfaceView instanceof TextureView) {
oldPlayer.clearVideoTextureView((TextureView) surfaceView);
} else if (surfaceView instanceof SurfaceView) {
oldPlayer.clearVideoSurfaceView((SurfaceView) surfaceView);
}
}
}
if (subtitleView != null) {
@ -743,7 +749,9 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (player != null && player.isPlayingAd()) {
if (player != null
&& player.isCommandAvailable(COMMAND_GET_CURRENT_MEDIA_ITEM)
&& player.isPlayingAd()) {
return super.dispatchKeyEvent(event);
}
@ -1274,7 +1282,8 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
}
int playbackState = player.getPlaybackState();
return controllerAutoShow
&& !player.getCurrentTimeline().isEmpty()
&& (!player.isCommandAvailable(COMMAND_GET_TIMELINE)
|| !player.getCurrentTimeline().isEmpty())
&& (playbackState == Player.STATE_IDLE
|| playbackState == Player.STATE_ENDED
|| !checkNotNull(player).getPlayWhenReady());
@ -1289,12 +1298,17 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
}
private boolean isPlayingAd() {
return player != null && player.isPlayingAd() && player.getPlayWhenReady();
return player != null
&& player.isCommandAvailable(COMMAND_GET_CURRENT_MEDIA_ITEM)
&& player.isPlayingAd()
&& player.getPlayWhenReady();
}
private void updateForCurrentTrackSelections(boolean isNewPlayer) {
@Nullable Player player = this.player;
if (player == null || player.getCurrentTracks().isEmpty()) {
if (player == null
|| !player.isCommandAvailable(COMMAND_GET_TRACKS)
|| player.getCurrentTracks().isEmpty()) {
if (!keepContentOnPlayerReset) {
hideArtwork();
closeShutter();
@ -1318,7 +1332,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
closeShutter();
// Display artwork if enabled and available, else hide it.
if (useArtwork()) {
if (setArtworkFromMediaMetadata(player.getMediaMetadata())) {
if (setArtworkFromMediaMetadata(player)) {
return;
}
if (setDrawableArtwork(defaultArtwork)) {
@ -1330,7 +1344,11 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
}
@RequiresNonNull("artworkView")
private boolean setArtworkFromMediaMetadata(MediaMetadata mediaMetadata) {
private boolean setArtworkFromMediaMetadata(Player player) {
if (!player.isCommandAvailable(COMMAND_GET_MEDIA_ITEMS_METADATA)) {
return false;
}
MediaMetadata mediaMetadata = player.getMediaMetadata();
if (mediaMetadata.artworkData == null) {
return false;
}
@ -1549,10 +1567,14 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
// is necessary to avoid closing the shutter when such a transition occurs. See:
// https://github.com/google/ExoPlayer/issues/5507.
Player player = checkNotNull(PlayerView.this.player);
Timeline timeline = player.getCurrentTimeline();
Timeline timeline =
player.isCommandAvailable(COMMAND_GET_TIMELINE)
? player.getCurrentTimeline()
: Timeline.EMPTY;
if (timeline.isEmpty()) {
lastPeriodUidWithTracks = null;
} else if (!player.getCurrentTracks().isEmpty()) {
} else if (player.isCommandAvailable(COMMAND_GET_TRACKS)
&& !player.getCurrentTracks().isEmpty()) {
lastPeriodUidWithTracks =
timeline.getPeriod(player.getCurrentPeriodIndex(), period, /* setIds= */ true).uid;
} else if (lastPeriodUidWithTracks != null) {

View File

@ -15,6 +15,9 @@
*/
package androidx.media3.ui;
import static androidx.media3.common.Player.COMMAND_GET_TRACKS;
import static androidx.media3.common.Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
@ -102,7 +105,9 @@ public final class TrackSelectionDialogBuilder {
Context context, CharSequence title, Player player, @C.TrackType int trackType) {
this.context = context;
this.title = title;
List<Tracks.Group> allTrackGroups = player.getCurrentTracks().getGroups();
Tracks tracks =
player.isCommandAvailable(COMMAND_GET_TRACKS) ? player.getCurrentTracks() : Tracks.EMPTY;
List<Tracks.Group> allTrackGroups = tracks.getGroups();
trackGroups = new ArrayList<>();
for (int i = 0; i < allTrackGroups.size(); i++) {
Tracks.Group trackGroup = allTrackGroups.get(i);
@ -113,6 +118,9 @@ public final class TrackSelectionDialogBuilder {
overrides = player.getTrackSelectionParameters().overrides;
callback =
(isDisabled, overrides) -> {
if (!player.isCommandAvailable(COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
return;
}
TrackSelectionParameters.Builder parametersBuilder =
player.getTrackSelectionParameters().buildUpon();
parametersBuilder.setTrackTypeDisabled(trackType, isDisabled);

View File

@ -34,7 +34,7 @@ import org.junit.runner.RunWith;
public class DefaultMediaDescriptionAdapterTest {
@Test
public void getters_returnMediaMetadataValues() {
public void getters_withGetMetatadataCommandAvailable_returnMediaMetadataValues() {
Context context = ApplicationProvider.getApplicationContext();
Player player = mock(Player.class);
MediaMetadata mediaMetadata =
@ -43,6 +43,7 @@ public class DefaultMediaDescriptionAdapterTest {
PendingIntent.getActivity(context, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE);
DefaultMediaDescriptionAdapter adapter = new DefaultMediaDescriptionAdapter(pendingIntent);
when(player.isCommandAvailable(Player.COMMAND_GET_MEDIA_ITEMS_METADATA)).thenReturn(true);
when(player.getMediaMetadata()).thenReturn(mediaMetadata);
assertThat(adapter.createCurrentContentIntent(player)).isEqualTo(pendingIntent);
@ -51,4 +52,22 @@ public class DefaultMediaDescriptionAdapterTest {
assertThat(adapter.getCurrentContentText(player).toString())
.isEqualTo(mediaMetadata.artist.toString());
}
@Test
public void getters_withoutGetMetatadataCommandAvailable_returnMediaMetadataValues() {
Context context = ApplicationProvider.getApplicationContext();
Player player = mock(Player.class);
MediaMetadata mediaMetadata =
new MediaMetadata.Builder().setDisplayTitle("display title").setArtist("artist").build();
PendingIntent pendingIntent =
PendingIntent.getActivity(context, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE);
DefaultMediaDescriptionAdapter adapter = new DefaultMediaDescriptionAdapter(pendingIntent);
when(player.isCommandAvailable(Player.COMMAND_GET_MEDIA_ITEMS_METADATA)).thenReturn(false);
when(player.getMediaMetadata()).thenReturn(mediaMetadata);
assertThat(adapter.createCurrentContentIntent(player)).isEqualTo(pendingIntent);
assertThat(adapter.getCurrentContentTitle(player).toString()).isEqualTo("");
assertThat(adapter.getCurrentContentText(player)).isNull();
}
}