diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapter.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapter.java index 629a8c06210..5b727efd9a4 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapter.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapter.java @@ -15,6 +15,8 @@ */ package com.google.android.exoplayer2.ui; +import static com.google.android.exoplayer2.Player.COMMAND_GET_MEDIA_ITEMS_METADATA; + import android.app.PendingIntent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -46,6 +48,9 @@ public DefaultMediaDescriptionAdapter(@Nullable PendingIntent pendingIntent) { @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; @@ -64,6 +69,9 @@ public PendingIntent createCurrentContentIntent(Player player) { @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; @@ -75,6 +83,9 @@ public CharSequence getCurrentContentText(Player player) { @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; diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java index a129954bc4a..6e0537d79fe 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java @@ -15,10 +15,17 @@ */ package com.google.android.exoplayer2.ui; +import static com.google.android.exoplayer2.Player.COMMAND_CHANGE_MEDIA_ITEMS; +import static com.google.android.exoplayer2.Player.COMMAND_GET_CURRENT_MEDIA_ITEM; +import static com.google.android.exoplayer2.Player.COMMAND_GET_TIMELINE; +import static com.google.android.exoplayer2.Player.COMMAND_PLAY_PAUSE; +import static com.google.android.exoplayer2.Player.COMMAND_PREPARE; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_BACK; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_FORWARD; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_DEFAULT_POSITION; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS; +import static com.google.android.exoplayer2.Player.COMMAND_STOP; import static com.google.android.exoplayer2.Player.EVENT_IS_PLAYING_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_MEDIA_METADATA_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_PLAYBACK_PARAMETERS_CHANGED; @@ -1203,7 +1210,9 @@ protected NotificationCompat.Builder createNotification( @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; } @@ -1257,6 +1266,7 @@ protected NotificationCompat.Builder createNotification( // 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() @@ -1535,24 +1545,43 @@ public void onReceive(Context context, Intent intent) { } 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 diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java index 55e9680b060..958c9618210 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java @@ -15,11 +15,22 @@ */ package com.google.android.exoplayer2.ui; +import static com.google.android.exoplayer2.Player.COMMAND_GET_CURRENT_MEDIA_ITEM; +import static com.google.android.exoplayer2.Player.COMMAND_GET_TIMELINE; +import static com.google.android.exoplayer2.Player.COMMAND_GET_TRACKS; +import static com.google.android.exoplayer2.Player.COMMAND_PLAY_PAUSE; +import static com.google.android.exoplayer2.Player.COMMAND_PREPARE; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_BACK; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_FORWARD; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_DEFAULT_POSITION; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_MEDIA_ITEM; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS; +import static com.google.android.exoplayer2.Player.COMMAND_SET_REPEAT_MODE; +import static com.google.android.exoplayer2.Player.COMMAND_SET_SHUFFLE_MODE; +import static com.google.android.exoplayer2.Player.COMMAND_SET_SPEED_AND_PITCH; +import static com.google.android.exoplayer2.Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS; import static com.google.android.exoplayer2.Player.EVENT_AVAILABLE_COMMANDS_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_IS_PLAYING_CHANGED; import static com.google.android.exoplayer2.Player.EVENT_PLAYBACK_PARAMETERS_CHANGED; @@ -35,6 +46,7 @@ import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Util.castNonNull; import static com.google.android.exoplayer2.util.Util.getDrawable; +import static com.google.android.exoplayer2.util.Util.msToUs; import android.annotation.SuppressLint; import android.content.Context; @@ -804,7 +816,7 @@ public void setShowTimeoutMs(int showTimeoutMs) { */ 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) { @@ -1068,7 +1080,7 @@ private void updateRepeatModeButton() { } @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); @@ -1102,7 +1114,7 @@ private void updateShuffleButton() { @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); @@ -1126,8 +1138,8 @@ private void initTrackSelectionAdapter() { 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(); @@ -1168,12 +1180,14 @@ private void updateTimeline() { 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; @@ -1215,6 +1229,11 @@ private void updateTimeline() { } 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) { @@ -1242,7 +1261,7 @@ private void updateProgress() { @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(); } @@ -1320,7 +1339,7 @@ private void displaySettingsWindow(RecyclerView.Adapter adapter, View anchorV } 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)); @@ -1341,11 +1360,12 @@ private void updateButton(boolean enabled, @Nullable View view) { } 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) { @@ -1358,17 +1378,13 @@ private void seekToTimeBarPosition(Player player, long positionMs) { 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; @@ -1446,10 +1462,12 @@ public boolean dispatchMediaKeyEvent(KeyEvent event) { } 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) { @@ -1464,10 +1482,14 @@ public boolean dispatchMediaKeyEvent(KeyEvent event) { 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; @@ -1507,7 +1529,10 @@ private void onLayoutChange( } 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() { @@ -1528,16 +1553,21 @@ private void dispatchPlayPause(Player player) { 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") @@ -1553,13 +1583,18 @@ private static boolean isHandledMediaKey(int keyCode) { } /** - * 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; } @@ -1680,22 +1715,33 @@ public void onClick(View view) { } 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); @@ -1898,7 +1944,8 @@ public void onBindViewHolderAtZeroPosition(SubSettingViewHolder holder) { 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( @@ -1939,7 +1986,8 @@ public void onBindViewHolderAtZeroPosition(SubSettingViewHolder holder) { 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 = @@ -2042,6 +2090,9 @@ public void onBindViewHolder(SubSettingViewHolder holder, int position) { 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( diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerView.java index 48e6821f525..5aaae64efe9 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerView.java @@ -15,7 +15,11 @@ */ package com.google.android.exoplayer2.ui; +import static com.google.android.exoplayer2.Player.COMMAND_GET_CURRENT_MEDIA_ITEM; +import static com.google.android.exoplayer2.Player.COMMAND_GET_MEDIA_ITEMS_METADATA; import static com.google.android.exoplayer2.Player.COMMAND_GET_TEXT; +import static com.google.android.exoplayer2.Player.COMMAND_GET_TIMELINE; +import static com.google.android.exoplayer2.Player.COMMAND_GET_TRACKS; import static com.google.android.exoplayer2.Player.COMMAND_SET_VIDEO_SURFACE; import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Util.getDrawable; @@ -529,10 +533,12 @@ public void setPlayer(@Nullable Player player) { @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) { @@ -735,7 +741,9 @@ public void setCustomErrorMessage(@Nullable CharSequence message) { @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); } @@ -1239,7 +1247,8 @@ private boolean shouldShowControllerIndefinitely() { } 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()); @@ -1254,12 +1263,17 @@ private void showController(boolean showIndefinitely) { } 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(); @@ -1283,7 +1297,7 @@ private void updateForCurrentTrackSelections(boolean isNewPlayer) { closeShutter(); // Display artwork if enabled and available, else hide it. if (useArtwork()) { - if (setArtworkFromMediaMetadata(player.getMediaMetadata())) { + if (setArtworkFromMediaMetadata(player)) { return; } if (setDrawableArtwork(defaultArtwork)) { @@ -1295,7 +1309,11 @@ private void updateForCurrentTrackSelections(boolean isNewPlayer) { } @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; } @@ -1514,10 +1532,14 @@ public void onTracksChanged(Tracks tracks) { // is necessary to avoid closing the shutter when such a transition occurs. See: // https://github.com/google/ExoPlayer/issues/5507. Player player = checkNotNull(StyledPlayerView.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) { diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/TrackSelectionDialogBuilder.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/TrackSelectionDialogBuilder.java index 29ca89d4198..e613b42d1ed 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/TrackSelectionDialogBuilder.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/TrackSelectionDialogBuilder.java @@ -15,6 +15,9 @@ */ package com.google.android.exoplayer2.ui; +import static com.google.android.exoplayer2.Player.COMMAND_GET_TRACKS; +import static com.google.android.exoplayer2.Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS; + import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; @@ -100,7 +103,9 @@ public TrackSelectionDialogBuilder( Context context, CharSequence title, Player player, @C.TrackType int trackType) { this.context = context; this.title = title; - List allTrackGroups = player.getCurrentTracks().getGroups(); + Tracks tracks = + player.isCommandAvailable(COMMAND_GET_TRACKS) ? player.getCurrentTracks() : Tracks.EMPTY; + List allTrackGroups = tracks.getGroups(); trackGroups = new ArrayList<>(); for (int i = 0; i < allTrackGroups.size(); i++) { Tracks.Group trackGroup = allTrackGroups.get(i); @@ -111,6 +116,9 @@ public 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); diff --git a/library/ui/src/test/java/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapterTest.java b/library/ui/src/test/java/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapterTest.java index 4ebe0f42e57..eb21c959f1c 100644 --- a/library/ui/src/test/java/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapterTest.java +++ b/library/ui/src/test/java/com/google/android/exoplayer2/ui/DefaultMediaDescriptionAdapterTest.java @@ -34,7 +34,7 @@ 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 void getters_returnMediaMetadataValues() { 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 void getters_returnMediaMetadataValues() { 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(); + } }