Use Media 3 command constants instead of legacy constants
PiperOrigin-RevId: 446425897
This commit is contained in:
parent
5e139780f6
commit
9ca0f7862a
@ -15,17 +15,32 @@
|
||||
*/
|
||||
package androidx.media3.session;
|
||||
|
||||
import static android.view.KeyEvent.KEYCODE_MEDIA_FAST_FORWARD;
|
||||
import static android.view.KeyEvent.KEYCODE_MEDIA_NEXT;
|
||||
import static android.view.KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
|
||||
import static android.view.KeyEvent.KEYCODE_MEDIA_PREVIOUS;
|
||||
import static android.view.KeyEvent.KEYCODE_MEDIA_REWIND;
|
||||
import static android.view.KeyEvent.KEYCODE_MEDIA_STOP;
|
||||
import static android.view.KeyEvent.KEYCODE_UNKNOWN;
|
||||
import static androidx.media3.common.Player.COMMAND_PLAY_PAUSE;
|
||||
import static androidx.media3.common.Player.COMMAND_SEEK_BACK;
|
||||
import static androidx.media3.common.Player.COMMAND_SEEK_FORWARD;
|
||||
import static androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT;
|
||||
import static androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM;
|
||||
import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS;
|
||||
import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.media.session.PlaybackStateCompat;
|
||||
import android.view.KeyEvent;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
|
||||
@ -41,13 +56,15 @@ import androidx.media3.common.util.Util;
|
||||
|
||||
private final Service service;
|
||||
|
||||
private int customActionPendingIntentRequestCode = 0;
|
||||
|
||||
public DefaultActionFactory(Service service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NotificationCompat.Action createMediaAction(
|
||||
IconCompat icon, CharSequence title, @Command long command) {
|
||||
IconCompat icon, CharSequence title, @Player.Command long command) {
|
||||
return new NotificationCompat.Action(icon, title, createMediaActionPendingIntent(command));
|
||||
}
|
||||
|
||||
@ -59,12 +76,12 @@ import androidx.media3.common.util.Util;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingIntent createMediaActionPendingIntent(@Command long command) {
|
||||
int keyCode = PlaybackStateCompat.toKeyCode(command);
|
||||
public PendingIntent createMediaActionPendingIntent(@Player.Command long command) {
|
||||
int keyCode = toKeyCode(command);
|
||||
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
|
||||
intent.setComponent(new ComponentName(service, service.getClass()));
|
||||
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
|
||||
if (Util.SDK_INT >= 26 && command == COMMAND_PLAY) {
|
||||
if (Util.SDK_INT >= 26 && command == COMMAND_PLAY_PAUSE) {
|
||||
return Api26.createForegroundServicePendingIntent(service, keyCode, intent);
|
||||
} else {
|
||||
return PendingIntent.getService(
|
||||
@ -75,6 +92,24 @@ import androidx.media3.common.util.Util;
|
||||
}
|
||||
}
|
||||
|
||||
private int toKeyCode(@Player.Command long action) {
|
||||
if (action == COMMAND_SEEK_TO_NEXT_MEDIA_ITEM || action == COMMAND_SEEK_TO_NEXT) {
|
||||
return KEYCODE_MEDIA_NEXT;
|
||||
} else if (action == COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
|
||||
|| action == COMMAND_SEEK_TO_PREVIOUS) {
|
||||
return KEYCODE_MEDIA_PREVIOUS;
|
||||
} else if (action == Player.COMMAND_STOP) {
|
||||
return KEYCODE_MEDIA_STOP;
|
||||
} else if (action == COMMAND_SEEK_FORWARD) {
|
||||
return KEYCODE_MEDIA_FAST_FORWARD;
|
||||
} else if (action == COMMAND_SEEK_BACK) {
|
||||
return KEYCODE_MEDIA_REWIND;
|
||||
} else if (action == COMMAND_PLAY_PAUSE) {
|
||||
return KEYCODE_MEDIA_PLAY_PAUSE;
|
||||
}
|
||||
return KEYCODE_UNKNOWN;
|
||||
}
|
||||
|
||||
private PendingIntent createCustomActionPendingIntent(String action, Bundle extras) {
|
||||
Intent intent = new Intent(ACTION_CUSTOM);
|
||||
intent.setComponent(new ComponentName(service, service.getClass()));
|
||||
@ -83,7 +118,7 @@ import androidx.media3.common.util.Util;
|
||||
// Custom actions always start the service in the background.
|
||||
return PendingIntent.getService(
|
||||
service,
|
||||
/* requestCode= */ KeyEvent.KEYCODE_UNKNOWN,
|
||||
/* requestCode= */ ++customActionPendingIntentRequestCode,
|
||||
intent,
|
||||
Util.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0);
|
||||
}
|
||||
|
@ -15,6 +15,12 @@
|
||||
*/
|
||||
package androidx.media3.session;
|
||||
|
||||
import static androidx.media3.common.Player.COMMAND_PLAY_PAUSE;
|
||||
import static androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT;
|
||||
import static androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM;
|
||||
import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS;
|
||||
import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM;
|
||||
import static androidx.media3.common.Player.COMMAND_STOP;
|
||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||
import static androidx.media3.common.util.Util.castNonNull;
|
||||
|
||||
@ -52,13 +58,9 @@ import java.util.concurrent.ExecutionException;
|
||||
* The following actions are included in the provided notifications:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link MediaNotification.ActionFactory#COMMAND_PLAY} to start playback. Included when
|
||||
* {@link MediaController#getPlayWhenReady()} returns {@code false}.
|
||||
* <li>{@link MediaNotification.ActionFactory#COMMAND_PAUSE}, to pause playback. Included when
|
||||
* ({@link MediaController#getPlayWhenReady()} returns {@code true}.
|
||||
* <li>{@link MediaNotification.ActionFactory#COMMAND_SKIP_TO_PREVIOUS} to skip to the previous
|
||||
* item.
|
||||
* <li>{@link MediaNotification.ActionFactory#COMMAND_SKIP_TO_NEXT} to skip to the next item.
|
||||
* <li>{@link MediaController#COMMAND_PLAY_PAUSE} to start or pause playback.
|
||||
* <li>{@link MediaController#COMMAND_SEEK_TO_PREVIOUS} to seek to the previous item.
|
||||
* <li>{@link MediaController#COMMAND_SEEK_TO_NEXT} to seek to the next item.
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Drawables</h2>
|
||||
@ -120,17 +122,17 @@ public final class DefaultMediaNotificationProvider implements MediaNotification
|
||||
// Skip to previous action.
|
||||
boolean skipToPreviousAdded = false;
|
||||
if (availableCommands.containsAny(
|
||||
Player.COMMAND_SEEK_TO_PREVIOUS, Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)) {
|
||||
COMMAND_SEEK_TO_PREVIOUS, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)) {
|
||||
skipToPreviousAdded = true;
|
||||
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));
|
||||
COMMAND_SEEK_TO_PREVIOUS));
|
||||
}
|
||||
boolean playPauseAdded = false;
|
||||
if (availableCommands.contains(Player.COMMAND_PLAY_PAUSE)) {
|
||||
if (availableCommands.contains(COMMAND_PLAY_PAUSE)) {
|
||||
playPauseAdded = true;
|
||||
if (mediaController.getPlaybackState() == Player.STATE_ENDED
|
||||
|| !mediaController.getPlayWhenReady()) {
|
||||
@ -139,24 +141,23 @@ public final class DefaultMediaNotificationProvider implements MediaNotification
|
||||
actionFactory.createMediaAction(
|
||||
IconCompat.createWithResource(context, R.drawable.media3_notification_play),
|
||||
context.getString(R.string.media3_controls_play_description),
|
||||
MediaNotification.ActionFactory.COMMAND_PLAY));
|
||||
COMMAND_PLAY_PAUSE));
|
||||
} 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));
|
||||
COMMAND_PLAY_PAUSE));
|
||||
}
|
||||
}
|
||||
// Skip to next action.
|
||||
if (availableCommands.containsAny(
|
||||
Player.COMMAND_SEEK_TO_NEXT, Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM)) {
|
||||
if (availableCommands.containsAny(COMMAND_SEEK_TO_NEXT, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM)) {
|
||||
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));
|
||||
COMMAND_SEEK_TO_NEXT));
|
||||
}
|
||||
|
||||
// Set metadata info in the notification.
|
||||
@ -187,11 +188,9 @@ public final class DefaultMediaNotificationProvider implements MediaNotification
|
||||
}
|
||||
|
||||
MediaStyle mediaStyle = new MediaStyle();
|
||||
if (mediaController.isCommandAvailable(Player.COMMAND_STOP) || Util.SDK_INT < 21) {
|
||||
if (mediaController.isCommandAvailable(COMMAND_STOP) || Util.SDK_INT < 21) {
|
||||
// We must include a cancel intent for pre-L devices.
|
||||
mediaStyle.setCancelButtonIntent(
|
||||
actionFactory.createMediaActionPendingIntent(
|
||||
MediaNotification.ActionFactory.COMMAND_STOP));
|
||||
mediaStyle.setCancelButtonIntent(actionFactory.createMediaActionPendingIntent(COMMAND_STOP));
|
||||
}
|
||||
if (playPauseAdded) {
|
||||
// Show play/pause button only in compact view.
|
||||
@ -208,9 +207,7 @@ public final class DefaultMediaNotificationProvider implements MediaNotification
|
||||
Notification notification =
|
||||
builder
|
||||
.setContentIntent(mediaController.getSessionActivity())
|
||||
.setDeleteIntent(
|
||||
actionFactory.createMediaActionPendingIntent(
|
||||
MediaNotification.ActionFactory.COMMAND_STOP))
|
||||
.setDeleteIntent(actionFactory.createMediaActionPendingIntent(COMMAND_STOP))
|
||||
.setOnlyAlertOnce(true)
|
||||
.setSmallIcon(getSmallIconResId(context))
|
||||
.setStyle(mediaStyle)
|
||||
|
@ -16,22 +16,16 @@
|
||||
package androidx.media3.session;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.media.session.PlaybackStateCompat;
|
||||
import androidx.annotation.IntRange;
|
||||
import androidx.annotation.LongDef;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/** A notification for media playbacks. */
|
||||
public final class MediaNotification {
|
||||
@ -43,44 +37,6 @@ public final class MediaNotification {
|
||||
@UnstableApi
|
||||
public interface ActionFactory {
|
||||
|
||||
/**
|
||||
* Commands that can be included in a media action. One of {@link #COMMAND_PLAY}, {@link
|
||||
* #COMMAND_PAUSE}, {@link #COMMAND_STOP}, {@link #COMMAND_REWIND}, {@link
|
||||
* #COMMAND_FAST_FORWARD}, {@link #COMMAND_SKIP_TO_PREVIOUS}, {@link #COMMAND_SKIP_TO_NEXT} or
|
||||
* {@link #COMMAND_SET_CAPTIONING_ENABLED}.
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target({TYPE_USE})
|
||||
@LongDef({
|
||||
COMMAND_PLAY,
|
||||
COMMAND_PAUSE,
|
||||
COMMAND_STOP,
|
||||
COMMAND_REWIND,
|
||||
COMMAND_FAST_FORWARD,
|
||||
COMMAND_SKIP_TO_PREVIOUS,
|
||||
COMMAND_SKIP_TO_NEXT,
|
||||
COMMAND_SET_CAPTIONING_ENABLED
|
||||
})
|
||||
@interface Command {}
|
||||
|
||||
/** The command to start playback. */
|
||||
long COMMAND_PLAY = PlaybackStateCompat.ACTION_PLAY;
|
||||
/** The command to pause playback. */
|
||||
long COMMAND_PAUSE = PlaybackStateCompat.ACTION_PAUSE;
|
||||
/** The command to stop playback. */
|
||||
long COMMAND_STOP = PlaybackStateCompat.ACTION_STOP;
|
||||
/** The command to rewind. */
|
||||
long COMMAND_REWIND = PlaybackStateCompat.ACTION_REWIND;
|
||||
/** The command to fast forward. */
|
||||
long COMMAND_FAST_FORWARD = PlaybackStateCompat.ACTION_FAST_FORWARD;
|
||||
/** The command to skip to the previous item in the queue. */
|
||||
long COMMAND_SKIP_TO_PREVIOUS = PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
|
||||
/** The command to skip to the next item in the queue. */
|
||||
long COMMAND_SKIP_TO_NEXT = PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
|
||||
/** The command to set captioning enabled. */
|
||||
long COMMAND_SET_CAPTIONING_ENABLED = PlaybackStateCompat.ACTION_SET_CAPTIONING_ENABLED;
|
||||
|
||||
/**
|
||||
* Creates a {@link NotificationCompat.Action} for a notification. These actions will be handled
|
||||
* by the library.
|
||||
@ -90,7 +46,7 @@ public final class MediaNotification {
|
||||
* @param command A command to send when users trigger this action.
|
||||
*/
|
||||
NotificationCompat.Action createMediaAction(
|
||||
IconCompat icon, CharSequence title, @Command long command);
|
||||
IconCompat icon, CharSequence title, @Player.Command long command);
|
||||
|
||||
/**
|
||||
* Creates a {@link NotificationCompat.Action} for a notification with a custom action. Actions
|
||||
@ -112,7 +68,7 @@ public final class MediaNotification {
|
||||
*
|
||||
* @param command The intent's command.
|
||||
*/
|
||||
PendingIntent createMediaActionPendingIntent(@Command long command);
|
||||
PendingIntent createMediaActionPendingIntent(@Player.Command long command);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,6 +21,7 @@ import static org.robolectric.Shadows.shadowOf;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@ -37,7 +38,7 @@ public class DefaultActionFactoryTest {
|
||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||
|
||||
PendingIntent pendingIntent =
|
||||
actionFactory.createMediaActionPendingIntent(MediaNotification.ActionFactory.COMMAND_PLAY);
|
||||
actionFactory.createMediaActionPendingIntent(Player.COMMAND_PLAY_PAUSE);
|
||||
|
||||
ShadowPendingIntent shadowPendingIntent = shadowOf(pendingIntent);
|
||||
assertThat(actionFactory.isMediaAction(shadowPendingIntent.getSavedIntent())).isTrue();
|
||||
|
Loading…
x
Reference in New Issue
Block a user