Gradle dependencies
compile group: 'androidx.media', name: 'media-widget', version: '1.0.0-alpha06'
- groupId: androidx.media
- artifactId: media-widget
- version: 1.0.0-alpha06
Artifact androidx.media:media-widget:1.0.0-alpha06 it located at Google repository (https://maven.google.com/)
Summary
Fields |
---|
from RemoteSessionPlayer | VOLUME_CONTROL_ABSOLUTE, VOLUME_CONTROL_FIXED, VOLUME_CONTROL_RELATIVE |
from SessionPlayer | BUFFERING_STATE_BUFFERING_AND_PLAYABLE, BUFFERING_STATE_BUFFERING_AND_STARVED, BUFFERING_STATE_COMPLETE, BUFFERING_STATE_UNKNOWN, PLAYER_STATE_ERROR, PLAYER_STATE_IDLE, PLAYER_STATE_PAUSED, PLAYER_STATE_PLAYING, REPEAT_MODE_ALL, REPEAT_MODE_GROUP, REPEAT_MODE_NONE, REPEAT_MODE_ONE, SHUFFLE_MODE_ALL, SHUFFLE_MODE_GROUP, SHUFFLE_MODE_NONE, UNKNOWN_TIME |
Methods |
---|
public abstract <any> | addPlaylistItem(int index, MediaItem item)
Adds the media item to the playlist at position index. |
public abstract java.util.concurrent.Future<SessionPlayer.PlayerResult> | adjustVolume(int direction)
Adjust player volume with the direction. |
public void | close()
|
public abstract AudioAttributesCompat | getAudioAttributes()
Gets the AudioAttributesCompat that media player has. |
public abstract long | getBufferedPosition()
Gets the buffered position of current playback, or SessionPlayer.UNKNOWN_TIME if unknown. |
public abstract int | getBufferingState()
Returns the current buffering state of the player. |
public abstract MediaItem | getCurrentMediaItem()
Gets the current media item. |
public abstract int | getCurrentMediaItemIndex()
Gets the index of current media item in playlist. |
public abstract long | getCurrentPosition()
Gets the current playback head position. |
public abstract long | getDuration()
Gets the duration of the current media item, or SessionPlayer.UNKNOWN_TIME if unknown. |
public abstract int | getMaxVolume()
Gets the maximum volume that can be used in RemoteSessionPlayer.setVolume(int). |
public abstract int | getNextMediaItemIndex()
Gets the next item index in the playlist. |
public abstract float | getPlaybackSpeed()
Gets the actual playback speed to be used by the player when playing. |
public abstract int | getPlayerState()
Gets the current player state. |
public abstract java.util.List<MediaItem> | getPlaylist()
Gets the playlist. |
public abstract MediaMetadata | getPlaylistMetadata()
Gets the playlist metadata. |
public abstract int | getPreviousMediaItemIndex()
Gets the previous item index in the playlist. |
public abstract int | getRepeatMode()
Gets the repeat mode. |
public abstract int | getShuffleMode()
Gets the shuffle mode. |
public abstract int | getVolume()
Gets the current volume of this player to this player. |
public abstract int | getVolumeControlType()
Gets the volume type. |
public abstract <any> | pause()
Pauses playback. |
public abstract <any> | play()
Plays the playback. |
public abstract <any> | prepare()
Prepares the media items for playback. |
public abstract <any> | removePlaylistItem(int index)
Removes the media item from the playlist |
public abstract <any> | replacePlaylistItem(int index, MediaItem item)
Replaces the media item at index in the playlist. |
public abstract <any> | seekTo(long position)
Seeks to the specified position. |
public abstract <any> | setAudioAttributes(AudioAttributesCompat attributes)
Sets the AudioAttributesCompat to be used during the playback of the media. |
public abstract <any> | setMediaItem(MediaItem item)
Sets a MediaItem for playback. |
public abstract <any> | setPlaybackSpeed(float playbackSpeed)
Sets the playback speed. |
public abstract <any> | setPlaylist(java.util.List<MediaItem> list, MediaMetadata metadata)
Sets a list of MediaItem with metadata. |
public abstract <any> | setRepeatMode(int repeatMode)
Sets the repeat mode. |
public abstract <any> | setShuffleMode(int shuffleMode)
Sets the shuffle mode. |
public abstract java.util.concurrent.Future<SessionPlayer.PlayerResult> | setVolume(int volume)
Sets the volume of the audio of the media to play, expressed as a linear multiplier
on the audio samples. |
public abstract <any> | skipToNextPlaylistItem()
Skips to the next item in the playlist. |
public abstract <any> | skipToPlaylistItem(int index)
Skips to the the media item. |
public abstract <any> | skipToPreviousPlaylistItem()
Skips to the previous item in the playlist. |
public abstract <any> | updatePlaylistMetadata(MediaMetadata metadata)
Updates the playlist metadata while keeping the playlist as-is. |
from SessionPlayer | getCallbacks, registerPlayerCallback, unregisterPlayerCallback |
from java.lang.Object | clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Constructors
Methods
public abstract <any>
play()
Plays the playback.
public abstract <any>
prepare()
Prepares the media items for playback. During this time, the player may allocate resources
required to play, such as audio and video decoders.
public abstract <any>
pause()
Pauses playback.
public abstract <any>
seekTo(long position)
Seeks to the specified position. Moves the playback head to the specified position.
Parameters:
position: the new playback position in ms. The value should be in the range of start
and end positions defined in MediaItem.
public abstract long
getCurrentPosition()
Gets the current playback head position.
Returns:
the current playback position in ms, or SessionPlayer.UNKNOWN_TIME if unknown.
public abstract long
getDuration()
Gets the duration of the current media item, or SessionPlayer.UNKNOWN_TIME if unknown.
Returns:
the duration in ms, or SessionPlayer.UNKNOWN_TIME.
public abstract long
getBufferedPosition()
Gets the buffered position of current playback, or SessionPlayer.UNKNOWN_TIME if unknown.
Returns:
the buffered position in ms, or SessionPlayer.UNKNOWN_TIME.
public abstract int
getPlayerState()
Gets the current player state.
Returns:
the current player state
See also: SessionPlayer.PlayerCallback.onPlayerStateChanged(SessionPlayer, int), SessionPlayer.PLAYER_STATE_IDLE, SessionPlayer.PLAYER_STATE_PAUSED, SessionPlayer.PLAYER_STATE_PLAYING, SessionPlayer.PLAYER_STATE_ERROR
public abstract int
getBufferingState()
Returns the current buffering state of the player.
During the buffering, see SessionPlayer.getBufferedPosition() for the quantifying the amount
already buffered.
Returns:
the buffering state.
See also: SessionPlayer.getBufferedPosition()
Sets the AudioAttributesCompat to be used during the playback of the media.
You must call this method in SessionPlayer.PLAYER_STATE_IDLE in order for the audio attributes to
become effective thereafter.
Parameters:
attributes: non-null AudioAttributes
.
Gets the AudioAttributesCompat that media player has.
public abstract <any>
setMediaItem(
MediaItem item)
Sets a MediaItem for playback.
It's recommended to fill MediaMetadata in each MediaItem especially for the
duration information with the key MediaMetadata.METADATA_KEY_DURATION. Without the
duration information in the metadata, session will do extra work to get the duration and send
it to the controller.
The implementation must notify registered callbacks with
SessionPlayer.PlayerCallback.onPlaylistChanged(SessionPlayer, List, MediaMetadata) when it's
completed.
Parameters:
item: the descriptor of media item you want to play
Returns:
a which represents the pending completion of the command.
public abstract
MediaItem getCurrentMediaItem()
Gets the current media item.
Returns:
the current media item. Can be null only when media item or playlist hasn't
been set.
public abstract int
getCurrentMediaItemIndex()
Gets the index of current media item in playlist. This value may be updated when
SessionPlayer.PlayerCallback.onCurrentMediaItemChanged(SessionPlayer, MediaItem) or
SessionPlayer.PlayerCallback.onPlaylistChanged(SessionPlayer, List, MediaMetadata) is called.
Returns:
the index of current media item. Can be -1 only when current media item is null or
playlist hasn't been set.
public abstract int
getPreviousMediaItemIndex()
Gets the previous item index in the playlist. The returned value can be outdated after
SessionPlayer.PlayerCallback.onCurrentMediaItemChanged(SessionPlayer, MediaItem) or
SessionPlayer.PlayerCallback.onPlaylistChanged(SessionPlayer, List, MediaMetadata) is called.
Returns:
the index of previous media item. Can be -1 only when previous media item does not
exist or playlist hasn't been set.
public abstract int
getNextMediaItemIndex()
Gets the next item index in the playlist. The returned value can be outdated after
SessionPlayer.PlayerCallback.onCurrentMediaItemChanged(SessionPlayer, MediaItem) or
SessionPlayer.PlayerCallback.onPlaylistChanged(SessionPlayer, List, MediaMetadata) is called.
Returns:
the index of next media item. Can be -1 only when next media item does not exist or
playlist hasn't been set.
public abstract <any>
setPlaybackSpeed(float playbackSpeed)
Sets the playback speed. A value of 1.0f is the default playback value.
After changing the playback speed, it is recommended to query the actual speed supported
by the player, see SessionPlayer.getPlaybackSpeed().
Parameters:
playbackSpeed: playback speed
public abstract float
getPlaybackSpeed()
Gets the actual playback speed to be used by the player when playing.
Note that it may differ from the speed set in SessionPlayer.setPlaybackSpeed(float).
Returns:
the actual playback speed
public abstract int
getVolume()
Gets the current volume of this player to this player.
Note that it does not take into account the associated stream volume because the playback is
happening outside of the phone device.
Returns:
the player volume.
public abstract java.util.concurrent.Future<SessionPlayer.PlayerResult>
adjustVolume(int direction)
Adjust player volume with the direction. Override this API to customize volume change in
remote device
Default implement adjust volume by 1
This would be ignored when volume control type is RemoteSessionPlayer.VOLUME_CONTROL_FIXED.
Parameters:
direction: direction of the volume changes. Positive value for volume up, negative for
volume down.
public abstract java.util.concurrent.Future<SessionPlayer.PlayerResult>
setVolume(int volume)
Sets the volume of the audio of the media to play, expressed as a linear multiplier
on the audio samples.
Note that this volume is specific to the player, and is separate from stream volume
used across the platform.
A value of 0 indicates muting. See RemoteSessionPlayer.getMaxVolume() for the volume range
supported by this player.
Parameters:
volume: a value between 0.0f and RemoteSessionPlayer.getMaxVolume().
public abstract int
getMaxVolume()
Gets the maximum volume that can be used in RemoteSessionPlayer.setVolume(int).
Returns:
the maximum volume. Shouldn't be negative.
public abstract int
getVolumeControlType()
Gets the volume type.
This shouldn't be changed after instantiation.
Returns:
one of the volume type
See also: RemoteSessionPlayer.VOLUME_CONTROL_FIXED, RemoteSessionPlayer.VOLUME_CONTROL_RELATIVE, RemoteSessionPlayer.VOLUME_CONTROL_ABSOLUTE
public abstract <any>
setPlaylist(java.util.List<MediaItem> list,
MediaMetadata metadata)
Sets a list of MediaItem with metadata. Ensure uniqueness of each MediaItem
in the playlist so the session can uniquely identity individual items. All
MediaItems shouldn't be null as well.
It's recommended to fill MediaMetadata in each MediaItem especially for the
duration information with the key MediaMetadata.METADATA_KEY_DURATION. Without the
duration information in the metadata, session will do extra work to get the duration and send
it to the controller.
The implementation must notify registered callbacks with
SessionPlayer.PlayerCallback.onPlaylistChanged(SessionPlayer, List, MediaMetadata) when it's
completed.
Parameters:
list: A list of MediaItem objects to set as a play list.
Returns:
a which represents the pending completion of the command.
See also: SessionPlayer.PlayerCallback.onPlaylistChanged(SessionPlayer, List, MediaMetadata)
public abstract <any>
addPlaylistItem(int index,
MediaItem item)
Adds the media item to the playlist at position index. Index equals or greater than
the current playlist size (e.g. MAX_VALUE
) will add the item at the end of
the playlist.
The implementation may not change the currently playing media item.
If index is less than or equal to the current index of the playlist,
the current index of the playlist will be increased correspondingly.
The implementation must notify registered callbacks with
SessionPlayer.PlayerCallback.onPlaylistChanged(SessionPlayer, List, MediaMetadata) when it's
completed.
Parameters:
index: the index of the item you want to add in the playlist
item: the media item you want to add
See also: SessionPlayer.PlayerCallback.onPlaylistChanged(SessionPlayer, List, MediaMetadata)
public abstract <any>
removePlaylistItem(int index)
Removes the media item from the playlist
The implementation may not change the currently playing media item even when it's removed.
The implementation must notify registered callbacks with
SessionPlayer.PlayerCallback.onPlaylistChanged(SessionPlayer, List, MediaMetadata) when it's
completed.
Parameters:
index: the index of the item you want to remove in the playlist
See also: SessionPlayer.PlayerCallback.onPlaylistChanged(SessionPlayer, List, MediaMetadata)
public abstract <any>
replacePlaylistItem(int index,
MediaItem item)
Replaces the media item at index in the playlist. This can be also used to update metadata of
an item.
The implementation must notify registered callbacks with
SessionPlayer.PlayerCallback.onPlaylistChanged(SessionPlayer, List, MediaMetadata) when it's
completed.
Parameters:
index: the index of the item to replace in the playlist
item: the new item
See also: SessionPlayer.PlayerCallback.onPlaylistChanged(SessionPlayer, List, MediaMetadata)
public abstract <any>
skipToPreviousPlaylistItem()
Skips to the previous item in the playlist.
The implementation must notify registered callbacks with
SessionPlayer.PlayerCallback.onCurrentMediaItemChanged(SessionPlayer, MediaItem) when it's
completed.
See also: SessionPlayer.PlayerCallback.onCurrentMediaItemChanged(SessionPlayer, MediaItem)
public abstract <any>
skipToNextPlaylistItem()
Skips to the next item in the playlist.
The implementation must notify registered callbacks with
SessionPlayer.PlayerCallback.onCurrentMediaItemChanged(SessionPlayer, MediaItem) when it's
completed.
See also: SessionPlayer.PlayerCallback.onCurrentMediaItemChanged(SessionPlayer, MediaItem)
public abstract <any>
skipToPlaylistItem(int index)
Skips to the the media item.
The implementation must notify registered callbacks with
SessionPlayer.PlayerCallback.onCurrentMediaItemChanged(SessionPlayer, MediaItem) when it's
completed.
Parameters:
index: The index of the item you want to play in the playlist
See also: SessionPlayer.PlayerCallback.onCurrentMediaItemChanged(SessionPlayer, MediaItem)
public abstract <any>
updatePlaylistMetadata(
MediaMetadata metadata)
Updates the playlist metadata while keeping the playlist as-is.
The implementation must notify registered callbacks with
SessionPlayer.PlayerCallback.onPlaylistMetadataChanged(SessionPlayer, MediaMetadata) when it's
completed.
Parameters:
metadata: metadata of the playlist
See also: SessionPlayer.PlayerCallback.onPlaylistMetadataChanged(SessionPlayer, MediaMetadata)
public abstract <any>
setRepeatMode(int repeatMode)
Sets the repeat mode.
The implementation must notify registered callbacks with
SessionPlayer.PlayerCallback.onRepeatModeChanged(SessionPlayer, int) when it's completed.
Parameters:
repeatMode: repeat mode
See also: SessionPlayer.REPEAT_MODE_NONE, SessionPlayer.REPEAT_MODE_ONE, SessionPlayer.REPEAT_MODE_ALL, SessionPlayer.REPEAT_MODE_GROUP, SessionPlayer.PlayerCallback.onRepeatModeChanged(SessionPlayer, int)
public abstract <any>
setShuffleMode(int shuffleMode)
Sets the shuffle mode.
The implementation must notify registered callbacks with
SessionPlayer.PlayerCallback.onShuffleModeChanged(SessionPlayer, int) when it's completed.
Parameters:
shuffleMode: The shuffle mode
See also: SessionPlayer.SHUFFLE_MODE_NONE, SessionPlayer.SHUFFLE_MODE_ALL, SessionPlayer.SHUFFLE_MODE_GROUP, SessionPlayer.PlayerCallback.onShuffleModeChanged(SessionPlayer, int)
public abstract java.util.List<MediaItem>
getPlaylist()
Gets the playlist.
Returns:
playlist, or null if none is set.
See also: SessionPlayer.PlayerCallback.onPlaylistChanged(SessionPlayer, List, MediaMetadata)
Gets the playlist metadata.
Returns:
metadata metadata of the playlist, or null if none is set
See also: SessionPlayer.PlayerCallback.onPlaylistChanged(SessionPlayer, List, MediaMetadata), SessionPlayer.PlayerCallback.onPlaylistMetadataChanged(SessionPlayer, MediaMetadata)
public abstract int
getRepeatMode()
Gets the repeat mode.
Returns:
repeat mode
See also: SessionPlayer.REPEAT_MODE_NONE, SessionPlayer.REPEAT_MODE_ONE, SessionPlayer.REPEAT_MODE_ALL, SessionPlayer.REPEAT_MODE_GROUP, SessionPlayer.PlayerCallback.onRepeatModeChanged(SessionPlayer, int)
public abstract int
getShuffleMode()
Gets the shuffle mode.
Returns:
The shuffle mode
See also: SessionPlayer.SHUFFLE_MODE_NONE, SessionPlayer.SHUFFLE_MODE_ALL, SessionPlayer.SHUFFLE_MODE_GROUP, SessionPlayer.PlayerCallback.onShuffleModeChanged(SessionPlayer, int)
Source
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media2.widget;
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
import static androidx.media2.SessionPlayer.PlayerResult.RESULT_CODE_BAD_VALUE;
import static androidx.media2.SessionPlayer.PlayerResult.RESULT_CODE_INVALID_STATE;
import static androidx.media2.SessionPlayer.PlayerResult.RESULT_CODE_SUCCESS;
import static androidx.media2.SessionPlayer.PlayerResult.RESULT_CODE_UNKNOWN_ERROR;
import android.content.Context;
import android.os.Bundle;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.concurrent.futures.ResolvableFuture;
import androidx.core.util.Pair;
import androidx.media.AudioAttributesCompat;
import androidx.media2.MediaItem;
import androidx.media2.MediaMetadata;
import androidx.media2.RemoteSessionPlayer;
import androidx.media2.SessionPlayer;
import androidx.media2.UriMediaItem;
import androidx.mediarouter.media.MediaItemStatus;
import androidx.mediarouter.media.MediaRouteSelector;
import androidx.mediarouter.media.MediaRouter;
import androidx.mediarouter.media.MediaSessionStatus;
import androidx.mediarouter.media.RemotePlaybackClient;
import androidx.mediarouter.media.RemotePlaybackClient.ItemActionCallback;
import androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback;
import androidx.mediarouter.media.RemotePlaybackClient.StatusCallback;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
/**
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
@RequiresApi(19)
public class RoutePlayer extends RemoteSessionPlayer {
private static final String TAG = "RoutePlayer";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final int ITEM_NONE = -1;
String mItemId;
int mCurrentPlayerState;
long mDuration;
long mLastStatusChangedTime;
long mPosition;
boolean mCanResume;
@SuppressWarnings("WeakerAccess") /* synthetic access */
MediaRouter.RouteInfo mSelectedRoute;
@SuppressWarnings("WeakerAccess") /* synthetic access */
final List<ResolvableFuture<PlayerResult>> mPendingVolumeResult = new ArrayList<>();
private MediaItem mItem;
private MediaRouter mMediaRouter;
private RemotePlaybackClient mClient;
private MediaRouter.Callback mRouterCallback = new MediaRouter.Callback() {
@Override
public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo route) {
if (TextUtils.equals(route.getId(), mSelectedRoute.getId())) {
final int volume = route.getVolume();
for (int i = 0; i < mPendingVolumeResult.size(); i++) {
mPendingVolumeResult.get(i).set(new PlayerResult(
RESULT_CODE_SUCCESS, getCurrentMediaItem()));
}
mPendingVolumeResult.clear();
List<Pair<PlayerCallback, Executor>> callbacks = getCallbacks();
for (Pair<PlayerCallback, Executor> pair : callbacks) {
if (pair.first instanceof RemoteSessionPlayer.Callback) {
final RemoteSessionPlayer.PlayerCallback callback = pair.first;
pair.second.execute(new Runnable() {
@Override
public void run() {
((RemoteSessionPlayer.Callback) callback)
.onVolumeChanged(RoutePlayer.this, volume);
}
});
}
}
}
}
};
private StatusCallback mStatusCallback = new StatusCallback() {
@Override
public void onItemStatusChanged(Bundle data,
String sessionId, MediaSessionStatus sessionStatus,
String itemId, MediaItemStatus itemStatus) {
if (DEBUG && !isSessionActive(sessionStatus)) {
Log.v(TAG, "onItemStatusChanged() is called, but session is not active.");
}
mLastStatusChangedTime = SystemClock.elapsedRealtime();
mPosition = itemStatus.getContentPosition();
mCurrentPlayerState = convertPlaybackStateToPlayerState(itemStatus.getPlaybackState());
List<Pair<PlayerCallback, Executor>> callbacks = getCallbacks();
for (Pair<PlayerCallback, Executor> pair : callbacks) {
final PlayerCallback callback = pair.first;
pair.second.execute(new Runnable() {
@Override
public void run() {
callback.onPlayerStateChanged(RoutePlayer.this, mCurrentPlayerState);
}
});
}
}
};
public RoutePlayer(Context context, MediaRouteSelector selector,
MediaRouter.RouteInfo route) {
mMediaRouter = MediaRouter.getInstance(context);
mMediaRouter.addCallback(selector, mRouterCallback);
mSelectedRoute = route;
mClient = new RemotePlaybackClient(context, route);
mClient.setStatusCallback(mStatusCallback);
if (mClient.isSessionManagementSupported()) {
mClient.startSession(null, new SessionActionCallback() {
@Override
public void onResult(Bundle data,
String sessionId, MediaSessionStatus sessionStatus) {
if (DEBUG && !isSessionActive(sessionStatus)) {
Log.v(TAG, "RoutePlayer has been initialized, but session is not"
+ "active.");
}
}
});
}
}
@Override
public ListenableFuture<PlayerResult> play() {
if (mItem == null) {
return createResult(RESULT_CODE_BAD_VALUE);
}
// RemotePlaybackClient cannot call resume(..) without calling pause(..) first.
if (!mCanResume) {
return playInternal();
}
if (mClient.isSessionManagementSupported()) {
final ResolvableFuture<PlayerResult> result = ResolvableFuture.create();
mClient.resume(null, new SessionActionCallback() {
@Override
public void onResult(Bundle data,
String sessionId, MediaSessionStatus sessionStatus) {
if (DEBUG && !isSessionActive(sessionStatus)) {
Log.v(TAG, "play() is called, but session is not active.");
}
// Do nothing since this returns the buffering state--
// StatusCallback#onItemStatusChanged is called when the session reaches the
// play state.
result.set(new PlayerResult(RESULT_CODE_SUCCESS, getCurrentMediaItem()));
}
});
}
return createResult(RESULT_CODE_INVALID_STATE);
}
@Override
public ListenableFuture<PlayerResult> prepare() {
return createResult();
}
@Override
public ListenableFuture<PlayerResult> pause() {
if (mClient.isSessionManagementSupported()) {
final ResolvableFuture<PlayerResult> result = ResolvableFuture.create();
mClient.pause(null, new SessionActionCallback() {
@Override
public void onResult(Bundle data,
String sessionId, MediaSessionStatus sessionStatus) {
if (DEBUG && !isSessionActive(sessionStatus)) {
Log.v(TAG, "pause() is called, but session is not active.");
}
mCanResume = true;
// Do not update playback state here since this returns the buffering state--
// StatusCallback#onItemStatusChanged is called when the session reaches the
// pause state.
result.set(new PlayerResult(RESULT_CODE_SUCCESS, getCurrentMediaItem()));
}
});
}
return createResult(RESULT_CODE_INVALID_STATE);
}
@Override
public ListenableFuture<PlayerResult> seekTo(long pos) {
if (mClient.isSessionManagementSupported()) {
final ResolvableFuture<PlayerResult> result = ResolvableFuture.create();
mClient.seek(mItemId, pos, null, new ItemActionCallback() {
@Override
public void onResult(Bundle data,
String sessionId, MediaSessionStatus sessionStatus,
String itemId, final MediaItemStatus itemStatus) {
if (DEBUG && !isSessionActive(sessionStatus)) {
Log.v(TAG, "seekTo(long) is called, but session is not active.");
}
if (itemStatus != null) {
List<Pair<PlayerCallback, Executor>> callbacks = getCallbacks();
for (Pair<PlayerCallback, Executor> pair : callbacks) {
final PlayerCallback callback = pair.first;
pair.second.execute(new Runnable() {
@Override
public void run() {
callback.onSeekCompleted(RoutePlayer.this,
itemStatus.getContentPosition());
}
});
}
} else {
result.set(new PlayerResult(RESULT_CODE_UNKNOWN_ERROR,
getCurrentMediaItem()));
}
}
});
}
return createResult(RESULT_CODE_INVALID_STATE);
}
@Override
public long getCurrentPosition() {
long expectedPosition = mPosition;
if (mCurrentPlayerState == PLAYER_STATE_PLAYING) {
expectedPosition = mPosition + (SystemClock.elapsedRealtime() - mLastStatusChangedTime);
}
return expectedPosition;
}
@Override
public long getDuration() {
return mDuration;
}
@Override
public long getBufferedPosition() {
return 0;
}
@Override
public int getPlayerState() {
return mCurrentPlayerState;
}
@Override
public int getBufferingState() {
return SessionPlayer.BUFFERING_STATE_UNKNOWN;
}
@Override
public ListenableFuture<PlayerResult> setAudioAttributes(AudioAttributesCompat attributes) {
// TODO: implement
return createResult(RESULT_CODE_INVALID_STATE);
}
@Override
public AudioAttributesCompat getAudioAttributes() {
return null;
}
@Override
public ListenableFuture<PlayerResult> setMediaItem(MediaItem item) {
mItem = item;
return createResult();
}
@Override
public MediaItem getCurrentMediaItem() {
return mItem;
}
@Override
public int getCurrentMediaItemIndex() {
return ITEM_NONE;
}
@Override
public int getPreviousMediaItemIndex() {
return ITEM_NONE;
}
@Override
public int getNextMediaItemIndex() {
return ITEM_NONE;
}
@Override
public ListenableFuture<PlayerResult> setPlaybackSpeed(float speed) {
// Do nothing
return createResult(RESULT_CODE_INVALID_STATE);
}
@Override
public float getPlaybackSpeed() {
return 1.0f;
}
@Override
public int getVolume() {
return mSelectedRoute.getVolume();
}
@Override
public Future<PlayerResult> adjustVolume(int direction) {
mSelectedRoute.requestUpdateVolume(direction);
ResolvableFuture<PlayerResult> result = ResolvableFuture.create();
mPendingVolumeResult.add(result);
return result;
}
@Override
public Future<PlayerResult> setVolume(int volume) {
mSelectedRoute.requestSetVolume(volume);
ResolvableFuture<PlayerResult> result = ResolvableFuture.create();
mPendingVolumeResult.add(result);
return result;
}
@Override
public int getMaxVolume() {
return mSelectedRoute.getVolumeMax();
}
@Override
public int getVolumeControlType() {
return mSelectedRoute.getVolumeHandling();
}
@Override
public ListenableFuture<PlayerResult> setPlaylist(List<MediaItem> list,
MediaMetadata metadata) {
// TODO: implement
return createResult(RESULT_CODE_INVALID_STATE);
}
@Override
public ListenableFuture<PlayerResult> addPlaylistItem(int index, MediaItem item) {
// TODO: implement
return createResult(RESULT_CODE_INVALID_STATE);
}
@Override
public ListenableFuture<PlayerResult> removePlaylistItem(int index) {
// TODO: implement
return createResult(RESULT_CODE_INVALID_STATE);
}
@Override
public ListenableFuture<PlayerResult> replacePlaylistItem(int index, MediaItem item) {
// TODO: implement
return createResult(RESULT_CODE_INVALID_STATE);
}
@Override
public ListenableFuture<PlayerResult> skipToPreviousPlaylistItem() {
// TODO: implement
return createResult(RESULT_CODE_INVALID_STATE);
}
@Override
public ListenableFuture<PlayerResult> skipToNextPlaylistItem() {
// TODO: implement
return createResult(RESULT_CODE_INVALID_STATE);
}
@Override
public ListenableFuture<PlayerResult> skipToPlaylistItem(int index) {
// TODO: implement
return createResult(RESULT_CODE_INVALID_STATE);
}
@Override
public ListenableFuture<PlayerResult> updatePlaylistMetadata(MediaMetadata metadata) {
// TODO: implement
return createResult(RESULT_CODE_INVALID_STATE);
}
@Override
public ListenableFuture<PlayerResult> setRepeatMode(int repeatMode) {
// TODO: implement
return createResult(RESULT_CODE_INVALID_STATE);
}
@Override
public ListenableFuture<PlayerResult> setShuffleMode(int shuffleMode) {
// TODO: implement
return createResult(RESULT_CODE_INVALID_STATE);
}
@Override
public List<MediaItem> getPlaylist() {
List<MediaItem> list = new ArrayList<>();
list.add(mItem);
return list;
}
@Override
public MediaMetadata getPlaylistMetadata() {
return null;
}
@Override
public int getRepeatMode() {
return SessionPlayer.REPEAT_MODE_NONE;
}
@Override
public int getShuffleMode() {
return SessionPlayer.SHUFFLE_MODE_NONE;
}
@Override
public void close() {
if (mClient != null) {
try {
mClient.release();
} catch (IllegalArgumentException e) {
Log.d(TAG, "Receiver not registered");
}
mClient = null;
}
mMediaRouter.removeCallback(mRouterCallback);
}
void setCurrentPosition(long position) {
mPosition = position;
}
boolean isSessionActive(MediaSessionStatus status) {
if (status == null || status.getSessionState() == MediaSessionStatus.SESSION_STATE_ENDED
|| status.getSessionState() == MediaSessionStatus.SESSION_STATE_INVALIDATED) {
return false;
}
return true;
}
int convertPlaybackStateToPlayerState(int playbackState) {
int playerState = PLAYER_STATE_IDLE;
switch (playbackState) {
case MediaItemStatus.PLAYBACK_STATE_PENDING:
case MediaItemStatus.PLAYBACK_STATE_FINISHED:
case MediaItemStatus.PLAYBACK_STATE_CANCELED:
playerState = PLAYER_STATE_IDLE;
break;
case MediaItemStatus.PLAYBACK_STATE_PLAYING:
playerState = PLAYER_STATE_PLAYING;
break;
case MediaItemStatus.PLAYBACK_STATE_PAUSED:
case MediaItemStatus.PLAYBACK_STATE_BUFFERING:
playerState = PLAYER_STATE_PAUSED;
break;
case MediaItemStatus.PLAYBACK_STATE_INVALIDATED:
case MediaItemStatus.PLAYBACK_STATE_ERROR:
playerState = PLAYER_STATE_ERROR;
break;
}
return playerState;
}
private ListenableFuture<PlayerResult> playInternal() {
if (!(mItem instanceof UriMediaItem)) {
Log.w(TAG, "Data source type is not Uri." + mItem);
return createResult(RESULT_CODE_BAD_VALUE);
}
final ResolvableFuture<PlayerResult> result = ResolvableFuture.create();
mClient.play(((UriMediaItem) mItem).getUri(), "video/mp4", null, mPosition, null,
new ItemActionCallback() {
@Override
public void onResult(Bundle data, String sessionId,
MediaSessionStatus sessionStatus,
String itemId, MediaItemStatus itemStatus) {
if (DEBUG && !isSessionActive(sessionStatus)) {
Log.v(TAG, "play() is called, but session is not active.");
}
mItemId = itemId;
if (itemStatus != null) {
mDuration = itemStatus.getContentDuration();
}
// Do not update playback state here since this returns the buffering state.
// StatusCallback#onItemStatusChanged is called when the session reaches the
// play state.
result.set(new PlayerResult(RESULT_CODE_SUCCESS, getCurrentMediaItem()));
}
});
return result;
}
private ListenableFuture<PlayerResult> createResult() {
return createResult(RESULT_CODE_SUCCESS);
}
private ListenableFuture<PlayerResult> createResult(int code) {
ResolvableFuture<PlayerResult> result = ResolvableFuture.create();
result.set(new PlayerResult(code, getCurrentMediaItem()));
return result;
}
}