Skip to content

Commit

Permalink
Start playback from notification
Browse files Browse the repository at this point in the history
This change fixes two bugs where MediaSessionServe shows a notification
with the Play icon but tapping it will not start playback:
1. After playback ends: we need to seek to the beginning of the media
   item.
2. After adding media items to the player but not starting playback:
   We need to call Player.prepare() too.

PiperOrigin-RevId: 432469953
  • Loading branch information
christosts authored and icbaker committed Mar 4, 2022
1 parent 6ae2629 commit 1023b9d
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import android.widget.ListView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.session.MediaBrowser
import androidx.media3.session.SessionToken
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
Expand Down Expand Up @@ -179,6 +180,9 @@ class PlayableFolderActivity : AppCompatActivity() {
returnConvertView.findViewById<TextView>(R.id.add_button).setOnClickListener {
val browser = this@PlayableFolderActivity.browser ?: return@setOnClickListener
browser.addMediaItem(mediaItem)
if (browser.playbackState == Player.STATE_IDLE) {
browser.prepare()
}
Snackbar.make(
findViewById<LinearLayout>(R.id.linear_layout),
getString(R.string.added_media_item_format, mediaItem.mediaMetadata.title),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ class PlaybackService : MediaLibraryService() {

val item = MediaItemTree.getItemFromTitle(mediaTitle) ?: MediaItemTree.getRandomItem()
player.setMediaItem(item)
player.prepare()
}

override fun onSetMediaUri(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import androidx.core.app.NotificationCompat;
import androidx.core.graphics.drawable.IconCompat;
import androidx.media3.common.MediaMetadata;
import androidx.media3.common.Player;
import androidx.media3.common.util.Consumer;
import androidx.media3.common.util.Log;
import androidx.media3.common.util.UnstableApi;
Expand Down Expand Up @@ -120,20 +121,21 @@ public MediaNotification createNotification(
IconCompat.createWithResource(context, R.drawable.media3_notification_seek_to_previous),
context.getString(R.string.media3_controls_seek_to_previous_description),
MediaNotification.ActionFactory.COMMAND_SKIP_TO_PREVIOUS));
if (mediaController.getPlayWhenReady()) {
// Pause action.
builder.addAction(
actionFactory.createMediaAction(
IconCompat.createWithResource(context, R.drawable.media3_notification_pause),
context.getString(R.string.media3_controls_pause_description),
MediaNotification.ActionFactory.COMMAND_PAUSE));
} else {
if (mediaController.getPlaybackState() == Player.STATE_ENDED
|| !mediaController.getPlayWhenReady()) {
// Play action.
builder.addAction(
actionFactory.createMediaAction(
IconCompat.createWithResource(context, R.drawable.media3_notification_play),
context.getString(R.string.media3_controls_play_description),
MediaNotification.ActionFactory.COMMAND_PLAY));
} else {
// Pause action.
builder.addAction(
actionFactory.createMediaAction(
IconCompat.createWithResource(context, R.drawable.media3_notification_pause),
context.getString(R.string.media3_controls_pause_description),
MediaNotification.ActionFactory.COMMAND_PAUSE));
}
// Skip to next action.
builder.addAction(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,9 @@ public void onConnected() {
@Override
public void onEvents(Player player, Player.Events events) {
if (events.containsAny(
Player.EVENT_PLAY_WHEN_READY_CHANGED, Player.EVENT_MEDIA_METADATA_CHANGED)) {
Player.EVENT_PLAYBACK_STATE_CHANGED,
Player.EVENT_PLAY_WHEN_READY_CHANGED,
Player.EVENT_MEDIA_METADATA_CHANGED)) {
updateNotification(session);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import static androidx.media3.common.Player.COMMAND_SET_SHUFFLE_MODE;
import static androidx.media3.common.Player.COMMAND_SET_SPEED_AND_PITCH;
import static androidx.media3.common.Player.COMMAND_STOP;
import static androidx.media3.common.Player.STATE_ENDED;
import static androidx.media3.common.Player.STATE_IDLE;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.common.util.Util.postOrRun;
Expand Down Expand Up @@ -231,7 +233,17 @@ private void handleMediaPlayPauseOnHandler(RemoteUserInfo remoteUserInfo) {
} else {
dispatchSessionTaskWithPlayerCommand(
COMMAND_PLAY_PAUSE,
(controller) -> sessionImpl.getPlayerWrapper().play(),
(controller) -> {
PlayerWrapper playerWrapper = sessionImpl.getPlayerWrapper();
@Player.State int playbackState = playerWrapper.getPlaybackState();
if (playbackState == STATE_IDLE) {
playerWrapper.prepare();
} else if (playbackState == STATE_ENDED) {
playerWrapper.seekTo(
playerWrapper.getCurrentMediaItemIndex(), /* positionMs= */ C.TIME_UNSET);
}
playerWrapper.play();
},
remoteUserInfo);
}
}
Expand Down Expand Up @@ -285,7 +297,17 @@ public void onPrepareFromUri(Uri mediaUri, @Nullable Bundle extras) {
public void onPlay() {
dispatchSessionTaskWithPlayerCommand(
COMMAND_PLAY_PAUSE,
controller -> sessionImpl.getPlayerWrapper().play(),
controller -> {
PlayerWrapper playerWrapper = sessionImpl.getPlayerWrapper();
@Player.State int playbackState = playerWrapper.getPlaybackState();
if (playbackState == Player.STATE_IDLE) {
playerWrapper.prepare();
} else if (playbackState == Player.STATE_ENDED) {
playerWrapper.seekTo(
playerWrapper.getCurrentMediaItemIndex(), /* positionMs= */ C.TIME_UNSET);
}
playerWrapper.play();
},
sessionCompat.getCurrentControllerInfo());
}

Expand Down Expand Up @@ -321,7 +343,15 @@ public void onPlayFromUri(Uri mediaUri, @Nullable Bundle extras) {
if (sessionImpl.onSetMediaUriOnHandler(
controller, mediaUri, extras == null ? Bundle.EMPTY : extras)
== RESULT_SUCCESS) {
sessionImpl.getPlayerWrapper().play();
PlayerWrapper playerWrapper = sessionImpl.getPlayerWrapper();
@Player.State int playbackState = playerWrapper.getPlaybackState();
if (playbackState == Player.STATE_IDLE) {
playerWrapper.prepare();
} else if (playbackState == STATE_ENDED) {
playerWrapper.seekTo(
playerWrapper.getCurrentMediaItemIndex(), /* positionMs= */ C.TIME_UNSET);
}
playerWrapper.play();
}
});
}
Expand Down

0 comments on commit 1023b9d

Please sign in to comment.