mirror of
https://github.com/samsonjs/media.git
synced 2026-03-27 09:45:47 +00:00
Allow using different notification IDs for different media sessions
When a media service currently produces multiple media sessions, the notification of the second session overwrites the notification of the first one, because all sessions use the same notification ID. When we use different notification IDs for different sessions, multiple media notifications can be up at the same time, which means that they can both be controlled at the same time.
PiperOrigin-RevId: 478709069
(cherry picked from commit 7783c6e4f7)
This commit is contained in:
parent
c8917b50e6
commit
9842c273e9
2 changed files with 90 additions and 5 deletions
|
|
@ -119,7 +119,7 @@ public class DefaultMediaNotificationProvider implements MediaNotification.Provi
|
|||
/** A builder for {@link DefaultMediaNotificationProvider} instances. */
|
||||
public static final class Builder {
|
||||
private final Context context;
|
||||
private int notificationId;
|
||||
private NotificationIdProvider notificationIdProvider;
|
||||
private String channelId;
|
||||
@StringRes private int channelNameResourceId;
|
||||
private BitmapLoader bitmapLoader;
|
||||
|
|
@ -132,7 +132,7 @@ public class DefaultMediaNotificationProvider implements MediaNotification.Provi
|
|||
*/
|
||||
public Builder(Context context) {
|
||||
this.context = context;
|
||||
notificationId = DEFAULT_NOTIFICATION_ID;
|
||||
notificationIdProvider = session -> DEFAULT_NOTIFICATION_ID;
|
||||
channelId = DEFAULT_CHANNEL_ID;
|
||||
channelNameResourceId = DEFAULT_CHANNEL_NAME_RESOURCE_ID;
|
||||
bitmapLoader = new SimpleBitmapLoader();
|
||||
|
|
@ -142,12 +142,30 @@ public class DefaultMediaNotificationProvider implements MediaNotification.Provi
|
|||
* Sets the {@link MediaNotification#notificationId} used for the created notifications. By
|
||||
* default, this is set to {@link #DEFAULT_NOTIFICATION_ID}.
|
||||
*
|
||||
* <p>Overwrites anything set in {@link #setNotificationIdProvider(NotificationIdProvider)}.
|
||||
*
|
||||
* @param notificationId The notification ID.
|
||||
* @return This builder.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setNotificationId(int notificationId) {
|
||||
this.notificationId = notificationId;
|
||||
this.notificationIdProvider = session -> notificationId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the provider for the {@link MediaNotification#notificationId} used for the created
|
||||
* notifications. By default, this is set to a provider that always returns {@link
|
||||
* #DEFAULT_NOTIFICATION_ID}.
|
||||
*
|
||||
* <p>Overwrites anything set in {@link #setNotificationId(int)}.
|
||||
*
|
||||
* @param notificationIdProvider The notification ID provider.
|
||||
* @return This builder.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setNotificationIdProvider(NotificationIdProvider notificationIdProvider) {
|
||||
this.notificationIdProvider = notificationIdProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -201,6 +219,16 @@ public class DefaultMediaNotificationProvider implements MediaNotification.Provi
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides notification IDs for posting media notifications for given media sessions.
|
||||
*
|
||||
* @see Builder#setNotificationIdProvider(NotificationIdProvider)
|
||||
*/
|
||||
public interface NotificationIdProvider {
|
||||
/** Returns the notification ID for the media notification of the given session. */
|
||||
int getNotificationId(MediaSession mediaSession);
|
||||
}
|
||||
|
||||
/**
|
||||
* An extras key that can be used to define the index of a {@link CommandButton} in {@linkplain
|
||||
* Notification.MediaStyle#setShowActionsInCompactView(int...) compact view}.
|
||||
|
|
@ -226,7 +254,7 @@ public class DefaultMediaNotificationProvider implements MediaNotification.Provi
|
|||
private static final String TAG = "NotificationProvider";
|
||||
|
||||
private final Context context;
|
||||
private final int notificationId;
|
||||
private final NotificationIdProvider notificationIdProvider;
|
||||
private final String channelId;
|
||||
@StringRes private final int channelNameResourceId;
|
||||
private final NotificationManager notificationManager;
|
||||
|
|
@ -241,7 +269,7 @@ public class DefaultMediaNotificationProvider implements MediaNotification.Provi
|
|||
|
||||
private DefaultMediaNotificationProvider(Builder builder) {
|
||||
this.context = builder.context;
|
||||
this.notificationId = builder.notificationId;
|
||||
this.notificationIdProvider = builder.notificationIdProvider;
|
||||
this.channelId = builder.channelId;
|
||||
this.channelNameResourceId = builder.channelNameResourceId;
|
||||
this.bitmapLoader = builder.bitmapLoader;
|
||||
|
|
@ -265,6 +293,7 @@ public class DefaultMediaNotificationProvider implements MediaNotification.Provi
|
|||
|
||||
Player player = mediaSession.getPlayer();
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId);
|
||||
int notificationId = notificationIdProvider.getNotificationId(mediaSession);
|
||||
|
||||
MediaStyle mediaStyle = new MediaStyle();
|
||||
int[] compactViewIndices =
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@
|
|||
*/
|
||||
package androidx.media3.session;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static androidx.media3.session.DefaultMediaNotificationProvider.DEFAULT_CHANNEL_ID;
|
||||
import static androidx.media3.session.DefaultMediaNotificationProvider.DEFAULT_NOTIFICATION_ID;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
|
|
@ -449,6 +452,33 @@ public class DefaultMediaNotificationProviderTest {
|
|||
verifyNoInteractions(mockOnNotificationChangedCallback1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void provider_idsNotSpecified_usesDefaultIds() {
|
||||
Context context = ApplicationProvider.getApplicationContext();
|
||||
DefaultMediaNotificationProvider defaultMediaNotificationProvider =
|
||||
new DefaultMediaNotificationProvider.Builder(context).build();
|
||||
MediaSession mockMediaSession = createMockMediaSessionForNotification(MediaMetadata.EMPTY);
|
||||
DefaultActionFactory defaultActionFactory =
|
||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||
|
||||
MediaNotification notification =
|
||||
defaultMediaNotificationProvider.createNotification(
|
||||
mockMediaSession,
|
||||
ImmutableList.of(),
|
||||
defaultActionFactory,
|
||||
mock(MediaNotification.Provider.Callback.class));
|
||||
|
||||
assertThat(notification.notificationId).isEqualTo(DEFAULT_NOTIFICATION_ID);
|
||||
assertThat(notification.notification.getChannelId()).isEqualTo(DEFAULT_CHANNEL_ID);
|
||||
ShadowNotificationManager shadowNotificationManager =
|
||||
Shadows.shadowOf(
|
||||
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE));
|
||||
assertHasNotificationChannel(
|
||||
shadowNotificationManager.getNotificationChannels(),
|
||||
/* channelId= */ DEFAULT_CHANNEL_ID,
|
||||
/* channelName= */ context.getString(R.string.default_notification_channel_name));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void provider_withCustomIds_notificationsUseCustomIds() {
|
||||
Context context = ApplicationProvider.getApplicationContext();
|
||||
|
|
@ -480,6 +510,32 @@ public class DefaultMediaNotificationProviderTest {
|
|||
/* channelName= */ context.getString(R.string.media3_controls_play_description));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void provider_withCustomNotificationIdProvider_notificationsUseCustomId() {
|
||||
Context context = ApplicationProvider.getApplicationContext();
|
||||
DefaultMediaNotificationProvider defaultMediaNotificationProvider =
|
||||
new DefaultMediaNotificationProvider.Builder(context)
|
||||
.setNotificationIdProvider(
|
||||
session -> {
|
||||
checkNotNull(session);
|
||||
return 3;
|
||||
})
|
||||
.setChannelName(/* channelNameResourceId= */ R.string.media3_controls_play_description)
|
||||
.build();
|
||||
MediaSession mockMediaSession = createMockMediaSessionForNotification(MediaMetadata.EMPTY);
|
||||
DefaultActionFactory defaultActionFactory =
|
||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||
|
||||
MediaNotification notification =
|
||||
defaultMediaNotificationProvider.createNotification(
|
||||
mockMediaSession,
|
||||
ImmutableList.of(),
|
||||
defaultActionFactory,
|
||||
mock(MediaNotification.Provider.Callback.class));
|
||||
|
||||
assertThat(notification.notificationId).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setCustomSmallIcon_notificationUsesCustomSmallIcon() {
|
||||
Context context = ApplicationProvider.getApplicationContext();
|
||||
|
|
|
|||
Loading…
Reference in a new issue