use of androidx.media3.common.Player.Commands in project media by androidx.
the class ConnectedControllersManager method addController.
public void addController(T controllerKey, ControllerInfo controllerInfo, SessionCommands sessionCommands, Player.Commands playerCommands) {
synchronized (lock) {
@Nullable ControllerInfo savedInfo = getController(controllerKey);
if (savedInfo == null) {
controllerInfoMap.put(controllerKey, controllerInfo);
controllerRecords.put(controllerInfo, new ConnectedControllerRecord<>(controllerKey, new SequencedFutureManager(), sessionCommands, playerCommands));
} else {
// already exist. Only update allowed commands.
ConnectedControllerRecord<T> record = checkStateNotNull(controllerRecords.get(savedInfo));
record.sessionCommands = sessionCommands;
record.playerCommands = playerCommands;
}
}
}
use of androidx.media3.common.Player.Commands in project media by androidx.
the class DefaultMediaNotificationProvider method createNotification.
@Override
public MediaNotification createNotification(MediaController mediaController, MediaNotification.ActionFactory actionFactory, Callback onNotificationChangedCallback) {
ensureNotificationChannel();
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
// TODO(b/193193926): Filter actions depending on the player's available commands.
// Skip to previous action.
builder.addAction(actionFactory.createMediaAction(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.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(actionFactory.createMediaAction(IconCompat.createWithResource(context, R.drawable.media3_notification_seek_to_next), context.getString(R.string.media3_controls_seek_to_next_description), MediaNotification.ActionFactory.COMMAND_SKIP_TO_NEXT));
// Set metadata info in the notification.
MediaMetadata metadata = mediaController.getMediaMetadata();
builder.setContentTitle(metadata.title).setContentText(metadata.artist);
if (metadata.artworkData != null) {
Bitmap artworkBitmap = BitmapFactory.decodeByteArray(metadata.artworkData, 0, metadata.artworkData.length);
builder.setLargeIcon(artworkBitmap);
}
androidx.media.app.NotificationCompat.MediaStyle mediaStyle = new androidx.media.app.NotificationCompat.MediaStyle().setCancelButtonIntent(actionFactory.createMediaActionPendingIntent(MediaNotification.ActionFactory.COMMAND_STOP)).setShowActionsInCompactView(1);
Notification notification = builder.setContentIntent(mediaController.getSessionActivity()).setDeleteIntent(actionFactory.createMediaActionPendingIntent(MediaNotification.ActionFactory.COMMAND_STOP)).setOnlyAlertOnce(true).setSmallIcon(getSmallIconResId(context)).setStyle(mediaStyle).setVisibility(NotificationCompat.VISIBILITY_PUBLIC).setOngoing(false).build();
return new MediaNotification(NOTIFICATION_ID, notification);
}
use of androidx.media3.common.Player.Commands in project media by androidx.
the class MediaControllerImplBase method onAvailableCommandsChangedFromSession.
void onAvailableCommandsChangedFromSession(SessionCommands sessionCommands, Commands playerCommands) {
if (!isConnected()) {
return;
}
boolean playerCommandsChanged = !Util.areEqual(playerCommandsFromSession, playerCommands);
boolean sessionCommandsChanged = !Util.areEqual(this.sessionCommands, sessionCommands);
if (!playerCommandsChanged && !sessionCommandsChanged) {
return;
}
boolean intersectedPlayerCommandsChanged = false;
if (playerCommandsChanged) {
playerCommandsFromSession = playerCommands;
Commands prevIntersectedPlayerCommands = intersectedPlayerCommands;
intersectedPlayerCommands = intersect(playerCommandsFromSession, playerCommandsFromPlayer);
intersectedPlayerCommandsChanged = !Util.areEqual(intersectedPlayerCommands, prevIntersectedPlayerCommands);
}
if (sessionCommandsChanged) {
this.sessionCommands = sessionCommands;
}
if (intersectedPlayerCommandsChanged) {
listeners.sendEvent(EVENT_AVAILABLE_COMMANDS_CHANGED, listener -> listener.onAvailableCommandsChanged(intersectedPlayerCommands));
}
if (sessionCommandsChanged) {
instance.notifyControllerListener(listener -> listener.onAvailableSessionCommandsChanged(instance, sessionCommands));
}
}
use of androidx.media3.common.Player.Commands in project media by androidx.
the class MediaControllerListenerTest method onTimelineChanged_emptyMediaItemAndMediaMetadata_whenCommandUnavailableFromPlayer.
@Test
public void onTimelineChanged_emptyMediaItemAndMediaMetadata_whenCommandUnavailableFromPlayer() throws Exception {
int testMediaItemsSize = 2;
List<MediaItem> testMediaItemList = MediaTestUtils.createMediaItems(testMediaItemsSize);
Timeline testTimeline = new PlaylistTimeline(testMediaItemList);
Bundle playerConfig = new RemoteMediaSession.MockPlayerConfigBuilder().setTimeline(testTimeline).build();
remoteSession.setPlayer(playerConfig);
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<Timeline> timelineFromParamRef = new AtomicReference<>();
AtomicReference<Timeline> timelineFromGetterRef = new AtomicReference<>();
AtomicReference<MediaMetadata> metadataFromGetterRef = new AtomicReference<>();
AtomicReference<MediaItem> currentMediaItemGetterRef = new AtomicReference<>();
Player.Listener listener = new Player.Listener() {
@Override
public void onTimelineChanged(Timeline timeline, int reason) {
timelineFromParamRef.set(timeline);
timelineFromGetterRef.set(controller.getCurrentTimeline());
metadataFromGetterRef.set(controller.getMediaMetadata());
currentMediaItemGetterRef.set(controller.getCurrentMediaItem());
latch.countDown();
}
};
controller.addListener(listener);
Commands commandsWithoutGetTimeline = createPlayerCommandsWithout(Player.COMMAND_GET_TIMELINE);
remoteSession.getMockPlayer().notifyAvailableCommandsChanged(commandsWithoutGetTimeline);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(timelineFromParamRef.get().getWindowCount()).isEqualTo(testMediaItemsSize);
for (int i = 0; i < timelineFromParamRef.get().getWindowCount(); i++) {
assertThat(timelineFromParamRef.get().getWindow(/* windowIndex= */
i, new Timeline.Window()).mediaItem).isEqualTo(MediaItem.EMPTY);
}
assertThat(timelineFromGetterRef.get().getWindowCount()).isEqualTo(testMediaItemsSize);
for (int i = 0; i < timelineFromGetterRef.get().getWindowCount(); i++) {
assertThat(timelineFromGetterRef.get().getWindow(/* windowIndex= */
i, new Timeline.Window()).mediaItem).isEqualTo(MediaItem.EMPTY);
}
assertThat(metadataFromGetterRef.get()).isEqualTo(MediaMetadata.EMPTY);
assertThat(currentMediaItemGetterRef.get()).isEqualTo(MediaItem.EMPTY);
}
Aggregations