Filter media notification actions

The DefaultMediaNotificationProvider checks if a command is available
before putting the respective action in the notification.

PiperOrigin-RevId: 440114422
This commit is contained in:
christosts 2022-04-07 16:36:23 +01:00 committed by Ian Baker
parent 9a7b71b7c2
commit 43709c6211
2 changed files with 54 additions and 30 deletions

View file

@ -523,6 +523,11 @@ public interface Player {
return flags.contains(command); return flags.contains(command);
} }
/** Returns whether the set of commands contains at least one of the given {@code commands}. */
public boolean containsAny(@Command int... commands) {
return flags.containsAny(commands);
}
/** Returns the number of commands in this set. */ /** Returns the number of commands in this set. */
public int size() { public int size() {
return flags.size(); return flags.size();

View file

@ -30,6 +30,7 @@ import android.os.Looper;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
import androidx.media.app.NotificationCompat.MediaStyle;
import androidx.media3.common.MediaMetadata; import androidx.media3.common.MediaMetadata;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.util.Consumer; import androidx.media3.common.util.Consumer;
@ -114,35 +115,48 @@ public final class DefaultMediaNotificationProvider implements MediaNotification
NotificationCompat.Builder builder = NotificationCompat.Builder builder =
new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID); new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID);
// TODO(b/193193926): Filter actions depending on the player's available commands. Player.Commands availableCommands = mediaController.getAvailableCommands();
// Skip to previous action. // Skip to previous action.
builder.addAction( boolean skipToPreviousAdded = false;
actionFactory.createMediaAction( if (availableCommands.containsAny(
IconCompat.createWithResource(context, R.drawable.media3_notification_seek_to_previous), Player.COMMAND_SEEK_TO_PREVIOUS, Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)) {
context.getString(R.string.media3_controls_seek_to_previous_description), skipToPreviousAdded = true;
MediaNotification.ActionFactory.COMMAND_SKIP_TO_PREVIOUS));
if (mediaController.getPlaybackState() == Player.STATE_ENDED
|| !mediaController.getPlayWhenReady()) {
// Play action.
builder.addAction( builder.addAction(
actionFactory.createMediaAction( actionFactory.createMediaAction(
IconCompat.createWithResource(context, R.drawable.media3_notification_play), IconCompat.createWithResource(
context.getString(R.string.media3_controls_play_description), context, R.drawable.media3_notification_seek_to_previous),
MediaNotification.ActionFactory.COMMAND_PLAY)); context.getString(R.string.media3_controls_seek_to_previous_description),
} else { MediaNotification.ActionFactory.COMMAND_SKIP_TO_PREVIOUS));
// Pause action. }
builder.addAction( boolean playPauseAdded = false;
actionFactory.createMediaAction( if (availableCommands.contains(Player.COMMAND_PLAY_PAUSE)) {
IconCompat.createWithResource(context, R.drawable.media3_notification_pause), playPauseAdded = true;
context.getString(R.string.media3_controls_pause_description), if (mediaController.getPlaybackState() == Player.STATE_ENDED
MediaNotification.ActionFactory.COMMAND_PAUSE)); || !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. // Skip to next action.
builder.addAction( if (availableCommands.containsAny(
actionFactory.createMediaAction( Player.COMMAND_SEEK_TO_NEXT, Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM)) {
IconCompat.createWithResource(context, R.drawable.media3_notification_seek_to_next), builder.addAction(
context.getString(R.string.media3_controls_seek_to_next_description), actionFactory.createMediaAction(
MediaNotification.ActionFactory.COMMAND_SKIP_TO_NEXT)); 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. // Set metadata info in the notification.
MediaMetadata metadata = mediaController.getMediaMetadata(); MediaMetadata metadata = mediaController.getMediaMetadata();
@ -171,12 +185,17 @@ public final class DefaultMediaNotificationProvider implements MediaNotification
} }
} }
androidx.media.app.NotificationCompat.MediaStyle mediaStyle = MediaStyle mediaStyle = new MediaStyle();
new androidx.media.app.NotificationCompat.MediaStyle() if (mediaController.isCommandAvailable(Player.COMMAND_STOP) || Util.SDK_INT < 21) {
.setCancelButtonIntent( // We must include a cancel intent for pre-L devices.
actionFactory.createMediaActionPendingIntent( mediaStyle.setCancelButtonIntent(
MediaNotification.ActionFactory.COMMAND_STOP)) actionFactory.createMediaActionPendingIntent(
.setShowActionsInCompactView(1 /* Show play/pause button only in compact view */); MediaNotification.ActionFactory.COMMAND_STOP));
}
if (playPauseAdded) {
// Show play/pause button only in compact view.
mediaStyle.setShowActionsInCompactView(skipToPreviousAdded ? 1 : 0);
}
Notification notification = Notification notification =
builder builder