diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaStyleNotificationHelper.java b/libraries/session/src/main/java/androidx/media3/session/MediaStyleNotificationHelper.java index faadf5da8d..9263bbc3f4 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaStyleNotificationHelper.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaStyleNotificationHelper.java @@ -18,12 +18,10 @@ package androidx.media3.session; import static android.Manifest.permission.MEDIA_CONTENT_CONTROL; import static androidx.core.app.NotificationCompat.COLOR_DEFAULT; import static androidx.media3.common.util.Assertions.checkArgument; -import static androidx.media3.common.util.Assertions.checkNotNull; import android.annotation.SuppressLint; import android.app.Notification; import android.app.PendingIntent; -import android.os.Build; import android.os.Bundle; import android.view.View; import android.widget.RemoteViews; @@ -37,7 +35,6 @@ import androidx.core.graphics.drawable.IconCompat; import androidx.media3.common.util.NullableType; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; -import androidx.media3.session.legacy.MediaSessionCompat; import com.google.errorprone.annotations.CanIgnoreReturnValue; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @@ -113,7 +110,6 @@ public class MediaStyleNotificationHelper { /* package */ final MediaSession session; - private boolean showCancelButton; /* package */ int @NullableType [] actionsToShowInCompact; @Nullable /* package */ PendingIntent cancelButtonIntent; /* package */ @MonotonicNonNull CharSequence remoteDeviceName; @@ -141,34 +137,12 @@ public class MediaStyleNotificationHelper { } /** - * Sets whether a cancel button at the top right should be shown in the notification on - * platforms before Lollipop. - * - *

Prior to Lollipop, there was a bug in the framework which prevented the developer to make - * a notification dismissable again after having used the same notification as the ongoing - * notification for a foreground service. When the notification was posted by {@link - * android.app.Service#startForeground}, but then the service exited foreground mode via {@link - * android.app.Service#stopForeground}, without removing the notification, the notification - * stayed ongoing, and thus not dismissable. - * - *

This is a common scenario for media notifications, as this is exactly the service - * lifecycle that happens when playing/pausing media. Thus, a workaround is provided by the - * support library: Instead of making the notification ongoing depending on the playback state, - * the support library provides the ability to add an explicit cancel button to the - * notification. - * - *

Note that the notification is enforced to be ongoing if a cancel button is shown to - * provide a consistent user experience. - * - *

Also note that this method is a no-op when running on Lollipop and later. - * - * @param show whether to show a cancel button + * @deprecated This method is a no-op and usages can be safely removed. There is no recommended + * alternative (it was previously only operational on API ≤ 21). */ @CanIgnoreReturnValue + @Deprecated public MediaStyle setShowCancelButton(boolean show) { - if (Build.VERSION.SDK_INT < 21) { - showCancelButton = show; - } return this; } @@ -218,41 +192,28 @@ public class MediaStyleNotificationHelper { @Override public void apply(NotificationBuilderWithBuilderAccessor builder) { + // Avoid ambiguity with androidx.media3.session.Session.Token + @SuppressWarnings("UnnecessarilyFullyQualified") + Notification.MediaStyle style = + new Notification.MediaStyle() + .setMediaSession( + (android.media.session.MediaSession.Token) + session.getSessionCompat().getSessionToken().getToken()); + if (actionsToShowInCompact != null) { + style.setShowActionsInCompactView(actionsToShowInCompact); + } if (Util.SDK_INT >= 34 && remoteDeviceName != null) { - Api21Impl.setMediaStyle( - builder.getBuilder(), - Api21Impl.fillInMediaStyle( - Api34Impl.setRemotePlaybackInfo( - Api21Impl.createMediaStyle(), - remoteDeviceName, - remoteDeviceIconRes, - remoteDeviceIntent), - actionsToShowInCompact, - session)); - } else if (Util.SDK_INT >= 21) { - Api21Impl.setMediaStyle( - builder.getBuilder(), - Api21Impl.fillInMediaStyle( - Api21Impl.createMediaStyle(), actionsToShowInCompact, session)); + Api34Impl.setRemotePlaybackInfo( + style, remoteDeviceName, remoteDeviceIconRes, remoteDeviceIntent); + builder.getBuilder().setStyle(style); + } else { + builder.getBuilder().setStyle(style); Bundle bundle = new Bundle(); bundle.putBundle(EXTRA_MEDIA3_SESSION, session.getToken().toBundle()); builder.getBuilder().addExtras(bundle); - } else if (showCancelButton) { - builder.getBuilder().setOngoing(true); } } - @Override - @Nullable - @SuppressWarnings("nullness:override.return") // NotificationCompat doesn't annotate @Nullable - public RemoteViews makeContentView(NotificationBuilderWithBuilderAccessor builder) { - if (Util.SDK_INT >= 21) { - // No custom content view required - return null; - } - return generateContentView(); - } - /* package */ RemoteViews generateContentView() { RemoteViews view = applyStandardTemplate( @@ -279,22 +240,7 @@ public class MediaStyleNotificationHelper { } } } - if (showCancelButton) { - view.setViewVisibility(androidx.media3.session.R.id.end_padder, View.GONE); - view.setViewVisibility(androidx.media3.session.R.id.cancel_action, View.VISIBLE); - view.setOnClickPendingIntent( - androidx.media3.session.R.id.cancel_action, cancelButtonIntent); - view.setInt( - androidx.media3.session.R.id.cancel_action, - "setAlpha", - mBuilder - .mContext - .getResources() - .getInteger(androidx.media3.session.R.integer.cancel_button_image_alpha)); - } else { - view.setViewVisibility(androidx.media3.session.R.id.end_padder, View.VISIBLE); - view.setViewVisibility(androidx.media3.session.R.id.cancel_action, View.GONE); - } + view.setViewVisibility(androidx.media3.session.R.id.end_padder, View.VISIBLE); return view; } @@ -321,17 +267,6 @@ public class MediaStyleNotificationHelper { return androidx.media3.session.R.layout.media3_notification_template_media; } - @Override - @Nullable - @SuppressWarnings("nullness:override.return") // NotificationCompat doesn't annotate @Nullable - public RemoteViews makeBigContentView(NotificationBuilderWithBuilderAccessor builder) { - if (Util.SDK_INT >= 21) { - // No custom content view required - return null; - } - return generateBigContentView(); - } - /* package */ RemoteViews generateBigContentView() { final int actionCount = Math.min(mBuilder.mActions.size(), MAX_MEDIA_BUTTONS); RemoteViews big = @@ -347,19 +282,6 @@ public class MediaStyleNotificationHelper { big.addView(androidx.media3.session.R.id.media_actions, button); } } - if (showCancelButton) { - big.setViewVisibility(androidx.media3.session.R.id.cancel_action, View.VISIBLE); - big.setInt( - androidx.media3.session.R.id.cancel_action, - "setAlpha", - mBuilder - .mContext - .getResources() - .getInteger(androidx.media3.session.R.integer.cancel_button_image_alpha)); - big.setOnClickPendingIntent(androidx.media3.session.R.id.cancel_action, cancelButtonIntent); - } else { - big.setViewVisibility(androidx.media3.session.R.id.cancel_action, View.GONE); - } return big; } @@ -412,27 +334,24 @@ public class MediaStyleNotificationHelper { @Override public void apply(NotificationBuilderWithBuilderAccessor builder) { + if (Util.SDK_INT < 24) { + super.apply(builder); + return; + } + Notification.DecoratedMediaCustomViewStyle style = + Api24Impl.createDecoratedMediaCustomViewStyle(); + if (actionsToShowInCompact != null) { + style.setShowActionsInCompactView(actionsToShowInCompact); + } if (Util.SDK_INT >= 34 && remoteDeviceName != null) { - Api21Impl.setMediaStyle( - builder.getBuilder(), - Api21Impl.fillInMediaStyle( - Api34Impl.setRemotePlaybackInfo( - Api24Impl.createDecoratedMediaCustomViewStyle(), - remoteDeviceName, - remoteDeviceIconRes, - remoteDeviceIntent), - actionsToShowInCompact, - session)); - } else if (Util.SDK_INT >= 24) { - Api21Impl.setMediaStyle( - builder.getBuilder(), - Api21Impl.fillInMediaStyle( - Api24Impl.createDecoratedMediaCustomViewStyle(), actionsToShowInCompact, session)); + Api34Impl.setRemotePlaybackInfo( + style, remoteDeviceName, remoteDeviceIconRes, remoteDeviceIntent); + builder.getBuilder().setStyle(style); + } else { + builder.getBuilder().setStyle(style); Bundle bundle = new Bundle(); bundle.putBundle(EXTRA_MEDIA3_SESSION, session.getToken().toBundle()); builder.getBuilder().addExtras(bundle); - } else { - super.apply(builder); } } @@ -445,25 +364,14 @@ public class MediaStyleNotificationHelper { return null; } boolean hasContentView = mBuilder.getContentView() != null; - if (Util.SDK_INT >= 21) { - // If we are on L/M the media notification will only be colored if the expanded - // version is of media style, so we have to create a custom view for the collapsed - // version as well in that case. - boolean createCustomContent = hasContentView || mBuilder.getBigContentView() != null; - if (createCustomContent) { - RemoteViews contentView = generateContentView(); - if (hasContentView) { - buildIntoRemoteViews(contentView, mBuilder.getContentView()); - } - setBackgroundColor(contentView); - return contentView; - } - } else { + boolean createCustomContent = hasContentView || mBuilder.getBigContentView() != null; + if (createCustomContent) { RemoteViews contentView = generateContentView(); if (hasContentView) { buildIntoRemoteViews(contentView, mBuilder.getContentView()); - return contentView; } + setBackgroundColor(contentView); + return contentView; } return null; } @@ -493,9 +401,7 @@ public class MediaStyleNotificationHelper { } RemoteViews bigContentView = generateBigContentView(); buildIntoRemoteViews(bigContentView, innerView); - if (Util.SDK_INT >= 21) { - setBackgroundColor(bigContentView); - } + setBackgroundColor(bigContentView); return bigContentView; } @@ -524,9 +430,7 @@ public class MediaStyleNotificationHelper { } RemoteViews headsUpContentView = generateBigContentView(); buildIntoRemoteViews(headsUpContentView, innerView); - if (Util.SDK_INT >= 21) { - setBackgroundColor(headsUpContentView); - } + setBackgroundColor(headsUpContentView); return headsUpContentView; } @@ -547,41 +451,6 @@ public class MediaStyleNotificationHelper { } } - @RequiresApi(21) - private static class Api21Impl { - private Api21Impl() {} - - @DoNotInline - static void setMediaStyle(Notification.Builder builder, Notification.MediaStyle style) { - builder.setStyle(style); - } - - @DoNotInline - public static Notification.MediaStyle createMediaStyle() { - return new Notification.MediaStyle(); - } - - @DoNotInline - public static Notification.MediaStyle fillInMediaStyle( - Notification.MediaStyle style, - @Nullable int[] actionsToShowInCompact, - MediaSession session) { - checkNotNull(style); - checkNotNull(session); - if (actionsToShowInCompact != null) { - setShowActionsInCompactView(style, actionsToShowInCompact); - } - MediaSessionCompat.Token legacyToken = session.getSessionCompat().getSessionToken(); - style.setMediaSession((android.media.session.MediaSession.Token) legacyToken.getToken()); - return style; - } - - @DoNotInline - public static void setShowActionsInCompactView(Notification.MediaStyle style, int... actions) { - style.setShowActionsInCompactView(actions); - } - } - @RequiresApi(24) private static class Api24Impl { private Api24Impl() {} diff --git a/libraries/session/src/main/res/layout/media3_notification_media_cancel_action.xml b/libraries/session/src/main/res/layout/media3_notification_media_cancel_action.xml deleted file mode 100644 index f853d0ad66..0000000000 --- a/libraries/session/src/main/res/layout/media3_notification_media_cancel_action.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - diff --git a/libraries/session/src/main/res/layout/media3_notification_template_big_media.xml b/libraries/session/src/main/res/layout/media3_notification_template_big_media.xml index bbe6228d12..63887c1e33 100644 --- a/libraries/session/src/main/res/layout/media3_notification_template_big_media.xml +++ b/libraries/session/src/main/res/layout/media3_notification_template_big_media.xml @@ -23,21 +23,12 @@ android:layout_width="@dimen/notification_large_icon_width" android:layout_height="@dimen/notification_large_icon_height" /> - + android:layout_marginStart="@dimen/notification_large_icon_width"/> - + android:orientation="horizontal"> - - + android:layout_marginStart="128dp"/> - - + android:orientation="horizontal"> - -