From 0e12eb4d92ea7c9c45736e849554d46ecec5f072 Mon Sep 17 00:00:00 2001 From: bachinger Date: Wed, 5 Sep 2018 04:37:20 -0700 Subject: [PATCH] Dispatch notification actions to the originating PlayerNotificationManager only. Issue #4643 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=211613803 --- .../ui/PlayerNotificationManager.java | 73 ++++++++++++------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java index 805ae0fa67..ae046e19e0 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java @@ -145,8 +145,23 @@ public class PlayerNotificationManager { /** Defines and handles custom actions. */ public interface CustomActionReceiver { - /** Gets the actions handled by this receiver. */ - Map createCustomActions(Context context); + /** + * Gets the actions handled by this receiver. + * + *

If multiple {@link PlayerNotificationManager} instances are in use at the same time, the + * {@code instanceId} must be set as an intent extra with key {@link + * PlayerNotificationManager#EXTRA_INSTANCE_ID} to avoid sending the action to every custom + * action receiver. It's also necessary to ensure something is different about the actions. This + * may be any of the {@link Intent} attributes considered by {@link Intent#filterEquals}, or + * different request code integers when creating the {@link PendingIntent}s with {@link + * PendingIntent#getBroadcast}. The easiest approach is to use the {@code instanceId} as the + * request code. + * + * @param context The {@link Context}. + * @param instanceId The instance id of the {@link PlayerNotificationManager}. + * @return A map of custom actions. + */ + Map createCustomActions(Context context, int instanceId); /** * Gets the actions to be included in the notification given the current player state. @@ -227,6 +242,8 @@ public class PlayerNotificationManager { public static final String ACTION_REWIND = "com.google.android.exoplayer.rewind"; /** The action which cancels the notification and stops playback. */ public static final String ACTION_STOP = "com.google.android.exoplayer.stop"; + /** The extra key of the instance id of the player notification manager. */ + public static final String EXTRA_INSTANCE_ID = "INSTANCE_ID"; /** * Visibility of notification on the lock screen. One of {@link @@ -264,6 +281,8 @@ public class PlayerNotificationManager { private static final long MAX_POSITION_FOR_SEEK_TO_PREVIOUS = 3000; + private static int instanceIdCounter; + private final Context context; private final String channelId; private final int notificationId; @@ -276,6 +295,7 @@ public class PlayerNotificationManager { private final NotificationBroadcastReceiver notificationBroadcastReceiver; private final Map playbackActions; private final Map customActions; + private final int instanceId; private @Nullable Player player; private ControlDispatcher controlDispatcher; @@ -368,6 +388,7 @@ public class PlayerNotificationManager { this.mediaDescriptionAdapter = mediaDescriptionAdapter; this.customActionReceiver = customActionReceiver; this.controlDispatcher = new DefaultControlDispatcher(); + instanceId = instanceIdCounter++; mainHandler = new Handler(Looper.getMainLooper()); notificationManager = NotificationManagerCompat.from(context); playerListener = new PlayerListener(); @@ -389,13 +410,13 @@ public class PlayerNotificationManager { visibility = NotificationCompat.VISIBILITY_PUBLIC; // initialize actions - playbackActions = createPlaybackActions(context); + playbackActions = createPlaybackActions(context, instanceId); for (String action : playbackActions.keySet()) { intentFilter.addAction(action); } customActions = customActionReceiver != null - ? customActionReceiver.createCustomActions(context) + ? customActionReceiver.createCustomActions(context, instanceId) : Collections.emptyMap(); for (String action : customActions.keySet()) { intentFilter.addAction(action); @@ -832,8 +853,8 @@ public class PlayerNotificationManager { *

This method can be safely overridden. However, the names must be of the playback actions * {@link #ACTION_PAUSE}, {@link #ACTION_PLAY}, {@link #ACTION_FAST_FORWARD}, {@link * #ACTION_REWIND}, {@link #ACTION_NEXT} or {@link #ACTION_PREVIOUS}, or a key contained in the - * map returned by {@link CustomActionReceiver#createCustomActions(Context)}. Otherwise the action - * name is ignored. + * map returned by {@link CustomActionReceiver#createCustomActions(Context, int)}. Otherwise the + * action name is ignored. */ protected List getActions(Player player) { boolean isPlayingAd = player.isPlayingAd(); @@ -887,64 +908,62 @@ public class PlayerNotificationManager { : (playActionIndex != -1 ? new int[] {playActionIndex} : new int[0]); } - private static Map createPlaybackActions(Context context) { + private static Map createPlaybackActions( + Context context, int instanceId) { Map actions = new HashMap<>(); - Intent playIntent = new Intent(ACTION_PLAY).setPackage(context.getPackageName()); actions.put( ACTION_PLAY, new NotificationCompat.Action( R.drawable.exo_notification_play, context.getString(R.string.exo_controls_play_description), - PendingIntent.getBroadcast(context, 0, playIntent, PendingIntent.FLAG_CANCEL_CURRENT))); - Intent pauseIntent = new Intent(ACTION_PAUSE).setPackage(context.getPackageName()); + createBroadcastIntent(ACTION_PLAY, context, instanceId))); actions.put( ACTION_PAUSE, new NotificationCompat.Action( R.drawable.exo_notification_pause, context.getString(R.string.exo_controls_pause_description), - PendingIntent.getBroadcast( - context, 0, pauseIntent, PendingIntent.FLAG_CANCEL_CURRENT))); - Intent stopIntent = new Intent(ACTION_STOP).setPackage(context.getPackageName()); + createBroadcastIntent(ACTION_PAUSE, context, instanceId))); actions.put( ACTION_STOP, new NotificationCompat.Action( R.drawable.exo_notification_stop, context.getString(R.string.exo_controls_stop_description), - PendingIntent.getBroadcast(context, 0, stopIntent, PendingIntent.FLAG_CANCEL_CURRENT))); - Intent rewindIntent = new Intent(ACTION_REWIND).setPackage(context.getPackageName()); + createBroadcastIntent(ACTION_STOP, context, instanceId))); actions.put( ACTION_REWIND, new NotificationCompat.Action( R.drawable.exo_notification_rewind, context.getString(R.string.exo_controls_rewind_description), - PendingIntent.getBroadcast( - context, 0, rewindIntent, PendingIntent.FLAG_CANCEL_CURRENT))); - Intent fastForwardIntent = new Intent(ACTION_FAST_FORWARD).setPackage(context.getPackageName()); + createBroadcastIntent(ACTION_REWIND, context, instanceId))); actions.put( ACTION_FAST_FORWARD, new NotificationCompat.Action( R.drawable.exo_notification_fastforward, context.getString(R.string.exo_controls_fastforward_description), - PendingIntent.getBroadcast( - context, 0, fastForwardIntent, PendingIntent.FLAG_CANCEL_CURRENT))); - Intent previousIntent = new Intent(ACTION_PREVIOUS).setPackage(context.getPackageName()); + createBroadcastIntent(ACTION_FAST_FORWARD, context, instanceId))); actions.put( ACTION_PREVIOUS, new NotificationCompat.Action( R.drawable.exo_notification_previous, context.getString(R.string.exo_controls_previous_description), - PendingIntent.getBroadcast( - context, 0, previousIntent, PendingIntent.FLAG_CANCEL_CURRENT))); - Intent nextIntent = new Intent(ACTION_NEXT).setPackage(context.getPackageName()); + createBroadcastIntent(ACTION_PREVIOUS, context, instanceId))); actions.put( ACTION_NEXT, new NotificationCompat.Action( R.drawable.exo_notification_next, context.getString(R.string.exo_controls_next_description), - PendingIntent.getBroadcast(context, 0, nextIntent, PendingIntent.FLAG_CANCEL_CURRENT))); + createBroadcastIntent(ACTION_NEXT, context, instanceId))); return actions; } + private static PendingIntent createBroadcastIntent( + String action, Context context, int instanceId) { + Intent intent = new Intent(action).setPackage(context.getPackageName()); + intent.putExtra(EXTRA_INSTANCE_ID, instanceId); + return PendingIntent.getBroadcast( + context, instanceId, intent, PendingIntent.FLAG_CANCEL_CURRENT); + } + private class PlayerListener implements Player.EventListener { @Override @@ -999,7 +1018,9 @@ public class PlayerNotificationManager { @Override public void onReceive(Context context, Intent intent) { Player player = PlayerNotificationManager.this.player; - if (player == null || !isNotificationStarted) { + if (player == null + || !isNotificationStarted + || intent.getIntExtra(EXTRA_INSTANCE_ID, instanceId) != instanceId) { return; } String action = intent.getAction();