mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
allow apps to set custom metadata
[] ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=201350930
This commit is contained in:
parent
4f2b596062
commit
62ee13b11d
2 changed files with 273 additions and 213 deletions
|
|
@ -29,6 +29,8 @@
|
||||||
([#4023](https://github.com/google/ExoPlayer/issues/4023)).
|
([#4023](https://github.com/google/ExoPlayer/issues/4023)).
|
||||||
* Add support for mu-law and A-law PCM with the ffmpeg extension
|
* Add support for mu-law and A-law PCM with the ffmpeg extension
|
||||||
([#4360](https://github.com/google/ExoPlayer/issues/4360)).
|
([#4360](https://github.com/google/ExoPlayer/issues/4360)).
|
||||||
|
* MediaSession extension:
|
||||||
|
* Allow apps to set custom metadata with a MediaMetadataProvider.
|
||||||
* Add `PlayerView.isControllerVisible`
|
* Add `PlayerView.isControllerVisible`
|
||||||
([#4385](https://github.com/google/ExoPlayer/issues/4385)).
|
([#4385](https://github.com/google/ExoPlayer/issues/4385)).
|
||||||
* Expose all internal ID3 data stored in MP4 udta boxes, and switch from using
|
* Expose all internal ID3 data stored in MP4 udta boxes, and switch from using
|
||||||
|
|
|
||||||
|
|
@ -46,25 +46,26 @@ import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connects a {@link MediaSessionCompat} to a {@link Player}.
|
* Connects a {@link MediaSessionCompat} to a {@link Player}.
|
||||||
* <p>
|
*
|
||||||
* The connector listens for actions sent by the media session's controller and implements these
|
* <p>The connector listens for actions sent by the media session's controller and implements these
|
||||||
* actions by calling appropriate player methods. The playback state of the media session is
|
* actions by calling appropriate player methods. The playback state of the media session is
|
||||||
* automatically synced with the player. The connector can also be optionally extended by providing
|
* automatically synced with the player. The connector can also be optionally extended by providing
|
||||||
* various collaborators:
|
* various collaborators:
|
||||||
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Actions to initiate media playback ({@code PlaybackStateCompat#ACTION_PREPARE_*} and
|
* <li>Actions to initiate media playback ({@code PlaybackStateCompat#ACTION_PREPARE_*} and {@code
|
||||||
* {@code PlaybackStateCompat#ACTION_PLAY_*}) can be handled by a {@link PlaybackPreparer} passed
|
* PlaybackStateCompat#ACTION_PLAY_*}) can be handled by a {@link PlaybackPreparer} passed
|
||||||
* when calling {@link #setPlayer(Player, PlaybackPreparer, CustomActionProvider...)}. Custom
|
* when calling {@link #setPlayer(Player, PlaybackPreparer, CustomActionProvider...)}. Custom
|
||||||
* actions can be handled by passing one or more {@link CustomActionProvider}s in a similar way.
|
* actions can be handled by passing one or more {@link CustomActionProvider}s in a similar
|
||||||
* </li>
|
* way.
|
||||||
* <li>To enable a media queue and navigation within it, you can set a {@link QueueNavigator} by
|
* <li>To enable a media queue and navigation within it, you can set a {@link QueueNavigator} by
|
||||||
* calling {@link #setQueueNavigator(QueueNavigator)}. Use of {@link TimelineQueueNavigator} is
|
* calling {@link #setQueueNavigator(QueueNavigator)}. Use of {@link TimelineQueueNavigator}
|
||||||
* recommended for most use cases.</li>
|
* is recommended for most use cases.
|
||||||
* <li>To enable editing of the media queue, you can set a {@link QueueEditor} by calling
|
* <li>To enable editing of the media queue, you can set a {@link QueueEditor} by calling {@link
|
||||||
* {@link #setQueueEditor(QueueEditor)}.</li>
|
* #setQueueEditor(QueueEditor)}.
|
||||||
* <li>An {@link ErrorMessageProvider} for providing human readable error messages and
|
* <li>An {@link ErrorMessageProvider} for providing human readable error messages and
|
||||||
* corresponding error codes can be set by calling
|
* corresponding error codes can be set by calling {@link
|
||||||
* {@link #setErrorMessageProvider(ErrorMessageProvider)}.</li>
|
* #setErrorMessageProvider(ErrorMessageProvider)}.
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public final class MediaSessionConnector {
|
public final class MediaSessionConnector {
|
||||||
|
|
@ -74,35 +75,30 @@ public final class MediaSessionConnector {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default repeat toggle modes which is the bitmask of
|
* The default repeat toggle modes which is the bitmask of {@link
|
||||||
* {@link RepeatModeUtil#REPEAT_TOGGLE_MODE_ONE} and
|
* RepeatModeUtil#REPEAT_TOGGLE_MODE_ONE} and {@link RepeatModeUtil#REPEAT_TOGGLE_MODE_ALL}.
|
||||||
* {@link RepeatModeUtil#REPEAT_TOGGLE_MODE_ALL}.
|
|
||||||
*/
|
*/
|
||||||
public static final @RepeatModeUtil.RepeatToggleModes int DEFAULT_REPEAT_TOGGLE_MODES =
|
public static final @RepeatModeUtil.RepeatToggleModes int DEFAULT_REPEAT_TOGGLE_MODES =
|
||||||
RepeatModeUtil.REPEAT_TOGGLE_MODE_ONE | RepeatModeUtil.REPEAT_TOGGLE_MODE_ALL;
|
RepeatModeUtil.REPEAT_TOGGLE_MODE_ONE | RepeatModeUtil.REPEAT_TOGGLE_MODE_ALL;
|
||||||
public static final String EXTRAS_PITCH = "EXO_PITCH";
|
|
||||||
private static final int BASE_MEDIA_SESSION_FLAGS = MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
|
|
||||||
| MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS;
|
|
||||||
private static final int EDITOR_MEDIA_SESSION_FLAGS = BASE_MEDIA_SESSION_FLAGS
|
|
||||||
| MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS;
|
|
||||||
|
|
||||||
/**
|
public static final String EXTRAS_PITCH = "EXO_PITCH";
|
||||||
* Receiver of media commands sent by a media controller.
|
private static final int BASE_MEDIA_SESSION_FLAGS =
|
||||||
*/
|
MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
|
||||||
|
| MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS;
|
||||||
|
private static final int EDITOR_MEDIA_SESSION_FLAGS =
|
||||||
|
BASE_MEDIA_SESSION_FLAGS | MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS;
|
||||||
|
|
||||||
|
/** Receiver of media commands sent by a media controller. */
|
||||||
public interface CommandReceiver {
|
public interface CommandReceiver {
|
||||||
/**
|
/**
|
||||||
* Returns the commands the receiver handles, or {@code null} if no commands need to be handled.
|
* Returns the commands the receiver handles, or {@code null} if no commands need to be handled.
|
||||||
*/
|
*/
|
||||||
String[] getCommands();
|
String[] getCommands();
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onCommand(String, Bundle, ResultReceiver)}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onCommand(String, Bundle, ResultReceiver)}.
|
|
||||||
*/
|
|
||||||
void onCommand(Player player, String command, Bundle extras, ResultReceiver cb);
|
void onCommand(Player player, String command, Bundle extras, ResultReceiver cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Interface to which playback preparation actions are delegated. */
|
||||||
* Interface to which playback preparation actions are delegated.
|
|
||||||
*/
|
|
||||||
public interface PlaybackPreparer extends CommandReceiver {
|
public interface PlaybackPreparer extends CommandReceiver {
|
||||||
|
|
||||||
long ACTIONS =
|
long ACTIONS =
|
||||||
|
|
@ -127,96 +123,77 @@ public final class MediaSessionConnector {
|
||||||
* @return The bitmask of the supported media actions.
|
* @return The bitmask of the supported media actions.
|
||||||
*/
|
*/
|
||||||
long getSupportedPrepareActions();
|
long getSupportedPrepareActions();
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onPrepare()}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onPrepare()}.
|
|
||||||
*/
|
|
||||||
void onPrepare();
|
void onPrepare();
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onPrepareFromMediaId(String, Bundle)}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onPrepareFromMediaId(String, Bundle)}.
|
|
||||||
*/
|
|
||||||
void onPrepareFromMediaId(String mediaId, Bundle extras);
|
void onPrepareFromMediaId(String mediaId, Bundle extras);
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onPrepareFromSearch(String, Bundle)}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onPrepareFromSearch(String, Bundle)}.
|
|
||||||
*/
|
|
||||||
void onPrepareFromSearch(String query, Bundle extras);
|
void onPrepareFromSearch(String query, Bundle extras);
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onPrepareFromUri(Uri, Bundle)}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onPrepareFromUri(Uri, Bundle)}.
|
|
||||||
*/
|
|
||||||
void onPrepareFromUri(Uri uri, Bundle extras);
|
void onPrepareFromUri(Uri uri, Bundle extras);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Interface to which playback actions are delegated. */
|
||||||
* Interface to which playback actions are delegated.
|
|
||||||
*/
|
|
||||||
public interface PlaybackController extends CommandReceiver {
|
public interface PlaybackController extends CommandReceiver {
|
||||||
|
|
||||||
long ACTIONS = PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_PLAY
|
long ACTIONS =
|
||||||
| PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_SEEK_TO
|
PlaybackStateCompat.ACTION_PLAY_PAUSE
|
||||||
| PlaybackStateCompat.ACTION_FAST_FORWARD | PlaybackStateCompat.ACTION_REWIND
|
| PlaybackStateCompat.ACTION_PLAY
|
||||||
| PlaybackStateCompat.ACTION_STOP | PlaybackStateCompat.ACTION_SET_REPEAT_MODE
|
| PlaybackStateCompat.ACTION_PAUSE
|
||||||
| PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE;
|
| PlaybackStateCompat.ACTION_SEEK_TO
|
||||||
|
| PlaybackStateCompat.ACTION_FAST_FORWARD
|
||||||
|
| PlaybackStateCompat.ACTION_REWIND
|
||||||
|
| PlaybackStateCompat.ACTION_STOP
|
||||||
|
| PlaybackStateCompat.ACTION_SET_REPEAT_MODE
|
||||||
|
| PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the actions which are supported by the controller. The supported actions must be a
|
* Returns the actions which are supported by the controller. The supported actions must be a
|
||||||
* bitmask combined out of {@link PlaybackStateCompat#ACTION_PLAY_PAUSE},
|
* bitmask combined out of {@link PlaybackStateCompat#ACTION_PLAY_PAUSE}, {@link
|
||||||
* {@link PlaybackStateCompat#ACTION_PLAY}, {@link PlaybackStateCompat#ACTION_PAUSE},
|
* PlaybackStateCompat#ACTION_PLAY}, {@link PlaybackStateCompat#ACTION_PAUSE}, {@link
|
||||||
* {@link PlaybackStateCompat#ACTION_SEEK_TO}, {@link PlaybackStateCompat#ACTION_FAST_FORWARD},
|
* PlaybackStateCompat#ACTION_SEEK_TO}, {@link PlaybackStateCompat#ACTION_FAST_FORWARD}, {@link
|
||||||
* {@link PlaybackStateCompat#ACTION_REWIND}, {@link PlaybackStateCompat#ACTION_STOP},
|
* PlaybackStateCompat#ACTION_REWIND}, {@link PlaybackStateCompat#ACTION_STOP}, {@link
|
||||||
* {@link PlaybackStateCompat#ACTION_SET_REPEAT_MODE} and
|
* PlaybackStateCompat#ACTION_SET_REPEAT_MODE} and {@link
|
||||||
* {@link PlaybackStateCompat#ACTION_SET_SHUFFLE_MODE}.
|
* PlaybackStateCompat#ACTION_SET_SHUFFLE_MODE}.
|
||||||
*
|
*
|
||||||
* @param player The player.
|
* @param player The player.
|
||||||
* @return The bitmask of the supported media actions.
|
* @return The bitmask of the supported media actions.
|
||||||
*/
|
*/
|
||||||
long getSupportedPlaybackActions(@Nullable Player player);
|
long getSupportedPlaybackActions(@Nullable Player player);
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onPlay()}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onPlay()}.
|
|
||||||
*/
|
|
||||||
void onPlay(Player player);
|
void onPlay(Player player);
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onPause()}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onPause()}.
|
|
||||||
*/
|
|
||||||
void onPause(Player player);
|
void onPause(Player player);
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onSeekTo(long)}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onSeekTo(long)}.
|
|
||||||
*/
|
|
||||||
void onSeekTo(Player player, long position);
|
void onSeekTo(Player player, long position);
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onFastForward()}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onFastForward()}.
|
|
||||||
*/
|
|
||||||
void onFastForward(Player player);
|
void onFastForward(Player player);
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onRewind()}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onRewind()}.
|
|
||||||
*/
|
|
||||||
void onRewind(Player player);
|
void onRewind(Player player);
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onStop()}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onStop()}.
|
|
||||||
*/
|
|
||||||
void onStop(Player player);
|
void onStop(Player player);
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onSetShuffleMode(int)}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onSetShuffleMode(int)}.
|
|
||||||
*/
|
|
||||||
void onSetShuffleMode(Player player, int shuffleMode);
|
void onSetShuffleMode(Player player, int shuffleMode);
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onSetRepeatMode(int)}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onSetRepeatMode(int)}.
|
|
||||||
*/
|
|
||||||
void onSetRepeatMode(Player player, int repeatMode);
|
void onSetRepeatMode(Player player, int repeatMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles queue navigation actions, and updates the media session queue by calling
|
* Handles queue navigation actions, and updates the media session queue by calling {@code
|
||||||
* {@code MediaSessionCompat.setQueue()}.
|
* MediaSessionCompat.setQueue()}.
|
||||||
*/
|
*/
|
||||||
public interface QueueNavigator extends CommandReceiver {
|
public interface QueueNavigator extends CommandReceiver {
|
||||||
|
|
||||||
long ACTIONS = PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM
|
long ACTIONS =
|
||||||
| PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
|
PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM
|
||||||
|
| PlaybackStateCompat.ACTION_SKIP_TO_NEXT
|
||||||
|
| PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the actions which are supported by the navigator. The supported actions must be a
|
* Returns the actions which are supported by the navigator. The supported actions must be a
|
||||||
* bitmask combined out of {@link PlaybackStateCompat#ACTION_SKIP_TO_QUEUE_ITEM},
|
* bitmask combined out of {@link PlaybackStateCompat#ACTION_SKIP_TO_QUEUE_ITEM}, {@link
|
||||||
* {@link PlaybackStateCompat#ACTION_SKIP_TO_NEXT},
|
* PlaybackStateCompat#ACTION_SKIP_TO_NEXT}, {@link
|
||||||
* {@link PlaybackStateCompat#ACTION_SKIP_TO_PREVIOUS}.
|
* PlaybackStateCompat#ACTION_SKIP_TO_PREVIOUS}.
|
||||||
*
|
*
|
||||||
* @param player The {@link Player}.
|
* @param player The {@link Player}.
|
||||||
* @return The bitmask of the supported media actions.
|
* @return The bitmask of the supported media actions.
|
||||||
|
|
@ -235,34 +212,26 @@ public final class MediaSessionConnector {
|
||||||
*/
|
*/
|
||||||
void onCurrentWindowIndexChanged(Player player);
|
void onCurrentWindowIndexChanged(Player player);
|
||||||
/**
|
/**
|
||||||
* Gets the id of the currently active queue item, or
|
* Gets the id of the currently active queue item, or {@link
|
||||||
* {@link MediaSessionCompat.QueueItem#UNKNOWN_ID} if the active item is unknown.
|
* MediaSessionCompat.QueueItem#UNKNOWN_ID} if the active item is unknown.
|
||||||
* <p>
|
*
|
||||||
* To let the connector publish metadata for the active queue item, the queue item with the
|
* <p>To let the connector publish metadata for the active queue item, the queue item with the
|
||||||
* returned id must be available in the list of items returned by
|
* returned id must be available in the list of items returned by {@link
|
||||||
* {@link MediaControllerCompat#getQueue()}.
|
* MediaControllerCompat#getQueue()}.
|
||||||
*
|
*
|
||||||
* @param player The player connected to the media session.
|
* @param player The player connected to the media session.
|
||||||
* @return The id of the active queue item.
|
* @return The id of the active queue item.
|
||||||
*/
|
*/
|
||||||
long getActiveQueueItemId(@Nullable Player player);
|
long getActiveQueueItemId(@Nullable Player player);
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onSkipToPrevious()}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onSkipToPrevious()}.
|
|
||||||
*/
|
|
||||||
void onSkipToPrevious(Player player);
|
void onSkipToPrevious(Player player);
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onSkipToQueueItem(long)}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onSkipToQueueItem(long)}.
|
|
||||||
*/
|
|
||||||
void onSkipToQueueItem(Player player, long id);
|
void onSkipToQueueItem(Player player, long id);
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onSkipToNext()}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onSkipToNext()}.
|
|
||||||
*/
|
|
||||||
void onSkipToNext(Player player);
|
void onSkipToNext(Player player);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Handles media session queue edits. */
|
||||||
* Handles media session queue edits.
|
|
||||||
*/
|
|
||||||
public interface QueueEditor extends CommandReceiver {
|
public interface QueueEditor extends CommandReceiver {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -270,8 +239,8 @@ public final class MediaSessionConnector {
|
||||||
*/
|
*/
|
||||||
void onAddQueueItem(Player player, MediaDescriptionCompat description);
|
void onAddQueueItem(Player player, MediaDescriptionCompat description);
|
||||||
/**
|
/**
|
||||||
* See {@link MediaSessionCompat.Callback#onAddQueueItem(MediaDescriptionCompat description,
|
* See {@link MediaSessionCompat.Callback#onAddQueueItem(MediaDescriptionCompat description, int
|
||||||
* int index)}.
|
* index)}.
|
||||||
*/
|
*/
|
||||||
void onAddQueueItem(Player player, MediaDescriptionCompat description, int index);
|
void onAddQueueItem(Player player, MediaDescriptionCompat description, int index);
|
||||||
/**
|
/**
|
||||||
|
|
@ -279,9 +248,7 @@ public final class MediaSessionConnector {
|
||||||
* description)}.
|
* description)}.
|
||||||
*/
|
*/
|
||||||
void onRemoveQueueItem(Player player, MediaDescriptionCompat description);
|
void onRemoveQueueItem(Player player, MediaDescriptionCompat description);
|
||||||
/**
|
/** See {@link MediaSessionCompat.Callback#onRemoveQueueItemAt(int index)}. */
|
||||||
* See {@link MediaSessionCompat.Callback#onRemoveQueueItemAt(int index)}.
|
|
||||||
*/
|
|
||||||
void onRemoveQueueItemAt(Player player, int index);
|
void onRemoveQueueItemAt(Player player, int index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -308,26 +275,33 @@ public final class MediaSessionConnector {
|
||||||
void onCustomAction(String action, Bundle extras);
|
void onCustomAction(String action, Bundle extras);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@link PlaybackStateCompat.CustomAction} which will be published to the
|
* Returns a {@link PlaybackStateCompat.CustomAction} which will be published to the media
|
||||||
* media session by the connector or {@code null} if this action should not be published at the
|
* session by the connector or {@code null} if this action should not be published at the given
|
||||||
* given player state.
|
* player state.
|
||||||
*
|
*
|
||||||
* @return The custom action to be included in the session playback state or {@code null}.
|
* @return The custom action to be included in the session playback state or {@code null}.
|
||||||
*/
|
*/
|
||||||
PlaybackStateCompat.CustomAction getCustomAction();
|
PlaybackStateCompat.CustomAction getCustomAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Provides a {@link MediaMetadataCompat} for a given player state. */
|
||||||
* The wrapped {@link MediaSessionCompat}.
|
public interface MediaMetadataProvider {
|
||||||
*/
|
/**
|
||||||
|
* Gets the {@link MediaMetadataCompat} to be published to the session.
|
||||||
|
*
|
||||||
|
* @param player The player for which to provide metadata.
|
||||||
|
* @return The {@link MediaMetadataCompat} to be published to the session.
|
||||||
|
*/
|
||||||
|
MediaMetadataCompat getMetadata(Player player);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The wrapped {@link MediaSessionCompat}. */
|
||||||
public final MediaSessionCompat mediaSession;
|
public final MediaSessionCompat mediaSession;
|
||||||
|
|
||||||
private final MediaControllerCompat mediaController;
|
private @Nullable final MediaMetadataProvider mediaMetadataProvider;
|
||||||
private final boolean doMaintainMetadata;
|
|
||||||
private final ExoPlayerEventListener exoPlayerEventListener;
|
private final ExoPlayerEventListener exoPlayerEventListener;
|
||||||
private final MediaSessionCallback mediaSessionCallback;
|
private final MediaSessionCallback mediaSessionCallback;
|
||||||
private final PlaybackController playbackController;
|
private final PlaybackController playbackController;
|
||||||
private final String metadataExtrasPrefix;
|
|
||||||
private final Map<String, CommandReceiver> commandMap;
|
private final Map<String, CommandReceiver> commandMap;
|
||||||
|
|
||||||
private Player player;
|
private Player player;
|
||||||
|
|
@ -353,14 +327,18 @@ public final class MediaSessionConnector {
|
||||||
/**
|
/**
|
||||||
* Creates an instance.
|
* Creates an instance.
|
||||||
*
|
*
|
||||||
* <p>Equivalent to {@code MediaSessionConnector(mediaSession, playbackController, true, null)}.
|
* <p>Equivalent to {@code MediaSessionConnector(mediaSession, playbackController, new
|
||||||
|
* DefaultMediaMetadataProvider(mediaSession.getController(), null))}.
|
||||||
*
|
*
|
||||||
* @param mediaSession The {@link MediaSessionCompat} to connect to.
|
* @param mediaSession The {@link MediaSessionCompat} to connect to.
|
||||||
* @param playbackController A {@link PlaybackController} for handling playback actions.
|
* @param playbackController A {@link PlaybackController} for handling playback actions.
|
||||||
*/
|
*/
|
||||||
public MediaSessionConnector(
|
public MediaSessionConnector(
|
||||||
MediaSessionCompat mediaSession, PlaybackController playbackController) {
|
MediaSessionCompat mediaSession, PlaybackController playbackController) {
|
||||||
this(mediaSession, playbackController, true, null);
|
this(
|
||||||
|
mediaSession,
|
||||||
|
playbackController,
|
||||||
|
new DefaultMediaMetadataProvider(mediaSession.getController(), null));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -369,24 +347,46 @@ public final class MediaSessionConnector {
|
||||||
* @param mediaSession The {@link MediaSessionCompat} to connect to.
|
* @param mediaSession The {@link MediaSessionCompat} to connect to.
|
||||||
* @param playbackController A {@link PlaybackController} for handling playback actions, or {@code
|
* @param playbackController A {@link PlaybackController} for handling playback actions, or {@code
|
||||||
* null} if the connector should handle playback actions directly.
|
* null} if the connector should handle playback actions directly.
|
||||||
* @param doMaintainMetadata Whether the connector should maintain the metadata of the session. If
|
* @param doMaintainMetadata Whether the connector should maintain the metadata of the session.
|
||||||
* {@code false}, you need to maintain the metadata of the media session yourself (provide at
|
|
||||||
* least the duration to allow clients to show a progress bar).
|
|
||||||
* @param metadataExtrasPrefix A string to prefix extra keys which are propagated from the active
|
* @param metadataExtrasPrefix A string to prefix extra keys which are propagated from the active
|
||||||
* queue item to the session metadata.
|
* queue item to the session metadata.
|
||||||
|
* @deprecated Use {@link MediaSessionConnector#MediaSessionConnector(MediaSessionCompat,
|
||||||
|
* PlaybackController, MediaMetadataProvider)}.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public MediaSessionConnector(
|
||||||
|
MediaSessionCompat mediaSession,
|
||||||
|
@Nullable PlaybackController playbackController,
|
||||||
|
boolean doMaintainMetadata,
|
||||||
|
@Nullable String metadataExtrasPrefix) {
|
||||||
|
this(
|
||||||
|
mediaSession,
|
||||||
|
playbackController,
|
||||||
|
doMaintainMetadata
|
||||||
|
? new DefaultMediaMetadataProvider(mediaSession.getController(), metadataExtrasPrefix)
|
||||||
|
: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance. Must be called on the same thread that is used to construct the player
|
||||||
|
* instances passed to {@link #setPlayer(Player, PlaybackPreparer, CustomActionProvider...)}.
|
||||||
|
*
|
||||||
|
* @param mediaSession The {@link MediaSessionCompat} to connect to.
|
||||||
|
* @param playbackController A {@link PlaybackController} for handling playback actions, or {@code
|
||||||
|
* null} if the connector should handle playback actions directly.
|
||||||
|
* @param mediaMetadataProvider A {@link MediaMetadataProvider} for providing a custom metadata
|
||||||
|
* object to be published to the media session, or {@code null} if metadata shouldn't be
|
||||||
|
* published.
|
||||||
*/
|
*/
|
||||||
public MediaSessionConnector(
|
public MediaSessionConnector(
|
||||||
MediaSessionCompat mediaSession,
|
MediaSessionCompat mediaSession,
|
||||||
PlaybackController playbackController,
|
@Nullable PlaybackController playbackController,
|
||||||
boolean doMaintainMetadata,
|
@Nullable MediaMetadataProvider mediaMetadataProvider) {
|
||||||
@Nullable String metadataExtrasPrefix) {
|
|
||||||
this.mediaSession = mediaSession;
|
this.mediaSession = mediaSession;
|
||||||
this.playbackController = playbackController != null ? playbackController
|
this.playbackController =
|
||||||
: new DefaultPlaybackController();
|
playbackController != null ? playbackController : new DefaultPlaybackController();
|
||||||
this.metadataExtrasPrefix = metadataExtrasPrefix != null ? metadataExtrasPrefix : "";
|
this.mediaMetadataProvider = mediaMetadataProvider;
|
||||||
this.doMaintainMetadata = doMaintainMetadata;
|
|
||||||
mediaSession.setFlags(BASE_MEDIA_SESSION_FLAGS);
|
mediaSession.setFlags(BASE_MEDIA_SESSION_FLAGS);
|
||||||
mediaController = mediaSession.getController();
|
|
||||||
mediaSessionCallback = new MediaSessionCallback();
|
mediaSessionCallback = new MediaSessionCallback();
|
||||||
exoPlayerEventListener = new ExoPlayerEventListener();
|
exoPlayerEventListener = new ExoPlayerEventListener();
|
||||||
customActionMap = Collections.emptyMap();
|
customActionMap = Collections.emptyMap();
|
||||||
|
|
@ -420,8 +420,10 @@ public final class MediaSessionConnector {
|
||||||
this.playbackPreparer = playbackPreparer;
|
this.playbackPreparer = playbackPreparer;
|
||||||
registerCommandReceiver(playbackPreparer);
|
registerCommandReceiver(playbackPreparer);
|
||||||
|
|
||||||
this.customActionProviders = (player != null && customActionProviders != null)
|
this.customActionProviders =
|
||||||
? customActionProviders : new CustomActionProvider[0];
|
(player != null && customActionProviders != null)
|
||||||
|
? customActionProviders
|
||||||
|
: new CustomActionProvider[0];
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
Handler handler = new Handler(Util.getLooper());
|
Handler handler = new Handler(Util.getLooper());
|
||||||
mediaSession.setCallback(mediaSessionCallback, handler);
|
mediaSession.setCallback(mediaSessionCallback, handler);
|
||||||
|
|
@ -486,19 +488,15 @@ public final class MediaSessionConnector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCommandReceiver(CommandReceiver commandReceiver) {
|
/**
|
||||||
if (commandReceiver != null && commandReceiver.getCommands() != null) {
|
* Updates the metadata of the media session.
|
||||||
for (String command : commandReceiver.getCommands()) {
|
*
|
||||||
commandMap.put(command, commandReceiver);
|
* <p>Apps normally only need to call this method when the backing data for a given media item has
|
||||||
}
|
* changed and the metadata should be updated immediately.
|
||||||
}
|
*/
|
||||||
}
|
public final void updateMediaSessionMetadata() {
|
||||||
|
if (mediaMetadataProvider != null) {
|
||||||
private void unregisterCommandReceiver(CommandReceiver commandReceiver) {
|
mediaSession.setMetadata(mediaMetadataProvider.getMetadata(player));
|
||||||
if (commandReceiver != null && commandReceiver.getCommands() != null) {
|
|
||||||
for (String command : commandReceiver.getCommands()) {
|
|
||||||
commandMap.remove(command);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -531,28 +529,50 @@ public final class MediaSessionConnector {
|
||||||
Pair<Integer, String> message = errorMessageProvider.getErrorMessage(playbackError);
|
Pair<Integer, String> message = errorMessageProvider.getErrorMessage(playbackError);
|
||||||
builder.setErrorMessage(message.first, message.second);
|
builder.setErrorMessage(message.first, message.second);
|
||||||
}
|
}
|
||||||
long activeQueueItemId = queueNavigator != null ? queueNavigator.getActiveQueueItemId(player)
|
long activeQueueItemId =
|
||||||
: MediaSessionCompat.QueueItem.UNKNOWN_ID;
|
queueNavigator != null
|
||||||
|
? queueNavigator.getActiveQueueItemId(player)
|
||||||
|
: MediaSessionCompat.QueueItem.UNKNOWN_ID;
|
||||||
Bundle extras = new Bundle();
|
Bundle extras = new Bundle();
|
||||||
extras.putFloat(EXTRAS_PITCH, player.getPlaybackParameters().pitch);
|
extras.putFloat(EXTRAS_PITCH, player.getPlaybackParameters().pitch);
|
||||||
builder.setActions(buildPlaybackActions())
|
builder
|
||||||
|
.setActions(buildPlaybackActions())
|
||||||
.setActiveQueueItemId(activeQueueItemId)
|
.setActiveQueueItemId(activeQueueItemId)
|
||||||
.setBufferedPosition(player.getBufferedPosition())
|
.setBufferedPosition(player.getBufferedPosition())
|
||||||
.setState(sessionPlaybackState, player.getCurrentPosition(),
|
.setState(
|
||||||
player.getPlaybackParameters().speed, SystemClock.elapsedRealtime())
|
sessionPlaybackState,
|
||||||
|
player.getCurrentPosition(),
|
||||||
|
player.getPlaybackParameters().speed,
|
||||||
|
SystemClock.elapsedRealtime())
|
||||||
.setExtras(extras);
|
.setExtras(extras);
|
||||||
mediaSession.setPlaybackState(builder.build());
|
mediaSession.setPlaybackState(builder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void registerCommandReceiver(CommandReceiver commandReceiver) {
|
||||||
|
if (commandReceiver != null && commandReceiver.getCommands() != null) {
|
||||||
|
for (String command : commandReceiver.getCommands()) {
|
||||||
|
commandMap.put(command, commandReceiver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unregisterCommandReceiver(CommandReceiver commandReceiver) {
|
||||||
|
if (commandReceiver != null && commandReceiver.getCommands() != null) {
|
||||||
|
for (String command : commandReceiver.getCommands()) {
|
||||||
|
commandMap.remove(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private long buildPlaybackActions() {
|
private long buildPlaybackActions() {
|
||||||
long actions = (PlaybackController.ACTIONS
|
long actions =
|
||||||
& playbackController.getSupportedPlaybackActions(player));
|
(PlaybackController.ACTIONS & playbackController.getSupportedPlaybackActions(player));
|
||||||
if (playbackPreparer != null) {
|
if (playbackPreparer != null) {
|
||||||
actions |= (PlaybackPreparer.ACTIONS & playbackPreparer.getSupportedPrepareActions());
|
actions |= (PlaybackPreparer.ACTIONS & playbackPreparer.getSupportedPrepareActions());
|
||||||
}
|
}
|
||||||
if (queueNavigator != null) {
|
if (queueNavigator != null) {
|
||||||
actions |= (QueueNavigator.ACTIONS & queueNavigator.getSupportedQueueNavigatorActions(
|
actions |=
|
||||||
player));
|
(QueueNavigator.ACTIONS & queueNavigator.getSupportedQueueNavigatorActions(player));
|
||||||
}
|
}
|
||||||
if (ratingCallback != null) {
|
if (ratingCallback != null) {
|
||||||
actions |= RatingCallback.ACTIONS;
|
actions |= RatingCallback.ACTIONS;
|
||||||
|
|
@ -560,17 +580,76 @@ public final class MediaSessionConnector {
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateMediaSessionMetadata() {
|
private int mapPlaybackState(int exoPlayerPlaybackState, boolean playWhenReady) {
|
||||||
if (doMaintainMetadata) {
|
switch (exoPlayerPlaybackState) {
|
||||||
|
case Player.STATE_BUFFERING:
|
||||||
|
return PlaybackStateCompat.STATE_BUFFERING;
|
||||||
|
case Player.STATE_READY:
|
||||||
|
return playWhenReady ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED;
|
||||||
|
case Player.STATE_ENDED:
|
||||||
|
return PlaybackStateCompat.STATE_PAUSED;
|
||||||
|
default:
|
||||||
|
return PlaybackStateCompat.STATE_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canDispatchToPlaybackPreparer(long action) {
|
||||||
|
return playbackPreparer != null
|
||||||
|
&& (playbackPreparer.getSupportedPrepareActions() & PlaybackPreparer.ACTIONS & action) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canDispatchToRatingCallback(long action) {
|
||||||
|
return ratingCallback != null && (RatingCallback.ACTIONS & action) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canDispatchToPlaybackController(long action) {
|
||||||
|
return (playbackController.getSupportedPlaybackActions(player)
|
||||||
|
& PlaybackController.ACTIONS
|
||||||
|
& action)
|
||||||
|
!= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canDispatchToQueueNavigator(long action) {
|
||||||
|
return queueNavigator != null
|
||||||
|
&& (queueNavigator.getSupportedQueueNavigatorActions(player)
|
||||||
|
& QueueNavigator.ACTIONS
|
||||||
|
& action)
|
||||||
|
!= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a default {@link MediaMetadataCompat} with properties and extras propagated from the
|
||||||
|
* active queue item to the session metadata.
|
||||||
|
*/
|
||||||
|
public static final class DefaultMediaMetadataProvider implements MediaMetadataProvider {
|
||||||
|
|
||||||
|
private final MediaControllerCompat mediaController;
|
||||||
|
private final String metadataExtrasPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance.
|
||||||
|
*
|
||||||
|
* @param mediaController The {@link MediaControllerCompat}.
|
||||||
|
* @param metadataExtrasPrefix A string to prefix extra keys which are propagated from the
|
||||||
|
* active queue item to the session metadata.
|
||||||
|
*/
|
||||||
|
public DefaultMediaMetadataProvider(
|
||||||
|
MediaControllerCompat mediaController, @Nullable String metadataExtrasPrefix) {
|
||||||
|
this.mediaController = mediaController;
|
||||||
|
this.metadataExtrasPrefix = metadataExtrasPrefix != null ? metadataExtrasPrefix : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MediaMetadataCompat getMetadata(Player player) {
|
||||||
MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
|
MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
|
||||||
if (player != null && player.isPlayingAd()) {
|
if (player != null && player.isPlayingAd()) {
|
||||||
builder.putLong(MediaMetadataCompat.METADATA_KEY_ADVERTISEMENT, 1);
|
builder.putLong(MediaMetadataCompat.METADATA_KEY_ADVERTISEMENT, 1);
|
||||||
}
|
}
|
||||||
builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, player == null ? 0
|
builder.putLong(
|
||||||
: player.getDuration() == C.TIME_UNSET ? -1 : player.getDuration());
|
MediaMetadataCompat.METADATA_KEY_DURATION,
|
||||||
|
player == null ? 0 : player.getDuration() == C.TIME_UNSET ? -1 : player.getDuration());
|
||||||
if (queueNavigator != null) {
|
long activeQueueItemId = mediaController.getPlaybackState().getActiveQueueItemId();
|
||||||
long activeQueueItemId = queueNavigator.getActiveQueueItemId(player);
|
if (activeQueueItemId != MediaSessionCompat.QueueItem.UNKNOWN_ID) {
|
||||||
List<MediaSessionCompat.QueueItem> queue = mediaController.getQueue();
|
List<MediaSessionCompat.QueueItem> queue = mediaController.getQueue();
|
||||||
for (int i = 0; queue != null && i < queue.size(); i++) {
|
for (int i = 0; queue != null && i < queue.size(); i++) {
|
||||||
MediaSessionCompat.QueueItem queueItem = queue.get(i);
|
MediaSessionCompat.QueueItem queueItem = queue.get(i);
|
||||||
|
|
@ -601,77 +680,50 @@ public final class MediaSessionConnector {
|
||||||
builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, title);
|
builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, title);
|
||||||
}
|
}
|
||||||
if (description.getSubtitle() != null) {
|
if (description.getSubtitle() != null) {
|
||||||
builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE,
|
builder.putString(
|
||||||
|
MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE,
|
||||||
String.valueOf(description.getSubtitle()));
|
String.valueOf(description.getSubtitle()));
|
||||||
}
|
}
|
||||||
if (description.getDescription() != null) {
|
if (description.getDescription() != null) {
|
||||||
builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_DESCRIPTION,
|
builder.putString(
|
||||||
|
MediaMetadataCompat.METADATA_KEY_DISPLAY_DESCRIPTION,
|
||||||
String.valueOf(description.getDescription()));
|
String.valueOf(description.getDescription()));
|
||||||
}
|
}
|
||||||
if (description.getIconBitmap() != null) {
|
if (description.getIconBitmap() != null) {
|
||||||
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON,
|
builder.putBitmap(
|
||||||
description.getIconBitmap());
|
MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, description.getIconBitmap());
|
||||||
}
|
}
|
||||||
if (description.getIconUri() != null) {
|
if (description.getIconUri() != null) {
|
||||||
builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI,
|
builder.putString(
|
||||||
|
MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI,
|
||||||
String.valueOf(description.getIconUri()));
|
String.valueOf(description.getIconUri()));
|
||||||
}
|
}
|
||||||
if (description.getMediaId() != null) {
|
if (description.getMediaId() != null) {
|
||||||
builder.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID,
|
builder.putString(
|
||||||
|
MediaMetadataCompat.METADATA_KEY_MEDIA_ID,
|
||||||
String.valueOf(description.getMediaId()));
|
String.valueOf(description.getMediaId()));
|
||||||
}
|
}
|
||||||
if (description.getMediaUri() != null) {
|
if (description.getMediaUri() != null) {
|
||||||
builder.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_URI,
|
builder.putString(
|
||||||
|
MediaMetadataCompat.METADATA_KEY_MEDIA_URI,
|
||||||
String.valueOf(description.getMediaUri()));
|
String.valueOf(description.getMediaUri()));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mediaSession.setMetadata(builder.build());
|
return builder.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int mapPlaybackState(int exoPlayerPlaybackState, boolean playWhenReady) {
|
|
||||||
switch (exoPlayerPlaybackState) {
|
|
||||||
case Player.STATE_BUFFERING:
|
|
||||||
return PlaybackStateCompat.STATE_BUFFERING;
|
|
||||||
case Player.STATE_READY:
|
|
||||||
return playWhenReady ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED;
|
|
||||||
case Player.STATE_ENDED:
|
|
||||||
return PlaybackStateCompat.STATE_PAUSED;
|
|
||||||
default:
|
|
||||||
return PlaybackStateCompat.STATE_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canDispatchToPlaybackPreparer(long action) {
|
|
||||||
return playbackPreparer != null && (playbackPreparer.getSupportedPrepareActions()
|
|
||||||
& PlaybackPreparer.ACTIONS & action) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canDispatchToRatingCallback(long action) {
|
|
||||||
return ratingCallback != null && (RatingCallback.ACTIONS & action) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canDispatchToPlaybackController(long action) {
|
|
||||||
return (playbackController.getSupportedPlaybackActions(player)
|
|
||||||
& PlaybackController.ACTIONS & action) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canDispatchToQueueNavigator(long action) {
|
|
||||||
return queueNavigator != null && (queueNavigator.getSupportedQueueNavigatorActions(player)
|
|
||||||
& QueueNavigator.ACTIONS & action) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ExoPlayerEventListener extends Player.DefaultEventListener {
|
private class ExoPlayerEventListener extends Player.DefaultEventListener {
|
||||||
|
|
||||||
private int currentWindowIndex;
|
private int currentWindowIndex;
|
||||||
private int currentWindowCount;
|
private int currentWindowCount;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTimelineChanged(Timeline timeline, Object manifest,
|
public void onTimelineChanged(
|
||||||
@Player.TimelineChangeReason int reason) {
|
Timeline timeline, Object manifest, @Player.TimelineChangeReason int reason) {
|
||||||
int windowCount = player.getCurrentTimeline().getWindowCount();
|
int windowCount = player.getCurrentTimeline().getWindowCount();
|
||||||
int windowIndex = player.getCurrentWindowIndex();
|
int windowIndex = player.getCurrentWindowIndex();
|
||||||
if (queueNavigator != null) {
|
if (queueNavigator != null) {
|
||||||
|
|
@ -693,16 +745,21 @@ public final class MediaSessionConnector {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) {
|
public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) {
|
||||||
mediaSession.setRepeatMode(repeatMode == Player.REPEAT_MODE_ONE
|
mediaSession.setRepeatMode(
|
||||||
? PlaybackStateCompat.REPEAT_MODE_ONE : repeatMode == Player.REPEAT_MODE_ALL
|
repeatMode == Player.REPEAT_MODE_ONE
|
||||||
? PlaybackStateCompat.REPEAT_MODE_ALL : PlaybackStateCompat.REPEAT_MODE_NONE);
|
? PlaybackStateCompat.REPEAT_MODE_ONE
|
||||||
|
: repeatMode == Player.REPEAT_MODE_ALL
|
||||||
|
? PlaybackStateCompat.REPEAT_MODE_ALL
|
||||||
|
: PlaybackStateCompat.REPEAT_MODE_NONE);
|
||||||
updateMediaSessionPlaybackState();
|
updateMediaSessionPlaybackState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
|
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
|
||||||
mediaSession.setShuffleMode(shuffleModeEnabled ? PlaybackStateCompat.SHUFFLE_MODE_ALL
|
mediaSession.setShuffleMode(
|
||||||
: PlaybackStateCompat.SHUFFLE_MODE_NONE);
|
shuffleModeEnabled
|
||||||
|
? PlaybackStateCompat.SHUFFLE_MODE_ALL
|
||||||
|
: PlaybackStateCompat.SHUFFLE_MODE_NONE);
|
||||||
updateMediaSessionPlaybackState();
|
updateMediaSessionPlaybackState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -713,7 +770,11 @@ public final class MediaSessionConnector {
|
||||||
queueNavigator.onCurrentWindowIndexChanged(player);
|
queueNavigator.onCurrentWindowIndexChanged(player);
|
||||||
}
|
}
|
||||||
currentWindowIndex = player.getCurrentWindowIndex();
|
currentWindowIndex = player.getCurrentWindowIndex();
|
||||||
|
// Update playback state after queueNavigator.onCurrentWindowIndexChanged has been called
|
||||||
|
// and before updating metadata.
|
||||||
|
updateMediaSessionPlaybackState();
|
||||||
updateMediaSessionMetadata();
|
updateMediaSessionMetadata();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
updateMediaSessionPlaybackState();
|
updateMediaSessionPlaybackState();
|
||||||
}
|
}
|
||||||
|
|
@ -722,7 +783,6 @@ public final class MediaSessionConnector {
|
||||||
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
|
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
|
||||||
updateMediaSessionPlaybackState();
|
updateMediaSessionPlaybackState();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MediaSessionCallback extends MediaSessionCompat.Callback {
|
private class MediaSessionCallback extends MediaSessionCompat.Callback {
|
||||||
|
|
@ -918,7 +978,5 @@ public final class MediaSessionConnector {
|
||||||
queueEditor.onRemoveQueueItemAt(player, index);
|
queueEditor.onRemoveQueueItemAt(player, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue