mirror of
https://github.com/androidx/media.git
synced 2025-05-16 20:19:57 +08:00
add next, previous, fastForward and rewind to ControlDispatcher
Issue: #6926, #6934 PiperOrigin-RevId: 293315532
This commit is contained in:
parent
0f6bf1525d
commit
e1c48515eb
@ -39,6 +39,9 @@
|
|||||||
* Testing
|
* Testing
|
||||||
* Upgrade Truth dependency from 0.44 to 1.0.
|
* Upgrade Truth dependency from 0.44 to 1.0.
|
||||||
* Upgrade to JUnit 4.13-rc-2.
|
* 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) ###
|
### 2.11.2 (TBD) ###
|
||||||
|
|
||||||
|
@ -127,11 +127,6 @@ public final class MediaSessionConnector {
|
|||||||
/** The default playback actions. */
|
/** The default playback actions. */
|
||||||
@PlaybackActions public static final long DEFAULT_PLAYBACK_ACTIONS = ALL_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
|
* The name of the {@link PlaybackStateCompat} float extra with the value of {@link
|
||||||
* PlaybackParameters#speed}.
|
* PlaybackParameters#speed}.
|
||||||
@ -440,8 +435,6 @@ public final class MediaSessionConnector {
|
|||||||
@Nullable private MediaButtonEventHandler mediaButtonEventHandler;
|
@Nullable private MediaButtonEventHandler mediaButtonEventHandler;
|
||||||
|
|
||||||
private long enabledPlaybackActions;
|
private long enabledPlaybackActions;
|
||||||
private int rewindMs;
|
|
||||||
private int fastForwardMs;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance.
|
* Creates an instance.
|
||||||
@ -461,8 +454,6 @@ public final class MediaSessionConnector {
|
|||||||
new DefaultMediaMetadataProvider(
|
new DefaultMediaMetadataProvider(
|
||||||
mediaSession.getController(), /* metadataExtrasPrefix= */ null);
|
mediaSession.getController(), /* metadataExtrasPrefix= */ null);
|
||||||
enabledPlaybackActions = DEFAULT_PLAYBACK_ACTIONS;
|
enabledPlaybackActions = DEFAULT_PLAYBACK_ACTIONS;
|
||||||
rewindMs = DEFAULT_REWIND_MS;
|
|
||||||
fastForwardMs = DEFAULT_FAST_FORWARD_MS;
|
|
||||||
mediaSession.setFlags(BASE_MEDIA_SESSION_FLAGS);
|
mediaSession.setFlags(BASE_MEDIA_SESSION_FLAGS);
|
||||||
mediaSession.setCallback(componentListener, new Handler(looper));
|
mediaSession.setCallback(componentListener, new Handler(looper));
|
||||||
}
|
}
|
||||||
@ -504,13 +495,12 @@ public final class MediaSessionConnector {
|
|||||||
/**
|
/**
|
||||||
* Sets the {@link ControlDispatcher}.
|
* Sets the {@link ControlDispatcher}.
|
||||||
*
|
*
|
||||||
* @param controlDispatcher The {@link ControlDispatcher}, or null to use {@link
|
* @param controlDispatcher The {@link ControlDispatcher}.
|
||||||
* DefaultControlDispatcher}.
|
|
||||||
*/
|
*/
|
||||||
public void setControlDispatcher(@Nullable ControlDispatcher controlDispatcher) {
|
public void setControlDispatcher(ControlDispatcher controlDispatcher) {
|
||||||
if (this.controlDispatcher != controlDispatcher) {
|
if (this.controlDispatcher != controlDispatcher) {
|
||||||
this.controlDispatcher =
|
this.controlDispatcher = controlDispatcher;
|
||||||
controlDispatcher == null ? new DefaultControlDispatcher() : controlDispatcher;
|
invalidateMediaSessionPlaybackState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,27 +541,27 @@ public final class MediaSessionConnector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the rewind increment in milliseconds.
|
* @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link
|
||||||
*
|
* DefaultControlDispatcher#DefaultControlDispatcher(long, long)} instead.
|
||||||
* @param rewindMs The rewind increment in milliseconds. A non-positive value will cause the
|
|
||||||
* rewind button to be disabled.
|
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Deprecated
|
||||||
public void setRewindIncrementMs(int rewindMs) {
|
public void setRewindIncrementMs(int rewindMs) {
|
||||||
if (this.rewindMs != rewindMs) {
|
if (controlDispatcher instanceof DefaultControlDispatcher) {
|
||||||
this.rewindMs = rewindMs;
|
((DefaultControlDispatcher) controlDispatcher).setRewindIncrementMs(rewindMs);
|
||||||
invalidateMediaSessionPlaybackState();
|
invalidateMediaSessionPlaybackState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the fast forward increment in milliseconds.
|
* @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link
|
||||||
*
|
* DefaultControlDispatcher#DefaultControlDispatcher(long, long)} instead.
|
||||||
* @param fastForwardMs The fast forward increment in milliseconds. A non-positive value will
|
|
||||||
* cause the fast forward button to be disabled.
|
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Deprecated
|
||||||
public void setFastForwardIncrementMs(int fastForwardMs) {
|
public void setFastForwardIncrementMs(int fastForwardMs) {
|
||||||
if (this.fastForwardMs != fastForwardMs) {
|
if (controlDispatcher instanceof DefaultControlDispatcher) {
|
||||||
this.fastForwardMs = fastForwardMs;
|
((DefaultControlDispatcher) controlDispatcher).setFastForwardIncrementMs(fastForwardMs);
|
||||||
invalidateMediaSessionPlaybackState();
|
invalidateMediaSessionPlaybackState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -875,8 +865,8 @@ public final class MediaSessionConnector {
|
|||||||
Timeline timeline = player.getCurrentTimeline();
|
Timeline timeline = player.getCurrentTimeline();
|
||||||
if (!timeline.isEmpty() && !player.isPlayingAd()) {
|
if (!timeline.isEmpty() && !player.isPlayingAd()) {
|
||||||
enableSeeking = player.isCurrentWindowSeekable();
|
enableSeeking = player.isCurrentWindowSeekable();
|
||||||
enableRewind = enableSeeking && rewindMs > 0;
|
enableRewind = enableSeeking && controlDispatcher.isRewindEnabled();
|
||||||
enableFastForward = enableSeeking && fastForwardMs > 0;
|
enableFastForward = enableSeeking && controlDispatcher.isFastForwardEnabled();
|
||||||
enableSetRating = ratingCallback != null;
|
enableSetRating = ratingCallback != null;
|
||||||
enableSetCaptioningEnabled = captionCallback != null && captionCallback.hasCaptions(player);
|
enableSetCaptioningEnabled = captionCallback != null && captionCallback.hasCaptions(player);
|
||||||
}
|
}
|
||||||
@ -955,28 +945,6 @@ public final class MediaSessionConnector {
|
|||||||
return player != null && mediaButtonEventHandler != null;
|
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) {
|
private void seekTo(Player player, int windowIndex, long positionMs) {
|
||||||
controlDispatcher.dispatchSeekTo(player, windowIndex, positionMs);
|
controlDispatcher.dispatchSeekTo(player, windowIndex, positionMs);
|
||||||
}
|
}
|
||||||
@ -1203,14 +1171,14 @@ public final class MediaSessionConnector {
|
|||||||
@Override
|
@Override
|
||||||
public void onFastForward() {
|
public void onFastForward() {
|
||||||
if (canDispatchPlaybackAction(PlaybackStateCompat.ACTION_FAST_FORWARD)) {
|
if (canDispatchPlaybackAction(PlaybackStateCompat.ACTION_FAST_FORWARD)) {
|
||||||
fastForward(player);
|
controlDispatcher.dispatchFastForward(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRewind() {
|
public void onRewind() {
|
||||||
if (canDispatchPlaybackAction(PlaybackStateCompat.ACTION_REWIND)) {
|
if (canDispatchPlaybackAction(PlaybackStateCompat.ACTION_REWIND)) {
|
||||||
rewind(player);
|
controlDispatcher.dispatchRewind(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ import java.util.Collections;
|
|||||||
*/
|
*/
|
||||||
public abstract class TimelineQueueNavigator implements MediaSessionConnector.QueueNavigator {
|
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;
|
public static final int DEFAULT_MAX_QUEUE_SIZE = 10;
|
||||||
|
|
||||||
private final MediaSessionCompat mediaSession;
|
private final MediaSessionCompat mediaSession;
|
||||||
@ -136,20 +135,7 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSkipToPrevious(Player player, ControlDispatcher controlDispatcher) {
|
public void onSkipToPrevious(Player player, ControlDispatcher controlDispatcher) {
|
||||||
Timeline timeline = player.getCurrentTimeline();
|
controlDispatcher.dispatchPrevious(player);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -166,17 +152,7 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSkipToNext(Player player, ControlDispatcher controlDispatcher) {
|
public void onSkipToNext(Player player, ControlDispatcher controlDispatcher) {
|
||||||
Timeline timeline = player.getCurrentTimeline();
|
controlDispatcher.dispatchNext(player);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommandReceiver implementation.
|
// CommandReceiver implementation.
|
||||||
|
@ -46,6 +46,38 @@ public interface ControlDispatcher {
|
|||||||
*/
|
*/
|
||||||
boolean dispatchSeekTo(Player player, int windowIndex, long positionMs);
|
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.
|
* Dispatches a {@link Player#setRepeatMode(int)} operation.
|
||||||
*
|
*
|
||||||
@ -72,4 +104,10 @@ public interface ControlDispatcher {
|
|||||||
* @return True if the operation was dispatched. False if suppressed.
|
* @return True if the operation was dispatched. False if suppressed.
|
||||||
*/
|
*/
|
||||||
boolean dispatchStop(Player player, boolean reset);
|
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();
|
||||||
}
|
}
|
||||||
|
@ -15,14 +15,40 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2;
|
package com.google.android.exoplayer2;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.Player.RepeatMode;
|
/** Default {@link ControlDispatcher}. */
|
||||||
|
|
||||||
/**
|
|
||||||
* Default {@link ControlDispatcher} that dispatches all operations to the player without
|
|
||||||
* modification.
|
|
||||||
*/
|
|
||||||
public class DefaultControlDispatcher implements 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
|
@Override
|
||||||
public boolean dispatchSetPlayWhenReady(Player player, boolean playWhenReady) {
|
public boolean dispatchSetPlayWhenReady(Player player, boolean playWhenReady) {
|
||||||
player.setPlayWhenReady(playWhenReady);
|
player.setPlayWhenReady(playWhenReady);
|
||||||
@ -36,7 +62,58 @@ public class DefaultControlDispatcher implements ControlDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
player.setRepeatMode(repeatMode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -52,4 +129,44 @@ public class DefaultControlDispatcher implements ControlDispatcher {
|
|||||||
player.stop(reset);
|
player.stop(reset);
|
||||||
return true;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,8 @@ import android.widget.ImageView;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
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.ExoPlayerLibraryInfo;
|
||||||
import com.google.android.exoplayer2.PlaybackPreparer;
|
import com.google.android.exoplayer2.PlaybackPreparer;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
@ -67,13 +69,13 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||||||
* <li><b>{@code rewind_increment}</b> - The duration of the rewind applied when the user taps the
|
* <li><b>{@code rewind_increment}</b> - The duration of the rewind applied when the user taps the
|
||||||
* rewind button, in milliseconds. Use zero to disable the rewind button.
|
* rewind button, in milliseconds. Use zero to disable the rewind button.
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Corresponding method: {@link #setRewindIncrementMs(int)}
|
* <li>Corresponding method: {@link #setControlDispatcher(ControlDispatcher)}
|
||||||
* <li>Default: {@link #DEFAULT_REWIND_MS}
|
* <li>Default: {@link DefaultControlDispatcher#DEFAULT_REWIND_MS}
|
||||||
* </ul>
|
* </ul>
|
||||||
* <li><b>{@code fastforward_increment}</b> - Like {@code rewind_increment}, but for fast forward.
|
* <li><b>{@code fastforward_increment}</b> - Like {@code rewind_increment}, but for fast forward.
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Corresponding method: {@link #setFastForwardIncrementMs(int)}
|
* <li>Corresponding method: {@link #setControlDispatcher(ControlDispatcher)}
|
||||||
* <li>Default: {@link #DEFAULT_FAST_FORWARD_MS}
|
* <li>Default: {@link DefaultControlDispatcher#DEFAULT_FAST_FORWARD_MS}
|
||||||
* </ul>
|
* </ul>
|
||||||
* <li><b>{@code repeat_toggle_modes}</b> - A flagged enumeration value specifying which repeat
|
* <li><b>{@code repeat_toggle_modes}</b> - A flagged enumeration value specifying which repeat
|
||||||
* mode toggle options are enabled. Valid values are: {@code none}, {@code one}, {@code all},
|
* 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);
|
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. */
|
/** The default show timeout, in milliseconds. */
|
||||||
public static final int DEFAULT_SHOW_TIMEOUT_MS = 5000;
|
public static final int DEFAULT_SHOW_TIMEOUT_MS = 5000;
|
||||||
/** The default repeat toggle modes. */
|
/** 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. */
|
/** 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;
|
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. */
|
/** The maximum interval between time bar position updates. */
|
||||||
private static final int MAX_UPDATE_INTERVAL_MS = 1000;
|
private static final int MAX_UPDATE_INTERVAL_MS = 1000;
|
||||||
|
|
||||||
@ -307,8 +304,6 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
private boolean showMultiWindowTimeBar;
|
private boolean showMultiWindowTimeBar;
|
||||||
private boolean multiWindowTimeBar;
|
private boolean multiWindowTimeBar;
|
||||||
private boolean scrubbing;
|
private boolean scrubbing;
|
||||||
private int rewindMs;
|
|
||||||
private int fastForwardMs;
|
|
||||||
private int showTimeoutMs;
|
private int showTimeoutMs;
|
||||||
private int timeBarMinUpdateIntervalMs;
|
private int timeBarMinUpdateIntervalMs;
|
||||||
private @RepeatModeUtil.RepeatToggleModes int repeatToggleModes;
|
private @RepeatModeUtil.RepeatToggleModes int repeatToggleModes;
|
||||||
@ -344,13 +339,13 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
@Nullable AttributeSet playbackAttrs) {
|
@Nullable AttributeSet playbackAttrs) {
|
||||||
super(context, attrs, defStyleAttr);
|
super(context, attrs, defStyleAttr);
|
||||||
int controllerLayoutId = R.layout.exo_player_control_view;
|
int controllerLayoutId = R.layout.exo_player_control_view;
|
||||||
rewindMs = DEFAULT_REWIND_MS;
|
|
||||||
fastForwardMs = DEFAULT_FAST_FORWARD_MS;
|
|
||||||
showTimeoutMs = DEFAULT_SHOW_TIMEOUT_MS;
|
showTimeoutMs = DEFAULT_SHOW_TIMEOUT_MS;
|
||||||
repeatToggleModes = DEFAULT_REPEAT_TOGGLE_MODES;
|
repeatToggleModes = DEFAULT_REPEAT_TOGGLE_MODES;
|
||||||
timeBarMinUpdateIntervalMs = DEFAULT_TIME_BAR_MIN_UPDATE_INTERVAL_MS;
|
timeBarMinUpdateIntervalMs = DEFAULT_TIME_BAR_MIN_UPDATE_INTERVAL_MS;
|
||||||
hideAtMs = C.TIME_UNSET;
|
hideAtMs = C.TIME_UNSET;
|
||||||
showShuffleButton = false;
|
showShuffleButton = false;
|
||||||
|
int rewindMs = DefaultControlDispatcher.DEFAULT_REWIND_MS;
|
||||||
|
int fastForwardMs = DefaultControlDispatcher.DEFAULT_FAST_FORWARD_MS;
|
||||||
if (playbackAttrs != null) {
|
if (playbackAttrs != null) {
|
||||||
TypedArray a =
|
TypedArray a =
|
||||||
context
|
context
|
||||||
@ -384,7 +379,8 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
extraAdGroupTimesMs = new long[0];
|
extraAdGroupTimesMs = new long[0];
|
||||||
extraPlayedAdGroups = new boolean[0];
|
extraPlayedAdGroups = new boolean[0];
|
||||||
componentListener = new ComponentListener();
|
componentListener = new ComponentListener();
|
||||||
controlDispatcher = new com.google.android.exoplayer2.DefaultControlDispatcher();
|
controlDispatcher =
|
||||||
|
new com.google.android.exoplayer2.DefaultControlDispatcher(fastForwardMs, rewindMs);
|
||||||
updateProgressAction = this::updateProgress;
|
updateProgressAction = this::updateProgress;
|
||||||
hideAction = this::hide;
|
hideAction = this::hide;
|
||||||
|
|
||||||
@ -589,37 +585,39 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
/**
|
/**
|
||||||
* Sets the {@link com.google.android.exoplayer2.ControlDispatcher}.
|
* Sets the {@link com.google.android.exoplayer2.ControlDispatcher}.
|
||||||
*
|
*
|
||||||
* @param controlDispatcher The {@link com.google.android.exoplayer2.ControlDispatcher}, or null
|
* @param controlDispatcher The {@link com.google.android.exoplayer2.ControlDispatcher}.
|
||||||
* to use {@link com.google.android.exoplayer2.DefaultControlDispatcher}.
|
|
||||||
*/
|
*/
|
||||||
public void setControlDispatcher(
|
public void setControlDispatcher(ControlDispatcher controlDispatcher) {
|
||||||
@Nullable com.google.android.exoplayer2.ControlDispatcher controlDispatcher) {
|
if (this.controlDispatcher != controlDispatcher) {
|
||||||
this.controlDispatcher =
|
this.controlDispatcher = controlDispatcher;
|
||||||
controlDispatcher == null
|
updateNavigation();
|
||||||
? new com.google.android.exoplayer2.DefaultControlDispatcher()
|
}
|
||||||
: controlDispatcher;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the rewind increment in milliseconds.
|
* @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link
|
||||||
*
|
* DefaultControlDispatcher#DefaultControlDispatcher(long, long)}.
|
||||||
* @param rewindMs The rewind increment in milliseconds. A non-positive value will cause the
|
|
||||||
* rewind button to be disabled.
|
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Deprecated
|
||||||
public void setRewindIncrementMs(int rewindMs) {
|
public void setRewindIncrementMs(int rewindMs) {
|
||||||
this.rewindMs = rewindMs;
|
if (controlDispatcher instanceof DefaultControlDispatcher) {
|
||||||
updateNavigation();
|
((DefaultControlDispatcher) controlDispatcher).setRewindIncrementMs(rewindMs);
|
||||||
|
updateNavigation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the fast forward increment in milliseconds.
|
* @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link
|
||||||
*
|
* DefaultControlDispatcher#DefaultControlDispatcher(long, long)}.
|
||||||
* @param fastForwardMs The fast forward increment in milliseconds. A non-positive value will
|
|
||||||
* cause the fast forward button to be disabled.
|
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Deprecated
|
||||||
public void setFastForwardIncrementMs(int fastForwardMs) {
|
public void setFastForwardIncrementMs(int fastForwardMs) {
|
||||||
this.fastForwardMs = fastForwardMs;
|
if (controlDispatcher instanceof DefaultControlDispatcher) {
|
||||||
updateNavigation();
|
((DefaultControlDispatcher) controlDispatcher).setFastForwardIncrementMs(fastForwardMs);
|
||||||
|
updateNavigation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -830,8 +828,8 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
boolean isSeekable = window.isSeekable;
|
boolean isSeekable = window.isSeekable;
|
||||||
enableSeeking = isSeekable;
|
enableSeeking = isSeekable;
|
||||||
enablePrevious = isSeekable || !window.isDynamic || player.hasPrevious();
|
enablePrevious = isSeekable || !window.isDynamic || player.hasPrevious();
|
||||||
enableRewind = isSeekable && rewindMs > 0;
|
enableRewind = isSeekable && controlDispatcher.isRewindEnabled();
|
||||||
enableFastForward = isSeekable && fastForwardMs > 0;
|
enableFastForward = isSeekable && controlDispatcher.isFastForwardEnabled();
|
||||||
enableNext = window.isDynamic || player.hasNext();
|
enableNext = window.isDynamic || player.hasNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1042,59 +1040,6 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
view.setVisibility(VISIBLE);
|
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) {
|
private void seekToTimeBarPosition(Player player, long positionMs) {
|
||||||
int windowIndex;
|
int windowIndex;
|
||||||
Timeline timeline = player.getCurrentTimeline();
|
Timeline timeline = player.getCurrentTimeline();
|
||||||
@ -1183,9 +1128,9 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||||
if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
|
if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
|
||||||
fastForward(player);
|
controlDispatcher.dispatchFastForward(player);
|
||||||
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_REWIND) {
|
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_REWIND) {
|
||||||
rewind(player);
|
controlDispatcher.dispatchRewind(player);
|
||||||
} else if (event.getRepeatCount() == 0) {
|
} else if (event.getRepeatCount() == 0) {
|
||||||
switch (keyCode) {
|
switch (keyCode) {
|
||||||
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||||
@ -1198,10 +1143,10 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
controlDispatcher.dispatchSetPlayWhenReady(player, false);
|
controlDispatcher.dispatchSetPlayWhenReady(player, false);
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||||
next(player);
|
controlDispatcher.dispatchNext(player);
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||||||
previous(player);
|
controlDispatcher.dispatchPrevious(player);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -1317,13 +1262,13 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (nextButton == view) {
|
if (nextButton == view) {
|
||||||
next(player);
|
controlDispatcher.dispatchNext(player);
|
||||||
} else if (previousButton == view) {
|
} else if (previousButton == view) {
|
||||||
previous(player);
|
controlDispatcher.dispatchPrevious(player);
|
||||||
} else if (fastForwardButton == view) {
|
} else if (fastForwardButton == view) {
|
||||||
fastForward(player);
|
controlDispatcher.dispatchFastForward(player);
|
||||||
} else if (rewindButton == view) {
|
} else if (rewindButton == view) {
|
||||||
rewind(player);
|
controlDispatcher.dispatchRewind(player);
|
||||||
} else if (playButton == view) {
|
} else if (playButton == view) {
|
||||||
if (player.getPlaybackState() == Player.STATE_IDLE) {
|
if (player.getPlaybackState() == Player.STATE_IDLE) {
|
||||||
if (playbackPreparer != null) {
|
if (playbackPreparer != null) {
|
||||||
|
@ -94,14 +94,14 @@ import java.util.Map;
|
|||||||
* <li><b>{@code rewindIncrementMs}</b> - Sets the rewind increment. If set to zero the rewind
|
* <li><b>{@code rewindIncrementMs}</b> - Sets the rewind increment. If set to zero the rewind
|
||||||
* action is not displayed.
|
* action is not displayed.
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Corresponding setter: {@link #setRewindIncrementMs(long)}
|
* <li>Corresponding setter: {@link #setControlDispatcher(ControlDispatcher)}
|
||||||
* <li>Default: {@link #DEFAULT_REWIND_MS} (5000)
|
* <li>Default: {@link DefaultControlDispatcher#DEFAULT_REWIND_MS} (5000)
|
||||||
* </ul>
|
* </ul>
|
||||||
* <li><b>{@code fastForwardIncrementMs}</b> - Sets the fast forward increment. If set to zero the
|
* <li><b>{@code fastForwardIncrementMs}</b> - Sets the fast forward increment. If set to zero the
|
||||||
* fast forward action is not displayed.
|
* fast forward action is not displayed.
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Corresponding setter: {@link #setFastForwardIncrementMs(long)}
|
* <li>Corresponding setter: {@link #setControlDispatcher(ControlDispatcher)}
|
||||||
* <li>Default: {@link #DEFAULT_FAST_FORWARD_MS} (15000)
|
* <li>Default: {@link DefaultControlDispatcher#DEFAULT_FAST_FORWARD_MS} (15000)
|
||||||
* </ul>
|
* </ul>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
@ -354,13 +354,6 @@ public class PlayerNotificationManager {
|
|||||||
})
|
})
|
||||||
public @interface Priority {}
|
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 static int instanceIdCounter;
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
@ -392,8 +385,6 @@ public class PlayerNotificationManager {
|
|||||||
private boolean useNavigationActionsInCompactView;
|
private boolean useNavigationActionsInCompactView;
|
||||||
private boolean usePlayPauseActions;
|
private boolean usePlayPauseActions;
|
||||||
private boolean useStopAction;
|
private boolean useStopAction;
|
||||||
private long fastForwardMs;
|
|
||||||
private long rewindMs;
|
|
||||||
private int badgeIconType;
|
private int badgeIconType;
|
||||||
private boolean colorized;
|
private boolean colorized;
|
||||||
private int defaults;
|
private int defaults;
|
||||||
@ -634,8 +625,6 @@ public class PlayerNotificationManager {
|
|||||||
smallIconResourceId = R.drawable.exo_notification_small_icon;
|
smallIconResourceId = R.drawable.exo_notification_small_icon;
|
||||||
defaults = 0;
|
defaults = 0;
|
||||||
priority = NotificationCompat.PRIORITY_LOW;
|
priority = NotificationCompat.PRIORITY_LOW;
|
||||||
fastForwardMs = DEFAULT_FAST_FORWARD_MS;
|
|
||||||
rewindMs = DEFAULT_REWIND_MS;
|
|
||||||
badgeIconType = NotificationCompat.BADGE_ICON_SMALL;
|
badgeIconType = NotificationCompat.BADGE_ICON_SMALL;
|
||||||
visibility = NotificationCompat.VISIBILITY_PUBLIC;
|
visibility = NotificationCompat.VISIBILITY_PUBLIC;
|
||||||
|
|
||||||
@ -701,12 +690,13 @@ public class PlayerNotificationManager {
|
|||||||
/**
|
/**
|
||||||
* Sets the {@link ControlDispatcher}.
|
* Sets the {@link ControlDispatcher}.
|
||||||
*
|
*
|
||||||
* @param controlDispatcher The {@link ControlDispatcher}, or null to use {@link
|
* @param controlDispatcher The {@link ControlDispatcher}.
|
||||||
* DefaultControlDispatcher}.
|
|
||||||
*/
|
*/
|
||||||
public final void setControlDispatcher(ControlDispatcher controlDispatcher) {
|
public final void setControlDispatcher(ControlDispatcher controlDispatcher) {
|
||||||
this.controlDispatcher =
|
if (this.controlDispatcher != controlDispatcher) {
|
||||||
controlDispatcher != null ? controlDispatcher : new DefaultControlDispatcher();
|
this.controlDispatcher = controlDispatcher;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -725,31 +715,29 @@ public class PlayerNotificationManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the fast forward increment in milliseconds.
|
* @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link
|
||||||
*
|
* DefaultControlDispatcher#DefaultControlDispatcher(long, long)}.
|
||||||
* @param fastForwardMs The fast forward increment in milliseconds. A value of zero will cause the
|
|
||||||
* fast forward action to be disabled.
|
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Deprecated
|
||||||
public final void setFastForwardIncrementMs(long fastForwardMs) {
|
public final void setFastForwardIncrementMs(long fastForwardMs) {
|
||||||
if (this.fastForwardMs == fastForwardMs) {
|
if (controlDispatcher instanceof DefaultControlDispatcher) {
|
||||||
return;
|
((DefaultControlDispatcher) controlDispatcher).setFastForwardIncrementMs(fastForwardMs);
|
||||||
|
invalidate();
|
||||||
}
|
}
|
||||||
this.fastForwardMs = fastForwardMs;
|
|
||||||
invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the rewind increment in milliseconds.
|
* @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link
|
||||||
*
|
* DefaultControlDispatcher#DefaultControlDispatcher(long, long)}.
|
||||||
* @param rewindMs The rewind increment in milliseconds. A value of zero will cause the rewind
|
|
||||||
* action to be disabled.
|
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Deprecated
|
||||||
public final void setRewindIncrementMs(long rewindMs) {
|
public final void setRewindIncrementMs(long rewindMs) {
|
||||||
if (this.rewindMs == rewindMs) {
|
if (controlDispatcher instanceof DefaultControlDispatcher) {
|
||||||
return;
|
((DefaultControlDispatcher) controlDispatcher).setRewindIncrementMs(rewindMs);
|
||||||
|
invalidate();
|
||||||
}
|
}
|
||||||
this.rewindMs = rewindMs;
|
|
||||||
invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1047,6 +1035,7 @@ public class PlayerNotificationManager {
|
|||||||
List<NotificationCompat.Action> actions = new ArrayList<>(actionNames.size());
|
List<NotificationCompat.Action> actions = new ArrayList<>(actionNames.size());
|
||||||
for (int i = 0; i < actionNames.size(); i++) {
|
for (int i = 0; i < actionNames.size(); i++) {
|
||||||
String actionName = actionNames.get(i);
|
String actionName = actionNames.get(i);
|
||||||
|
@Nullable
|
||||||
NotificationCompat.Action action =
|
NotificationCompat.Action action =
|
||||||
playbackActions.containsKey(actionName)
|
playbackActions.containsKey(actionName)
|
||||||
? playbackActions.get(actionName)
|
? playbackActions.get(actionName)
|
||||||
@ -1146,8 +1135,8 @@ public class PlayerNotificationManager {
|
|||||||
if (!timeline.isEmpty() && !player.isPlayingAd()) {
|
if (!timeline.isEmpty() && !player.isPlayingAd()) {
|
||||||
timeline.getWindow(player.getCurrentWindowIndex(), window);
|
timeline.getWindow(player.getCurrentWindowIndex(), window);
|
||||||
enablePrevious = window.isSeekable || !window.isDynamic || player.hasPrevious();
|
enablePrevious = window.isSeekable || !window.isDynamic || player.hasPrevious();
|
||||||
enableRewind = rewindMs > 0;
|
enableRewind = controlDispatcher.isRewindEnabled();
|
||||||
enableFastForward = fastForwardMs > 0;
|
enableFastForward = controlDispatcher.isFastForwardEnabled();
|
||||||
enableNext = window.isDynamic || player.hasNext();
|
enableNext = window.isDynamic || player.hasNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1222,63 +1211,6 @@ public class PlayerNotificationManager {
|
|||||||
&& player.getPlayWhenReady();
|
&& 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) {
|
private boolean shouldShowPauseButton(Player player) {
|
||||||
return player.getPlaybackState() != Player.STATE_ENDED
|
return player.getPlaybackState() != Player.STATE_ENDED
|
||||||
&& player.getPlaybackState() != Player.STATE_IDLE
|
&& player.getPlaybackState() != Player.STATE_IDLE
|
||||||
@ -1438,19 +1370,19 @@ public class PlayerNotificationManager {
|
|||||||
playbackPreparer.preparePlayback();
|
playbackPreparer.preparePlayback();
|
||||||
}
|
}
|
||||||
} else if (player.getPlaybackState() == Player.STATE_ENDED) {
|
} 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);
|
controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ true);
|
||||||
} else if (ACTION_PAUSE.equals(action)) {
|
} else if (ACTION_PAUSE.equals(action)) {
|
||||||
controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ false);
|
controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ false);
|
||||||
} else if (ACTION_PREVIOUS.equals(action)) {
|
} else if (ACTION_PREVIOUS.equals(action)) {
|
||||||
previous(player);
|
controlDispatcher.dispatchPrevious(player);
|
||||||
} else if (ACTION_REWIND.equals(action)) {
|
} else if (ACTION_REWIND.equals(action)) {
|
||||||
rewind(player);
|
controlDispatcher.dispatchRewind(player);
|
||||||
} else if (ACTION_FAST_FORWARD.equals(action)) {
|
} else if (ACTION_FAST_FORWARD.equals(action)) {
|
||||||
fastForward(player);
|
controlDispatcher.dispatchFastForward(player);
|
||||||
} else if (ACTION_NEXT.equals(action)) {
|
} else if (ACTION_NEXT.equals(action)) {
|
||||||
next(player);
|
controlDispatcher.dispatchNext(player);
|
||||||
} else if (ACTION_STOP.equals(action)) {
|
} else if (ACTION_STOP.equals(action)) {
|
||||||
controlDispatcher.dispatchStop(player, /* reset= */ true);
|
controlDispatcher.dispatchStop(player, /* reset= */ true);
|
||||||
} else if (ACTION_DISMISS.equals(action)) {
|
} else if (ACTION_DISMISS.equals(action)) {
|
||||||
|
@ -965,31 +965,30 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
|
|||||||
/**
|
/**
|
||||||
* Sets the {@link ControlDispatcher}.
|
* Sets the {@link ControlDispatcher}.
|
||||||
*
|
*
|
||||||
* @param controlDispatcher The {@link ControlDispatcher}, or null to use {@link
|
* @param controlDispatcher The {@link ControlDispatcher}.
|
||||||
* DefaultControlDispatcher}.
|
|
||||||
*/
|
*/
|
||||||
public void setControlDispatcher(@Nullable ControlDispatcher controlDispatcher) {
|
public void setControlDispatcher(ControlDispatcher controlDispatcher) {
|
||||||
Assertions.checkStateNotNull(controller);
|
Assertions.checkStateNotNull(controller);
|
||||||
controller.setControlDispatcher(controlDispatcher);
|
controller.setControlDispatcher(controlDispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the rewind increment in milliseconds.
|
* @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link
|
||||||
*
|
* DefaultControlDispatcher#DefaultControlDispatcher(long, long)}.
|
||||||
* @param rewindMs The rewind increment in milliseconds. A non-positive value will cause the
|
|
||||||
* rewind button to be disabled.
|
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Deprecated
|
||||||
public void setRewindIncrementMs(int rewindMs) {
|
public void setRewindIncrementMs(int rewindMs) {
|
||||||
Assertions.checkStateNotNull(controller);
|
Assertions.checkStateNotNull(controller);
|
||||||
controller.setRewindIncrementMs(rewindMs);
|
controller.setRewindIncrementMs(rewindMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the fast forward increment in milliseconds.
|
* @deprecated Use {@link #setControlDispatcher(ControlDispatcher)} with {@link
|
||||||
*
|
* DefaultControlDispatcher#DefaultControlDispatcher(long, long)}.
|
||||||
* @param fastForwardMs The fast forward increment in milliseconds. A non-positive value will
|
|
||||||
* cause the fast forward button to be disabled.
|
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Deprecated
|
||||||
public void setFastForwardIncrementMs(int fastForwardMs) {
|
public void setFastForwardIncrementMs(int fastForwardMs) {
|
||||||
Assertions.checkStateNotNull(controller);
|
Assertions.checkStateNotNull(controller);
|
||||||
controller.setFastForwardIncrementMs(fastForwardMs);
|
controller.setFastForwardIncrementMs(fastForwardMs);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user