Add separate interface RatingCallback to handle user ratings.

To support Google Assistant media apps need to support the action
ACTION_SET_RATING. Before this change developers have to use a QueueEditor for
this which does not have any other mandatory actions required for Assistant.
With this change developers can implement the rating action with the
PlaybackPreparer which they need to implement anyway to support Assistant.

https://developer.android.com/guide/topics/media-apps/interacting-with-assistant.html#transport_controls

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=188056722
This commit is contained in:
bachinger 2018-03-06 11:52:10 -08:00 committed by Oliver Woodman
parent b7c9912a3d
commit ae421bb50c
2 changed files with 48 additions and 51 deletions

View File

@ -105,23 +105,24 @@ public final class MediaSessionConnector {
*/ */
public interface PlaybackPreparer extends CommandReceiver { public interface PlaybackPreparer extends CommandReceiver {
long ACTIONS = PlaybackStateCompat.ACTION_PREPARE long ACTIONS =
| PlaybackStateCompat.ACTION_PREPARE_FROM_MEDIA_ID PlaybackStateCompat.ACTION_PREPARE
| PlaybackStateCompat.ACTION_PREPARE_FROM_SEARCH | PlaybackStateCompat.ACTION_PREPARE_FROM_MEDIA_ID
| PlaybackStateCompat.ACTION_PREPARE_FROM_URI | PlaybackStateCompat.ACTION_PREPARE_FROM_SEARCH
| PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID | PlaybackStateCompat.ACTION_PREPARE_FROM_URI
| PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH | PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID
| PlaybackStateCompat.ACTION_PLAY_FROM_URI; | PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH
| PlaybackStateCompat.ACTION_PLAY_FROM_URI;
/** /**
* Returns the actions which are supported by the preparer. The supported actions must be a * Returns the actions which are supported by the preparer. The supported actions must be a
* bitmask combined out of {@link PlaybackStateCompat#ACTION_PREPARE}, * bitmask combined out of {@link PlaybackStateCompat#ACTION_PREPARE}, {@link
* {@link PlaybackStateCompat#ACTION_PREPARE_FROM_MEDIA_ID}, * PlaybackStateCompat#ACTION_PREPARE_FROM_MEDIA_ID}, {@link
* {@link PlaybackStateCompat#ACTION_PREPARE_FROM_SEARCH}, * PlaybackStateCompat#ACTION_PREPARE_FROM_SEARCH}, {@link
* {@link PlaybackStateCompat#ACTION_PREPARE_FROM_URI}, * PlaybackStateCompat#ACTION_PREPARE_FROM_URI}, {@link
* {@link PlaybackStateCompat#ACTION_PLAY_FROM_MEDIA_ID}, * PlaybackStateCompat#ACTION_PLAY_FROM_MEDIA_ID}, {@link
* {@link PlaybackStateCompat#ACTION_PLAY_FROM_SEARCH} and * PlaybackStateCompat#ACTION_PLAY_FROM_SEARCH} and {@link
* {@link PlaybackStateCompat#ACTION_PLAY_FROM_URI}. * PlaybackStateCompat#ACTION_PLAY_FROM_URI}.
* *
* @return The bitmask of the supported media actions. * @return The bitmask of the supported media actions.
*/ */
@ -264,15 +265,6 @@ public final class MediaSessionConnector {
*/ */
public interface QueueEditor extends CommandReceiver { public interface QueueEditor extends CommandReceiver {
long ACTIONS = PlaybackStateCompat.ACTION_SET_RATING;
/**
* Returns {@link PlaybackStateCompat#ACTION_SET_RATING} or {@code 0}. The Media API does
* not declare action constants for adding and removing queue items.
*
* @param player The {@link Player}.
*/
long getSupportedQueueEditorActions(@Nullable Player player);
/** /**
* See {@link MediaSessionCompat.Callback#onAddQueueItem(MediaDescriptionCompat description)}. * See {@link MediaSessionCompat.Callback#onAddQueueItem(MediaDescriptionCompat description)}.
*/ */
@ -291,9 +283,14 @@ public final class MediaSessionConnector {
* 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);
/** }
* See {@link MediaSessionCompat.Callback#onSetRating(RatingCompat)}.
*/ /** Callback receiving a user rating for the active media item. */
public interface RatingCallback extends CommandReceiver {
long ACTIONS = PlaybackStateCompat.ACTION_SET_RATING;
/** See {@link MediaSessionCompat.Callback#onSetRating(RatingCompat)}. */
void onSetRating(Player player, RatingCompat rating); void onSetRating(Player player, RatingCompat rating);
} }
@ -341,6 +338,7 @@ public final class MediaSessionConnector {
private PlaybackPreparer playbackPreparer; private PlaybackPreparer playbackPreparer;
private QueueNavigator queueNavigator; private QueueNavigator queueNavigator;
private QueueEditor queueEditor; private QueueEditor queueEditor;
private RatingCallback ratingCallback;
private ExoPlaybackException playbackException; private ExoPlaybackException playbackException;
/** /**
@ -471,6 +469,17 @@ public final class MediaSessionConnector {
: EDITOR_MEDIA_SESSION_FLAGS); : EDITOR_MEDIA_SESSION_FLAGS);
} }
/**
* Sets the {@link RatingCallback} to handle user ratings.
*
* @param ratingCallback The rating callback.
*/
public void setRatingCallback(RatingCallback ratingCallback) {
unregisterCommandReceiver(this.ratingCallback);
this.ratingCallback = ratingCallback;
registerCommandReceiver(this.ratingCallback);
}
private void registerCommandReceiver(CommandReceiver commandReceiver) { private void registerCommandReceiver(CommandReceiver commandReceiver) {
if (commandReceiver != null && commandReceiver.getCommands() != null) { if (commandReceiver != null && commandReceiver.getCommands() != null) {
for (String command : commandReceiver.getCommands()) { for (String command : commandReceiver.getCommands()) {
@ -539,8 +548,8 @@ public final class MediaSessionConnector {
actions |= (QueueNavigator.ACTIONS & queueNavigator.getSupportedQueueNavigatorActions( actions |= (QueueNavigator.ACTIONS & queueNavigator.getSupportedQueueNavigatorActions(
player)); player));
} }
if (queueEditor != null) { if (ratingCallback != null) {
actions |= (QueueEditor.ACTIONS & queueEditor.getSupportedQueueEditorActions(player)); actions |= RatingCallback.ACTIONS;
} }
return actions; return actions;
} }
@ -634,6 +643,10 @@ public final class MediaSessionConnector {
& PlaybackPreparer.ACTIONS & action) != 0; & PlaybackPreparer.ACTIONS & action) != 0;
} }
private boolean canDispatchToRatingCallback(long action) {
return ratingCallback != null && (RatingCallback.ACTIONS & action) != 0;
}
private boolean canDispatchToPlaybackController(long action) { private boolean canDispatchToPlaybackController(long action) {
return (playbackController.getSupportedPlaybackActions(player) return (playbackController.getSupportedPlaybackActions(player)
& PlaybackController.ACTIONS & action) != 0; & PlaybackController.ACTIONS & action) != 0;
@ -644,11 +657,6 @@ public final class MediaSessionConnector {
& QueueNavigator.ACTIONS & action) != 0; & QueueNavigator.ACTIONS & action) != 0;
} }
private boolean canDispatchToQueueEditor(long action) {
return queueEditor != null && (queueEditor.getSupportedQueueEditorActions(player)
& QueueEditor.ACTIONS & action) != 0;
}
private class ExoPlayerEventListener extends Player.DefaultEventListener { private class ExoPlayerEventListener extends Player.DefaultEventListener {
private int currentWindowIndex; private int currentWindowIndex;
@ -879,6 +887,13 @@ public final class MediaSessionConnector {
} }
} }
@Override
public void onSetRating(RatingCompat rating) {
if (canDispatchToRatingCallback(PlaybackStateCompat.ACTION_SET_RATING)) {
ratingCallback.onSetRating(player, rating);
}
}
@Override @Override
public void onAddQueueItem(MediaDescriptionCompat description) { public void onAddQueueItem(MediaDescriptionCompat description) {
if (queueEditor != null) { if (queueEditor != null) {
@ -907,13 +922,6 @@ public final class MediaSessionConnector {
} }
} }
@Override
public void onSetRating(RatingCompat rating) {
if (canDispatchToQueueEditor(PlaybackStateCompat.ACTION_SET_RATING)) {
queueEditor.onSetRating(player, rating);
}
}
} }
} }

View File

@ -20,7 +20,6 @@ import android.os.ResultReceiver;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.media.MediaDescriptionCompat; import android.support.v4.media.MediaDescriptionCompat;
import android.support.v4.media.RatingCompat;
import android.support.v4.media.session.MediaControllerCompat; import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.MediaSessionCompat;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
@ -166,11 +165,6 @@ public final class TimelineQueueEditor
this.equalityChecker = equalityChecker; this.equalityChecker = equalityChecker;
} }
@Override
public long getSupportedQueueEditorActions(@Nullable Player player) {
return 0;
}
@Override @Override
public void onAddQueueItem(Player player, MediaDescriptionCompat description) { public void onAddQueueItem(Player player, MediaDescriptionCompat description) {
onAddQueueItem(player, description, player.getCurrentTimeline().getWindowCount()); onAddQueueItem(player, description, player.getCurrentTimeline().getWindowCount());
@ -202,11 +196,6 @@ public final class TimelineQueueEditor
queueMediaSource.removeMediaSource(index); queueMediaSource.removeMediaSource(index);
} }
@Override
public void onSetRating(Player player, RatingCompat rating) {
// Do nothing.
}
// CommandReceiver implementation. // CommandReceiver implementation.
@NonNull @NonNull