Start playback from notification

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
(cherry picked from commit 1023b9d55efe8f0470c5f3b75cd84e40860f79be)
This commit is contained in:
christosts 2022-03-04 17:52:46 +00:00 committed by Ian Baker
parent 4456a865cc
commit c56c6a2ea4
5 changed files with 50 additions and 13 deletions

View File

@ -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
@ -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),

View File

@ -96,7 +96,6 @@ class PlaybackService : MediaLibraryService() {
val item = MediaItemTree.getItemFromTitle(mediaTitle) ?: MediaItemTree.getRandomItem()
player.setMediaItem(item)
player.prepare()
}
override fun onSetMediaUri(

View File

@ -27,6 +27,7 @@ import android.os.Bundle;
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.UnstableApi;
import androidx.media3.common.util.Util;
@ -93,20 +94,21 @@ import androidx.media3.common.util.Util;
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(

View File

@ -196,7 +196,9 @@ import java.util.concurrent.TimeoutException;
@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);
}
}

View File

@ -28,6 +28,8 @@ import static androidx.media3.common.Player.COMMAND_SET_REPEAT_MODE;
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;
@ -231,7 +233,17 @@ import org.checkerframework.checker.initialization.qual.Initialized;
} 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);
}
}
@ -285,7 +297,17 @@ import org.checkerframework.checker.initialization.qual.Initialized;
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());
}
@ -321,7 +343,15 @@ import org.checkerframework.checker.initialization.qual.Initialized;
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();
}
});
}