From 89b5420bc81ed39e65df76ba54ec07877efd1cd9 Mon Sep 17 00:00:00 2001 From: tonihei Date: Fri, 14 Feb 2025 06:15:08 -0800 Subject: [PATCH] Show notification even in STATE_IDLE Currently the notification disappears immediately when the player enters an error or stopped state, but still has its media and could resume on user request. This can be fixed by only checking the existence of media and not the state when deciding to show a notification. PiperOrigin-RevId: 726901050 (cherry picked from commit f0da364d3fdd8574c8506f0682a7d2ecf8135ad8) --- RELEASENOTES.md | 3 ++ .../session/MediaNotificationManager.java | 4 +- .../session/MediaSessionServiceTest.java | 49 +++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6d3ea9ac62..63d2cacbdd 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -35,6 +35,9 @@ * Muxers: * IMA extension: * Session: + * Keep notification visible when playback enters an error or stopped + state. The notification is only removed if the playlist is cleared or + the player is released. * UI: * Downloads: * OkHttp Extension: 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 14f2406a97..fc4ccdce6d 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaNotificationManager.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaNotificationManager.java @@ -251,9 +251,7 @@ import java.util.concurrent.TimeoutException; private boolean shouldShowNotification(MediaSession session) { MediaController controller = getConnectedControllerForSession(session); - return controller != null - && !controller.getCurrentTimeline().isEmpty() - && controller.getPlaybackState() != Player.STATE_IDLE; + return controller != null && !controller.getCurrentTimeline().isEmpty(); } @Nullable diff --git a/libraries/session/src/test/java/androidx/media3/session/MediaSessionServiceTest.java b/libraries/session/src/test/java/androidx/media3/session/MediaSessionServiceTest.java index aeb6908a00..97daf26a99 100644 --- a/libraries/session/src/test/java/androidx/media3/session/MediaSessionServiceTest.java +++ b/libraries/session/src/test/java/androidx/media3/session/MediaSessionServiceTest.java @@ -67,6 +67,55 @@ public class MediaSessionServiceTest { (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); } + @Test + public void service_sessionIdleNoMedia_createsNoNotification() { + ExoPlayer player = new TestExoPlayerBuilder(context).build(); + MediaSession session = new MediaSession.Builder(context, player).build(); + ServiceController serviceController = Robolectric.buildService(TestService.class); + TestService service = serviceController.create().get(); + service.setMediaNotificationProvider( + new DefaultMediaNotificationProvider( + service, + /* notificationIdProvider= */ unused -> 2000, + DefaultMediaNotificationProvider.DEFAULT_CHANNEL_ID, + DefaultMediaNotificationProvider.DEFAULT_CHANNEL_NAME_RESOURCE_ID)); + service.addSession(session); + + // Give the service a chance to create a notification. + ShadowLooper.idleMainLooper(); + + assertThat(getStatusBarNotification(2000)).isNull(); + + session.release(); + player.release(); + serviceController.destroy(); + } + + @Test + public void service_sessionIdleWithMedia_createsNotification() { + ExoPlayer player = new TestExoPlayerBuilder(context).build(); + MediaSession session = new MediaSession.Builder(context, player).build(); + ServiceController serviceController = Robolectric.buildService(TestService.class); + TestService service = serviceController.create().get(); + service.setMediaNotificationProvider( + new DefaultMediaNotificationProvider( + service, + /* notificationIdProvider= */ unused -> 2000, + DefaultMediaNotificationProvider.DEFAULT_CHANNEL_ID, + DefaultMediaNotificationProvider.DEFAULT_CHANNEL_NAME_RESOURCE_ID)); + service.addSession(session); + + // Add media and give the service a chance to create a notification. + player.setMediaItem(MediaItem.fromUri("asset:///media/mp4/sample.mp4")); + ShadowLooper.idleMainLooper(); + + assertThat(getStatusBarNotification(2000)).isNotNull(); + + session.release(); + player.release(); + serviceController.destroy(); + } + @Test public void service_multipleSessionsOnMainThread_createsNotificationForEachSession() { ExoPlayer player1 = new TestExoPlayerBuilder(context).build();