From e1c48515eb3a1cb7b345028d1d4ecb3758d739c0 Mon Sep 17 00:00:00 2001 From: bachinger Date: Wed, 5 Feb 2020 08:49:06 +0000 Subject: [PATCH] add next, previous, fastForward and rewind to ControlDispatcher Issue: #6926, #6934 PiperOrigin-RevId: 293315532 --- RELEASENOTES.md | 3 + .../mediasession/MediaSessionConnector.java | 72 +++------ .../mediasession/TimelineQueueNavigator.java | 28 +--- .../android/exoplayer2/ControlDispatcher.java | 38 +++++ .../exoplayer2/DefaultControlDispatcher.java | 131 ++++++++++++++++- .../exoplayer2/ui/PlayerControlView.java | 139 ++++++------------ .../ui/PlayerNotificationManager.java | 130 ++++------------ .../android/exoplayer2/ui/PlayerView.java | 21 ++- 8 files changed, 270 insertions(+), 292 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 7ee8eae82d..d781d5f5e4 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -39,6 +39,9 @@ * Testing * Upgrade Truth dependency from 0.44 to 1.0. * Upgrade to JUnit 4.13-rc-2. +* UI + * move logic of prev, next, fast forward and rewind to ControlDispatcher + [#6926](https://github.com/google/ExoPlayer/issues/6926)). ### 2.11.2 (TBD) ### diff --git a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java index b06db715e9..0853de4b61 100644 --- a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java +++ b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java @@ -127,11 +127,6 @@ public final class MediaSessionConnector { /** The default playback actions. */ @PlaybackActions public static final long DEFAULT_PLAYBACK_ACTIONS = ALL_PLAYBACK_ACTIONS; - /** The default fast forward increment, in milliseconds. */ - public static final int DEFAULT_FAST_FORWARD_MS = 15000; - /** The default rewind increment, in milliseconds. */ - public static final int DEFAULT_REWIND_MS = 5000; - /** * The name of the {@link PlaybackStateCompat} float extra with the value of {@link * PlaybackParameters#speed}. @@ -440,8 +435,6 @@ public final class MediaSessionConnector { @Nullable private MediaButtonEventHandler mediaButtonEventHandler; private long enabledPlaybackActions; - private int rewindMs; - private int fastForwardMs; /** * Creates an instance. @@ -461,8 +454,6 @@ public final class MediaSessionConnector { new DefaultMediaMetadataProvider( mediaSession.getController(), /* metadataExtrasPrefix= */ null); enabledPlaybackActions = DEFAULT_PLAYBACK_ACTIONS; - rewindMs = DEFAULT_REWIND_MS; - fastForwardMs = DEFAULT_FAST_FORWARD_MS; mediaSession.setFlags(BASE_MEDIA_SESSION_FLAGS); mediaSession.setCallback(componentListener, new Handler(looper)); } @@ -504,13 +495,12 @@ public final class MediaSessionConnector { /** * Sets the {@link ControlDispatcher}. * - * @param controlDispatcher The {@link ControlDispatcher}, or null to use {@link - * DefaultControlDispatcher}. + * @param controlDispatcher The {@link ControlDispatcher}. */ - public void setControlDispatcher(@Nullable ControlDispatcher controlDispatcher) { + public void setControlDispatcher(ControlDispatcher controlDispatcher) { if (this.controlDispatcher != controlDispatcher) { - this.controlDispatcher = - controlDispatcher == null ? new DefaultControlDispatcher() : controlDispatcher; + this.controlDispatcher = controlDispatcher; + invalidateMediaSessionPlaybackState(); } } @@ -551,27 +541,27 @@ public final class MediaSessionConnector { } /** - * Sets the rewind increment in milliseconds. - * - * @param rewindMs The rewind increment in milliseconds. A non-positive value will cause the - * rewind button to be disabled. + * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link + * DefaultControlDispatcher#DefaultControlDispatcher(long, long)} instead. */ + @SuppressWarnings("deprecation") + @Deprecated public void setRewindIncrementMs(int rewindMs) { - if (this.rewindMs != rewindMs) { - this.rewindMs = rewindMs; + if (controlDispatcher instanceof DefaultControlDispatcher) { + ((DefaultControlDispatcher) controlDispatcher).setRewindIncrementMs(rewindMs); invalidateMediaSessionPlaybackState(); } } /** - * Sets the fast forward increment in milliseconds. - * - * @param fastForwardMs The fast forward increment in milliseconds. A non-positive value will - * cause the fast forward button to be disabled. + * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link + * DefaultControlDispatcher#DefaultControlDispatcher(long, long)} instead. */ + @SuppressWarnings("deprecation") + @Deprecated public void setFastForwardIncrementMs(int fastForwardMs) { - if (this.fastForwardMs != fastForwardMs) { - this.fastForwardMs = fastForwardMs; + if (controlDispatcher instanceof DefaultControlDispatcher) { + ((DefaultControlDispatcher) controlDispatcher).setFastForwardIncrementMs(fastForwardMs); invalidateMediaSessionPlaybackState(); } } @@ -875,8 +865,8 @@ public final class MediaSessionConnector { Timeline timeline = player.getCurrentTimeline(); if (!timeline.isEmpty() && !player.isPlayingAd()) { enableSeeking = player.isCurrentWindowSeekable(); - enableRewind = enableSeeking && rewindMs > 0; - enableFastForward = enableSeeking && fastForwardMs > 0; + enableRewind = enableSeeking && controlDispatcher.isRewindEnabled(); + enableFastForward = enableSeeking && controlDispatcher.isFastForwardEnabled(); enableSetRating = ratingCallback != null; enableSetCaptioningEnabled = captionCallback != null && captionCallback.hasCaptions(player); } @@ -955,28 +945,6 @@ public final class MediaSessionConnector { return player != null && mediaButtonEventHandler != null; } - private void rewind(Player player) { - if (player.isCurrentWindowSeekable() && rewindMs > 0) { - seekToOffset(player, /* offsetMs= */ -rewindMs); - } - } - - private void fastForward(Player player) { - if (player.isCurrentWindowSeekable() && fastForwardMs > 0) { - seekToOffset(player, /* offsetMs= */ fastForwardMs); - } - } - - private void seekToOffset(Player player, long offsetMs) { - long positionMs = player.getCurrentPosition() + offsetMs; - long durationMs = player.getDuration(); - if (durationMs != C.TIME_UNSET) { - positionMs = Math.min(positionMs, durationMs); - } - positionMs = Math.max(positionMs, 0); - seekTo(player, player.getCurrentWindowIndex(), positionMs); - } - private void seekTo(Player player, int windowIndex, long positionMs) { controlDispatcher.dispatchSeekTo(player, windowIndex, positionMs); } @@ -1203,14 +1171,14 @@ public final class MediaSessionConnector { @Override public void onFastForward() { if (canDispatchPlaybackAction(PlaybackStateCompat.ACTION_FAST_FORWARD)) { - fastForward(player); + controlDispatcher.dispatchFastForward(player); } } @Override public void onRewind() { if (canDispatchPlaybackAction(PlaybackStateCompat.ACTION_REWIND)) { - rewind(player); + controlDispatcher.dispatchRewind(player); } } diff --git a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.java b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.java index f9d0eca353..024faea209 100644 --- a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.java +++ b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.java @@ -36,7 +36,6 @@ import java.util.Collections; */ public abstract class TimelineQueueNavigator implements MediaSessionConnector.QueueNavigator { - public static final long MAX_POSITION_FOR_SEEK_TO_PREVIOUS = 3000; public static final int DEFAULT_MAX_QUEUE_SIZE = 10; private final MediaSessionCompat mediaSession; @@ -136,20 +135,7 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu @Override public void onSkipToPrevious(Player player, ControlDispatcher controlDispatcher) { - Timeline timeline = player.getCurrentTimeline(); - if (timeline.isEmpty() || player.isPlayingAd()) { - return; - } - int windowIndex = player.getCurrentWindowIndex(); - timeline.getWindow(windowIndex, window); - int previousWindowIndex = player.getPreviousWindowIndex(); - if (previousWindowIndex != C.INDEX_UNSET - && (player.getCurrentPosition() <= MAX_POSITION_FOR_SEEK_TO_PREVIOUS - || (window.isDynamic && !window.isSeekable))) { - controlDispatcher.dispatchSeekTo(player, previousWindowIndex, C.TIME_UNSET); - } else { - controlDispatcher.dispatchSeekTo(player, windowIndex, 0); - } + controlDispatcher.dispatchPrevious(player); } @Override @@ -166,17 +152,7 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu @Override public void onSkipToNext(Player player, ControlDispatcher controlDispatcher) { - Timeline timeline = player.getCurrentTimeline(); - if (timeline.isEmpty() || player.isPlayingAd()) { - return; - } - int windowIndex = player.getCurrentWindowIndex(); - int nextWindowIndex = player.getNextWindowIndex(); - if (nextWindowIndex != C.INDEX_UNSET) { - controlDispatcher.dispatchSeekTo(player, nextWindowIndex, C.TIME_UNSET); - } else if (timeline.getWindow(windowIndex, window).isDynamic) { - controlDispatcher.dispatchSeekTo(player, windowIndex, C.TIME_UNSET); - } + controlDispatcher.dispatchNext(player); } // CommandReceiver implementation. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ControlDispatcher.java b/library/core/src/main/java/com/google/android/exoplayer2/ControlDispatcher.java index f8749fc1a8..7b78147e12 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ControlDispatcher.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ControlDispatcher.java @@ -46,6 +46,38 @@ public interface ControlDispatcher { */ boolean dispatchSeekTo(Player player, int windowIndex, long positionMs); + /** + * Dispatches a {@link Player#previous()} operation. + * + * @param player The {@link Player} to which the operation should be dispatched. + * @return True if the operation was dispatched. False if suppressed. + */ + boolean dispatchPrevious(Player player); + + /** + * Dispatches a {@link Player#next()} operation. + * + * @param player The {@link Player} to which the operation should be dispatched. + * @return True if the operation was dispatched. False if suppressed. + */ + boolean dispatchNext(Player player); + + /** + * Dispatches a rewind operation. + * + * @param player The {@link Player} to which the operation should be dispatched. + * @return True if the operation was dispatched. False if suppressed. + */ + boolean dispatchRewind(Player player); + + /** + * Dispatches a fast forward operation. + * + * @param player The {@link Player} to which the operation should be dispatched. + * @return True if the operation was dispatched. False if suppressed. + */ + boolean dispatchFastForward(Player player); + /** * Dispatches a {@link Player#setRepeatMode(int)} operation. * @@ -72,4 +104,10 @@ public interface ControlDispatcher { * @return True if the operation was dispatched. False if suppressed. */ boolean dispatchStop(Player player, boolean reset); + + /** Returns {@code true} if rewind is enabled, {@code false} otherwise. */ + boolean isRewindEnabled(); + + /** Returns {@code true} if fast forward is enabled, {@code false} otherwise. */ + boolean isFastForwardEnabled(); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/DefaultControlDispatcher.java b/library/core/src/main/java/com/google/android/exoplayer2/DefaultControlDispatcher.java index df3ef36b88..4d812d2d9a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/DefaultControlDispatcher.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/DefaultControlDispatcher.java @@ -15,14 +15,40 @@ */ package com.google.android.exoplayer2; -import com.google.android.exoplayer2.Player.RepeatMode; - -/** - * Default {@link ControlDispatcher} that dispatches all operations to the player without - * modification. - */ +/** Default {@link ControlDispatcher}. */ public class DefaultControlDispatcher implements ControlDispatcher { + /** The default fast forward increment, in milliseconds. */ + public static final int DEFAULT_FAST_FORWARD_MS = 15000; + /** The default rewind increment, in milliseconds. */ + public static final int DEFAULT_REWIND_MS = 5000; + + private static final int MAX_POSITION_FOR_SEEK_TO_PREVIOUS = 3000; + + private final Timeline.Window window; + + private long rewindIncrementMs; + private long fastForwardIncrementMs; + + /** Creates an instance. */ + public DefaultControlDispatcher() { + this(DEFAULT_FAST_FORWARD_MS, DEFAULT_REWIND_MS); + } + + /** + * Creates an instance with the given increments. + * + * @param fastForwardIncrementMs The fast forward increment in milliseconds. A non-positive value + * disables the fast forward operation. + * @param rewindIncrementMs The rewind increment in milliseconds. A non-positive value disables + * the rewind operation. + */ + public DefaultControlDispatcher(long fastForwardIncrementMs, long rewindIncrementMs) { + this.fastForwardIncrementMs = fastForwardIncrementMs; + this.rewindIncrementMs = rewindIncrementMs; + window = new Timeline.Window(); + } + @Override public boolean dispatchSetPlayWhenReady(Player player, boolean playWhenReady) { player.setPlayWhenReady(playWhenReady); @@ -36,7 +62,58 @@ public class DefaultControlDispatcher implements ControlDispatcher { } @Override - public boolean dispatchSetRepeatMode(Player player, @RepeatMode int repeatMode) { + public boolean dispatchPrevious(Player player) { + Timeline timeline = player.getCurrentTimeline(); + if (timeline.isEmpty() || player.isPlayingAd()) { + return true; + } + int windowIndex = player.getCurrentWindowIndex(); + timeline.getWindow(windowIndex, window); + int previousWindowIndex = player.getPreviousWindowIndex(); + if (previousWindowIndex != C.INDEX_UNSET + && (player.getCurrentPosition() <= MAX_POSITION_FOR_SEEK_TO_PREVIOUS + || (window.isDynamic && !window.isSeekable))) { + player.seekTo(previousWindowIndex, C.TIME_UNSET); + } else { + player.seekTo(windowIndex, /* positionMs= */ 0); + } + return true; + } + + @Override + public boolean dispatchNext(Player player) { + Timeline timeline = player.getCurrentTimeline(); + if (timeline.isEmpty() || player.isPlayingAd()) { + return true; + } + int windowIndex = player.getCurrentWindowIndex(); + int nextWindowIndex = player.getNextWindowIndex(); + if (nextWindowIndex != C.INDEX_UNSET) { + player.seekTo(nextWindowIndex, C.TIME_UNSET); + } else if (timeline.getWindow(windowIndex, window).isLive) { + player.seekTo(windowIndex, C.TIME_UNSET); + } + return true; + } + + @Override + public boolean dispatchRewind(Player player) { + if (isRewindEnabled() && player.isCurrentWindowSeekable()) { + seekToOffset(player, -rewindIncrementMs); + } + return true; + } + + @Override + public boolean dispatchFastForward(Player player) { + if (isFastForwardEnabled() && player.isCurrentWindowSeekable()) { + seekToOffset(player, fastForwardIncrementMs); + } + return true; + } + + @Override + public boolean dispatchSetRepeatMode(Player player, @Player.RepeatMode int repeatMode) { player.setRepeatMode(repeatMode); return true; } @@ -52,4 +129,44 @@ public class DefaultControlDispatcher implements ControlDispatcher { player.stop(reset); return true; } + + @Override + public boolean isRewindEnabled() { + return rewindIncrementMs > 0; + } + + @Override + public boolean isFastForwardEnabled() { + return fastForwardIncrementMs > 0; + } + + /** + * @deprecated Create a new instance instead and pass the new instance to the UI component. This + * makes sure the UI gets updated and is in sync with the new values. + */ + @Deprecated + public void setRewindIncrementMs(long rewindMs) { + this.rewindIncrementMs = rewindMs; + } + + /** + * @deprecated Create a new instance instead and pass the new instance to the UI component. This + * makes sure the UI gets updated and is in sync with the new values. + */ + @Deprecated + public void setFastForwardIncrementMs(long fastForwardMs) { + this.fastForwardIncrementMs = fastForwardMs; + } + + // Internal methods. + + private static void seekToOffset(Player player, long offsetMs) { + long positionMs = player.getCurrentPosition() + offsetMs; + long durationMs = player.getDuration(); + if (durationMs != C.TIME_UNSET) { + positionMs = Math.min(positionMs, durationMs); + } + positionMs = Math.max(positionMs, 0); + player.seekTo(player.getCurrentWindowIndex(), positionMs); + } } diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java index bfb4e018f0..c7ecfdbf86 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java @@ -33,6 +33,8 @@ import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.ControlDispatcher; +import com.google.android.exoplayer2.DefaultControlDispatcher; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.PlaybackPreparer; import com.google.android.exoplayer2.Player; @@ -67,13 +69,13 @@ import java.util.concurrent.CopyOnWriteArrayList; *
  • {@code rewind_increment} - The duration of the rewind applied when the user taps the * rewind button, in milliseconds. Use zero to disable the rewind button. * *
  • {@code fastforward_increment} - Like {@code rewind_increment}, but for fast forward. * *
  • {@code repeat_toggle_modes} - A flagged enumeration value specifying which repeat * mode toggle options are enabled. Valid values are: {@code none}, {@code one}, {@code all}, @@ -246,10 +248,6 @@ public class PlayerControlView extends FrameLayout { void onProgressUpdate(long position, long bufferedPosition); } - /** The default fast forward increment, in milliseconds. */ - public static final int DEFAULT_FAST_FORWARD_MS = 15000; - /** The default rewind increment, in milliseconds. */ - public static final int DEFAULT_REWIND_MS = 5000; /** The default show timeout, in milliseconds. */ public static final int DEFAULT_SHOW_TIMEOUT_MS = 5000; /** The default repeat toggle modes. */ @@ -260,7 +258,6 @@ public class PlayerControlView extends FrameLayout { /** The maximum number of windows that can be shown in a multi-window time bar. */ public static final int MAX_WINDOWS_FOR_MULTI_WINDOW_TIME_BAR = 100; - private static final long MAX_POSITION_FOR_SEEK_TO_PREVIOUS = 3000; /** The maximum interval between time bar position updates. */ private static final int MAX_UPDATE_INTERVAL_MS = 1000; @@ -307,8 +304,6 @@ public class PlayerControlView extends FrameLayout { private boolean showMultiWindowTimeBar; private boolean multiWindowTimeBar; private boolean scrubbing; - private int rewindMs; - private int fastForwardMs; private int showTimeoutMs; private int timeBarMinUpdateIntervalMs; private @RepeatModeUtil.RepeatToggleModes int repeatToggleModes; @@ -344,13 +339,13 @@ public class PlayerControlView extends FrameLayout { @Nullable AttributeSet playbackAttrs) { super(context, attrs, defStyleAttr); int controllerLayoutId = R.layout.exo_player_control_view; - rewindMs = DEFAULT_REWIND_MS; - fastForwardMs = DEFAULT_FAST_FORWARD_MS; showTimeoutMs = DEFAULT_SHOW_TIMEOUT_MS; repeatToggleModes = DEFAULT_REPEAT_TOGGLE_MODES; timeBarMinUpdateIntervalMs = DEFAULT_TIME_BAR_MIN_UPDATE_INTERVAL_MS; hideAtMs = C.TIME_UNSET; showShuffleButton = false; + int rewindMs = DefaultControlDispatcher.DEFAULT_REWIND_MS; + int fastForwardMs = DefaultControlDispatcher.DEFAULT_FAST_FORWARD_MS; if (playbackAttrs != null) { TypedArray a = context @@ -384,7 +379,8 @@ public class PlayerControlView extends FrameLayout { extraAdGroupTimesMs = new long[0]; extraPlayedAdGroups = new boolean[0]; componentListener = new ComponentListener(); - controlDispatcher = new com.google.android.exoplayer2.DefaultControlDispatcher(); + controlDispatcher = + new com.google.android.exoplayer2.DefaultControlDispatcher(fastForwardMs, rewindMs); updateProgressAction = this::updateProgress; hideAction = this::hide; @@ -589,37 +585,39 @@ public class PlayerControlView extends FrameLayout { /** * Sets the {@link com.google.android.exoplayer2.ControlDispatcher}. * - * @param controlDispatcher The {@link com.google.android.exoplayer2.ControlDispatcher}, or null - * to use {@link com.google.android.exoplayer2.DefaultControlDispatcher}. + * @param controlDispatcher The {@link com.google.android.exoplayer2.ControlDispatcher}. */ - public void setControlDispatcher( - @Nullable com.google.android.exoplayer2.ControlDispatcher controlDispatcher) { - this.controlDispatcher = - controlDispatcher == null - ? new com.google.android.exoplayer2.DefaultControlDispatcher() - : controlDispatcher; + public void setControlDispatcher(ControlDispatcher controlDispatcher) { + if (this.controlDispatcher != controlDispatcher) { + this.controlDispatcher = controlDispatcher; + updateNavigation(); + } } /** - * Sets the rewind increment in milliseconds. - * - * @param rewindMs The rewind increment in milliseconds. A non-positive value will cause the - * rewind button to be disabled. + * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link + * DefaultControlDispatcher#DefaultControlDispatcher(long, long)}. */ + @SuppressWarnings("deprecation") + @Deprecated public void setRewindIncrementMs(int rewindMs) { - this.rewindMs = rewindMs; - updateNavigation(); + if (controlDispatcher instanceof DefaultControlDispatcher) { + ((DefaultControlDispatcher) controlDispatcher).setRewindIncrementMs(rewindMs); + updateNavigation(); + } } /** - * Sets the fast forward increment in milliseconds. - * - * @param fastForwardMs The fast forward increment in milliseconds. A non-positive value will - * cause the fast forward button to be disabled. + * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link + * DefaultControlDispatcher#DefaultControlDispatcher(long, long)}. */ + @SuppressWarnings("deprecation") + @Deprecated public void setFastForwardIncrementMs(int fastForwardMs) { - this.fastForwardMs = fastForwardMs; - updateNavigation(); + if (controlDispatcher instanceof DefaultControlDispatcher) { + ((DefaultControlDispatcher) controlDispatcher).setFastForwardIncrementMs(fastForwardMs); + updateNavigation(); + } } /** @@ -830,8 +828,8 @@ public class PlayerControlView extends FrameLayout { boolean isSeekable = window.isSeekable; enableSeeking = isSeekable; enablePrevious = isSeekable || !window.isDynamic || player.hasPrevious(); - enableRewind = isSeekable && rewindMs > 0; - enableFastForward = isSeekable && fastForwardMs > 0; + enableRewind = isSeekable && controlDispatcher.isRewindEnabled(); + enableFastForward = isSeekable && controlDispatcher.isFastForwardEnabled(); enableNext = window.isDynamic || player.hasNext(); } } @@ -1042,59 +1040,6 @@ public class PlayerControlView extends FrameLayout { view.setVisibility(VISIBLE); } - private void previous(Player player) { - Timeline timeline = player.getCurrentTimeline(); - if (timeline.isEmpty() || player.isPlayingAd()) { - return; - } - int windowIndex = player.getCurrentWindowIndex(); - timeline.getWindow(windowIndex, window); - int previousWindowIndex = player.getPreviousWindowIndex(); - if (previousWindowIndex != C.INDEX_UNSET - && (player.getCurrentPosition() <= MAX_POSITION_FOR_SEEK_TO_PREVIOUS - || (window.isDynamic && !window.isSeekable))) { - seekTo(player, previousWindowIndex, C.TIME_UNSET); - } else { - seekTo(player, windowIndex, /* positionMs= */ 0); - } - } - - private void next(Player player) { - Timeline timeline = player.getCurrentTimeline(); - if (timeline.isEmpty() || player.isPlayingAd()) { - return; - } - int windowIndex = player.getCurrentWindowIndex(); - int nextWindowIndex = player.getNextWindowIndex(); - if (nextWindowIndex != C.INDEX_UNSET) { - seekTo(player, nextWindowIndex, C.TIME_UNSET); - } else if (timeline.getWindow(windowIndex, window).isDynamic) { - seekTo(player, windowIndex, C.TIME_UNSET); - } - } - - private void rewind(Player player) { - if (player.isCurrentWindowSeekable() && rewindMs > 0) { - seekToOffset(player, -rewindMs); - } - } - - private void fastForward(Player player) { - if (player.isCurrentWindowSeekable() && fastForwardMs > 0) { - seekToOffset(player, fastForwardMs); - } - } - - private void seekToOffset(Player player, long offsetMs) { - long positionMs = player.getCurrentPosition() + offsetMs; - long durationMs = player.getDuration(); - if (durationMs != C.TIME_UNSET) { - positionMs = Math.min(positionMs, durationMs); - } - positionMs = Math.max(positionMs, 0); - seekTo(player, player.getCurrentWindowIndex(), positionMs); - } - private void seekToTimeBarPosition(Player player, long positionMs) { int windowIndex; Timeline timeline = player.getCurrentTimeline(); @@ -1183,9 +1128,9 @@ public class PlayerControlView extends FrameLayout { } if (event.getAction() == KeyEvent.ACTION_DOWN) { if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) { - fastForward(player); + controlDispatcher.dispatchFastForward(player); } else if (keyCode == KeyEvent.KEYCODE_MEDIA_REWIND) { - rewind(player); + controlDispatcher.dispatchRewind(player); } else if (event.getRepeatCount() == 0) { switch (keyCode) { case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: @@ -1198,10 +1143,10 @@ public class PlayerControlView extends FrameLayout { controlDispatcher.dispatchSetPlayWhenReady(player, false); break; case KeyEvent.KEYCODE_MEDIA_NEXT: - next(player); + controlDispatcher.dispatchNext(player); break; case KeyEvent.KEYCODE_MEDIA_PREVIOUS: - previous(player); + controlDispatcher.dispatchPrevious(player); break; default: break; @@ -1317,13 +1262,13 @@ public class PlayerControlView extends FrameLayout { return; } if (nextButton == view) { - next(player); + controlDispatcher.dispatchNext(player); } else if (previousButton == view) { - previous(player); + controlDispatcher.dispatchPrevious(player); } else if (fastForwardButton == view) { - fastForward(player); + controlDispatcher.dispatchFastForward(player); } else if (rewindButton == view) { - rewind(player); + controlDispatcher.dispatchRewind(player); } else if (playButton == view) { if (player.getPlaybackState() == Player.STATE_IDLE) { if (playbackPreparer != 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 c9fb3c4efa..42fcd50c58 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 @@ -94,14 +94,14 @@ import java.util.Map; *
  • {@code rewindIncrementMs} - Sets the rewind increment. If set to zero the rewind * action is not displayed. * *
  • {@code fastForwardIncrementMs} - Sets the fast forward increment. If set to zero the * fast forward action is not displayed. * * * @@ -354,13 +354,6 @@ public class PlayerNotificationManager { }) public @interface Priority {} - /** The default fast forward increment, in milliseconds. */ - public static final int DEFAULT_FAST_FORWARD_MS = 15000; - /** The default rewind increment, in milliseconds. */ - public static final int DEFAULT_REWIND_MS = 5000; - - private static final long MAX_POSITION_FOR_SEEK_TO_PREVIOUS = 3000; - private static int instanceIdCounter; private final Context context; @@ -392,8 +385,6 @@ public class PlayerNotificationManager { private boolean useNavigationActionsInCompactView; private boolean usePlayPauseActions; private boolean useStopAction; - private long fastForwardMs; - private long rewindMs; private int badgeIconType; private boolean colorized; private int defaults; @@ -634,8 +625,6 @@ public class PlayerNotificationManager { smallIconResourceId = R.drawable.exo_notification_small_icon; defaults = 0; priority = NotificationCompat.PRIORITY_LOW; - fastForwardMs = DEFAULT_FAST_FORWARD_MS; - rewindMs = DEFAULT_REWIND_MS; badgeIconType = NotificationCompat.BADGE_ICON_SMALL; visibility = NotificationCompat.VISIBILITY_PUBLIC; @@ -701,12 +690,13 @@ public class PlayerNotificationManager { /** * Sets the {@link ControlDispatcher}. * - * @param controlDispatcher The {@link ControlDispatcher}, or null to use {@link - * DefaultControlDispatcher}. + * @param controlDispatcher The {@link ControlDispatcher}. */ public final void setControlDispatcher(ControlDispatcher controlDispatcher) { - this.controlDispatcher = - controlDispatcher != null ? controlDispatcher : new DefaultControlDispatcher(); + if (this.controlDispatcher != controlDispatcher) { + this.controlDispatcher = controlDispatcher; + invalidate(); + } } /** @@ -725,31 +715,29 @@ public class PlayerNotificationManager { } /** - * Sets the fast forward increment in milliseconds. - * - * @param fastForwardMs The fast forward increment in milliseconds. A value of zero will cause the - * fast forward action to be disabled. + * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link + * DefaultControlDispatcher#DefaultControlDispatcher(long, long)}. */ + @SuppressWarnings("deprecation") + @Deprecated public final void setFastForwardIncrementMs(long fastForwardMs) { - if (this.fastForwardMs == fastForwardMs) { - return; + if (controlDispatcher instanceof DefaultControlDispatcher) { + ((DefaultControlDispatcher) controlDispatcher).setFastForwardIncrementMs(fastForwardMs); + invalidate(); } - this.fastForwardMs = fastForwardMs; - invalidate(); } /** - * Sets the rewind increment in milliseconds. - * - * @param rewindMs The rewind increment in milliseconds. A value of zero will cause the rewind - * action to be disabled. + * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link + * DefaultControlDispatcher#DefaultControlDispatcher(long, long)}. */ + @SuppressWarnings("deprecation") + @Deprecated public final void setRewindIncrementMs(long rewindMs) { - if (this.rewindMs == rewindMs) { - return; + if (controlDispatcher instanceof DefaultControlDispatcher) { + ((DefaultControlDispatcher) controlDispatcher).setRewindIncrementMs(rewindMs); + invalidate(); } - this.rewindMs = rewindMs; - invalidate(); } /** @@ -1047,6 +1035,7 @@ public class PlayerNotificationManager { List actions = new ArrayList<>(actionNames.size()); for (int i = 0; i < actionNames.size(); i++) { String actionName = actionNames.get(i); + @Nullable NotificationCompat.Action action = playbackActions.containsKey(actionName) ? playbackActions.get(actionName) @@ -1146,8 +1135,8 @@ public class PlayerNotificationManager { if (!timeline.isEmpty() && !player.isPlayingAd()) { timeline.getWindow(player.getCurrentWindowIndex(), window); enablePrevious = window.isSeekable || !window.isDynamic || player.hasPrevious(); - enableRewind = rewindMs > 0; - enableFastForward = fastForwardMs > 0; + enableRewind = controlDispatcher.isRewindEnabled(); + enableFastForward = controlDispatcher.isFastForwardEnabled(); enableNext = window.isDynamic || player.hasNext(); } @@ -1222,63 +1211,6 @@ public class PlayerNotificationManager { && player.getPlayWhenReady(); } - private void previous(Player player) { - Timeline timeline = player.getCurrentTimeline(); - if (timeline.isEmpty() || player.isPlayingAd()) { - return; - } - int windowIndex = player.getCurrentWindowIndex(); - timeline.getWindow(windowIndex, window); - int previousWindowIndex = player.getPreviousWindowIndex(); - if (previousWindowIndex != C.INDEX_UNSET - && (player.getCurrentPosition() <= MAX_POSITION_FOR_SEEK_TO_PREVIOUS - || (window.isDynamic && !window.isSeekable))) { - seekTo(player, previousWindowIndex, C.TIME_UNSET); - } else { - seekTo(player, windowIndex, /* positionMs= */ 0); - } - } - - private void next(Player player) { - Timeline timeline = player.getCurrentTimeline(); - if (timeline.isEmpty() || player.isPlayingAd()) { - return; - } - int windowIndex = player.getCurrentWindowIndex(); - int nextWindowIndex = player.getNextWindowIndex(); - if (nextWindowIndex != C.INDEX_UNSET) { - seekTo(player, nextWindowIndex, C.TIME_UNSET); - } else if (timeline.getWindow(windowIndex, window).isDynamic) { - seekTo(player, windowIndex, C.TIME_UNSET); - } - } - - private void rewind(Player player) { - if (player.isCurrentWindowSeekable() && rewindMs > 0) { - seekToOffset(player, /* offsetMs= */ -rewindMs); - } - } - - private void fastForward(Player player) { - if (player.isCurrentWindowSeekable() && fastForwardMs > 0) { - seekToOffset(player, /* offsetMs= */ fastForwardMs); - } - } - - private void seekToOffset(Player player, long offsetMs) { - long positionMs = player.getCurrentPosition() + offsetMs; - long durationMs = player.getDuration(); - if (durationMs != C.TIME_UNSET) { - positionMs = Math.min(positionMs, durationMs); - } - positionMs = Math.max(positionMs, 0); - seekTo(player, player.getCurrentWindowIndex(), positionMs); - } - - private void seekTo(Player player, int windowIndex, long positionMs) { - controlDispatcher.dispatchSeekTo(player, windowIndex, positionMs); - } - private boolean shouldShowPauseButton(Player player) { return player.getPlaybackState() != Player.STATE_ENDED && player.getPlaybackState() != Player.STATE_IDLE @@ -1438,19 +1370,19 @@ public class PlayerNotificationManager { playbackPreparer.preparePlayback(); } } else if (player.getPlaybackState() == Player.STATE_ENDED) { - seekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET); + controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET); } controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ true); } else if (ACTION_PAUSE.equals(action)) { controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ false); } else if (ACTION_PREVIOUS.equals(action)) { - previous(player); + controlDispatcher.dispatchPrevious(player); } else if (ACTION_REWIND.equals(action)) { - rewind(player); + controlDispatcher.dispatchRewind(player); } else if (ACTION_FAST_FORWARD.equals(action)) { - fastForward(player); + controlDispatcher.dispatchFastForward(player); } else if (ACTION_NEXT.equals(action)) { - next(player); + controlDispatcher.dispatchNext(player); } else if (ACTION_STOP.equals(action)) { controlDispatcher.dispatchStop(player, /* reset= */ true); } else if (ACTION_DISMISS.equals(action)) { diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java index 13545fb9fb..8ae9492441 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java @@ -965,31 +965,30 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider /** * Sets the {@link ControlDispatcher}. * - * @param controlDispatcher The {@link ControlDispatcher}, or null to use {@link - * DefaultControlDispatcher}. + * @param controlDispatcher The {@link ControlDispatcher}. */ - public void setControlDispatcher(@Nullable ControlDispatcher controlDispatcher) { + public void setControlDispatcher(ControlDispatcher controlDispatcher) { Assertions.checkStateNotNull(controller); controller.setControlDispatcher(controlDispatcher); } /** - * Sets the rewind increment in milliseconds. - * - * @param rewindMs The rewind increment in milliseconds. A non-positive value will cause the - * rewind button to be disabled. + * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link + * DefaultControlDispatcher#DefaultControlDispatcher(long, long)}. */ + @SuppressWarnings("deprecation") + @Deprecated public void setRewindIncrementMs(int rewindMs) { Assertions.checkStateNotNull(controller); controller.setRewindIncrementMs(rewindMs); } /** - * Sets the fast forward increment in milliseconds. - * - * @param fastForwardMs The fast forward increment in milliseconds. A non-positive value will - * cause the fast forward button to be disabled. + * @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link + * DefaultControlDispatcher#DefaultControlDispatcher(long, long)}. */ + @SuppressWarnings("deprecation") + @Deprecated public void setFastForwardIncrementMs(int fastForwardMs) { Assertions.checkStateNotNull(controller); controller.setFastForwardIncrementMs(fastForwardMs);