From c8a016ecb6e8673229be829de6948d4899572465 Mon Sep 17 00:00:00 2001 From: nift4 Date: Sun, 27 Jul 2025 16:46:54 +0200 Subject: [PATCH] Add notification for empty player setting --- .../session/MediaNotificationManager.java | 31 ++++++++++- .../media3/session/MediaSessionService.java | 53 +++++++++++++++++-- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaNotificationManager.java b/libraries/session/src/main/java/androidx/media3/session/MediaNotificationManager.java index 4ed6948bb7..e0c309cc7c 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaNotificationManager.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaNotificationManager.java @@ -39,6 +39,7 @@ import androidx.media3.common.util.Log; import androidx.media3.common.util.Util; import androidx.media3.session.MediaNotification.Provider.NotificationChannelInfo; +import androidx.media3.session.MediaSessionService.ShowNotificationForEmptyPlayerMode; import androidx.media3.session.MediaSessionService.ShowNotificationForIdlePlayerMode; import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.FutureCallback; @@ -85,6 +86,7 @@ private boolean isUserEngagedTimeoutEnabled; private long userEngagedTimeoutMs; @ShowNotificationForIdlePlayerMode int showNotificationForIdlePlayerMode; + @ShowNotificationForEmptyPlayerMode int showNotificationForEmptyPlayerMode; public MediaNotificationManager( MediaSessionService mediaSessionService, @@ -108,6 +110,8 @@ public MediaNotificationManager( userEngagedTimeoutMs = MediaSessionService.DEFAULT_FOREGROUND_SERVICE_TIMEOUT_MS; showNotificationForIdlePlayerMode = MediaSessionService.SHOW_NOTIFICATION_FOR_IDLE_PLAYER_AFTER_STOP_OR_ERROR; + showNotificationForEmptyPlayerMode = + MediaSessionService.SHOW_NOTIFICATION_FOR_EMPTY_PLAYER_NEVER; } /** @@ -236,6 +240,16 @@ public void setShowNotificationForIdlePlayer( } } + public void setShowNotificationForEmptyPlayer( + @ShowNotificationForEmptyPlayerMode int showNotificationForEmptyPlayerMode) { + this.showNotificationForEmptyPlayerMode = showNotificationForEmptyPlayerMode; + List sessions = mediaSessionService.getSessions(); + for (int i = 0; i < sessions.size(); i++) { + mediaSessionService.onUpdateNotificationInternal( + sessions.get(i), /* startInForegroundWhenPaused= */ false); + } + } + @Override public boolean handleMessage(Message msg) { if (msg.what == MSG_USER_ENGAGED_TIMEOUT) { @@ -345,10 +359,25 @@ private void removeNotification() { private boolean shouldShowNotification(MediaSession session) { MediaController controller = getConnectedControllerForSession(session); - if (controller == null || controller.getCurrentTimeline().isEmpty()) { + if (controller == null) { return false; } ControllerInfo controllerInfo = checkNotNull(controllerMap.get(session)); + if (controller.getCurrentTimeline().isEmpty()) { + switch (showNotificationForEmptyPlayerMode) { + case MediaSessionService.SHOW_NOTIFICATION_FOR_EMPTY_PLAYER_ALWAYS: + break; + case MediaSessionService.SHOW_NOTIFICATION_FOR_EMPTY_PLAYER_NEVER: + return false; + case MediaSessionService.SHOW_NOTIFICATION_FOR_EMPTY_PLAYER_AFTER_STOP_OR_ERROR: + if (!controllerInfo.hasBeenPrepared) { + return false; + } + break; + default: + throw new IllegalStateException(); + } + } if (controller.getPlaybackState() != Player.STATE_IDLE) { // Playback first prepared or restarted, reset previous notification dismissed flag. controllerInfo.wasNotificationDismissed = false; diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionService.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionService.java index 91a0bc7b61..ee67ad10b1 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionService.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionService.java @@ -199,8 +199,8 @@ default void onForegroundServiceStartNotAllowedException() {} public @interface ShowNotificationForIdlePlayerMode {} /** - * Always show a notification when the {@link Player} is in {@link Player#STATE_IDLE}, has media, - * and the notification wasn't explicitly dismissed. + * Always show a notification when the {@link Player} is in {@link Player#STATE_IDLE} and the + * notification wasn't explicitly dismissed. */ @UnstableApi public static final int SHOW_NOTIFICATION_FOR_IDLE_PLAYER_ALWAYS = 1; @@ -209,10 +209,45 @@ default void onForegroundServiceStartNotAllowedException() {} /** * Shows a notification when the {@link Player} is in {@link Player#STATE_IDLE} due to {@link - * Player#stop} or an error, has media, and the notification wasn't explicitly dismissed. + * Player#stop} or an error, and the notification wasn't explicitly dismissed. */ @UnstableApi public static final int SHOW_NOTIFICATION_FOR_IDLE_PLAYER_AFTER_STOP_OR_ERROR = 3; + /** + * The behavior for showing notifications when the {@link Player} has no media. + * + *

One of {@link #SHOW_NOTIFICATION_FOR_EMPTY_PLAYER_ALWAYS}, {@link + * #SHOW_NOTIFICATION_FOR_EMPTY_PLAYER_NEVER}, {@link + * #SHOW_NOTIFICATION_FOR_EMPTY_PLAYER_AFTER_STOP_OR_ERROR}. + * + *

The default value is {@link #SHOW_NOTIFICATION_FOR_EMPTY_PLAYER_NEVER}. + */ + @UnstableApi + @Documented + @Retention(RetentionPolicy.SOURCE) + @Target(TYPE_USE) + @IntDef({ + SHOW_NOTIFICATION_FOR_EMPTY_PLAYER_ALWAYS, + SHOW_NOTIFICATION_FOR_EMPTY_PLAYER_NEVER, + SHOW_NOTIFICATION_FOR_EMPTY_PLAYER_AFTER_STOP_OR_ERROR + }) + public @interface ShowNotificationForEmptyPlayerMode {} + + /** + * Always show a notification when the {@link Player} is empty and the notification wasn't + * explicitly dismissed. + */ + @UnstableApi public static final int SHOW_NOTIFICATION_FOR_EMPTY_PLAYER_ALWAYS = 1; + + /** Never show a notification when the {@link Player} is empty. */ + @UnstableApi public static final int SHOW_NOTIFICATION_FOR_EMPTY_PLAYER_NEVER = 2; + + /** + * Shows a notification when the {@link Player} is empty, in {@link Player#STATE_IDLE} due to + * {@link Player#stop} or an error, and the notification wasn't explicitly dismissed. + */ + @UnstableApi public static final int SHOW_NOTIFICATION_FOR_EMPTY_PLAYER_AFTER_STOP_OR_ERROR = 3; + private static final String TAG = "MSessionService"; private final Object lock; @@ -595,6 +630,18 @@ public final void setShowNotificationForIdlePlayer( .setShowNotificationForIdlePlayer(showNotificationForIdlePlayerMode); } + /** + * Sets whether and when a notification for a {@link Player} that has no media should be shown. + * + * @param showNotificationForEmptyPlayerMode The {@link ShowNotificationForEmptyPlayerMode}. + */ + @UnstableApi + public final void setShowNotificationForEmptyPlayer( + @ShowNotificationForEmptyPlayerMode int showNotificationForEmptyPlayerMode) { + getMediaNotificationManager() + .setShowNotificationForEmptyPlayer(showNotificationForEmptyPlayerMode); + } + /** * Returns whether there is a session with ongoing user-engaged playback that is run in a * foreground service.