6868import android .os .SystemClock ;
6969import android .text .TextUtils ;
7070import android .view .KeyEvent ;
71+ import androidx .annotation .NonNull ;
7172import androidx .annotation .Nullable ;
7273import androidx .annotation .RequiresApi ;
7374import androidx .core .util .ObjectsCompat ;
136137 private final MediaSessionCompat sessionCompat ;
137138 @ Nullable private final MediaButtonReceiver runtimeBroadcastReceiver ;
138139 @ Nullable private final ComponentName broadcastReceiverComponentName ;
140+ private boolean optOutOfMediaButtonPlaybackResumption ;
139141 @ Nullable private VolumeProviderCompat volumeProviderCompat ;
140142 private final boolean playIfSuppressed ;
141143
@@ -191,7 +193,7 @@ public MediaSessionLegacyStub(
191193 broadcastReceiverComponentName = queryPackageManagerForMediaButtonReceiver (context );
192194 @ Nullable ComponentName receiverComponentName = broadcastReceiverComponentName ;
193195 boolean isReceiverComponentAService = false ;
194- if (receiverComponentName == null || SDK_INT < 31 ) {
196+ if (receiverComponentName == null && SDK_INT < 26 ) {
195197 // Below API 26, media button events are sent to the receiver at runtime also. We always want
196198 // these to arrive at the service at runtime. release() then set the receiver for restart if
197199 // available.
@@ -201,37 +203,35 @@ public MediaSessionLegacyStub(
201203 receiverComponentName =
202204 getServiceComponentByAction (context , MediaSessionService .SERVICE_INTERFACE );
203205 }
204- isReceiverComponentAService =
205- receiverComponentName != null
206- && !Objects .equals (receiverComponentName , broadcastReceiverComponentName );
206+ isReceiverComponentAService = receiverComponentName != null ;
207207 }
208- Intent intent = new Intent (Intent .ACTION_MEDIA_BUTTON , sessionUri );
209- PendingIntent mediaButtonIntent ;
210- if (receiverComponentName == null ) {
208+ final PendingIntent mediaButtonIntent ;
209+ if (receiverComponentName == null && SDK_INT < 26 ) {
211210 // Neither a media button receiver from the app manifest nor a service available that could
212211 // handle media button events. Create a runtime receiver and a pending intent for it.
213212 runtimeBroadcastReceiver = new MediaButtonReceiver ();
214213 IntentFilter filter = new IntentFilter (Intent .ACTION_MEDIA_BUTTON );
215214 filter .addDataScheme (castNonNull (sessionUri .getScheme ()));
216215 Util .registerReceiverNotExported (context , runtimeBroadcastReceiver , filter );
217216 // Create a pending intent to be broadcast to the receiver.
217+ Intent intent = new Intent (Intent .ACTION_MEDIA_BUTTON , sessionUri );
218218 intent .setPackage (context .getPackageName ());
219219 mediaButtonIntent =
220220 PendingIntent .getBroadcast (
221221 context , /* requestCode= */ 0 , intent , PENDING_INTENT_FLAG_MUTABLE );
222- // Creates a fake ComponentName for MediaSessionCompat in pre-L or without a service.
223- receiverComponentName = new ComponentName (context , context .getClass ());
224222 } else {
225- intent .setComponent (receiverComponentName );
226- mediaButtonIntent =
227- isReceiverComponentAService
228- ? (SDK_INT >= 26
229- ? PendingIntent .getForegroundService (
230- context , /* requestCode= */ 0 , intent , PENDING_INTENT_FLAG_MUTABLE )
231- : PendingIntent .getService (
232- context , /* requestCode= */ 0 , intent , PENDING_INTENT_FLAG_MUTABLE ))
233- : PendingIntent .getBroadcast (
234- context , /* requestCode= */ 0 , intent , PENDING_INTENT_FLAG_MUTABLE );
223+ if (receiverComponentName != null && SDK_INT < 31 ) {
224+ Intent intent = new Intent (Intent .ACTION_MEDIA_BUTTON , sessionUri );
225+ intent .setComponent (receiverComponentName );
226+ mediaButtonIntent =
227+ isReceiverComponentAService
228+ ? PendingIntent .getService (
229+ context , /* requestCode= */ 0 , intent , PENDING_INTENT_FLAG_MUTABLE )
230+ : PendingIntent .getBroadcast (
231+ context , /* requestCode= */ 0 , intent , PENDING_INTENT_FLAG_MUTABLE );
232+ } else {
233+ mediaButtonIntent = null ;
234+ }
235235 runtimeBroadcastReceiver = null ;
236236 }
237237
@@ -243,7 +243,6 @@ public MediaSessionLegacyStub(
243243 new MediaSessionCompat (
244244 context ,
245245 sessionCompatId ,
246- SDK_INT < 31 ? receiverComponentName : null ,
247246 SDK_INT < 31 ? mediaButtonIntent : null ,
248247 /* sessionInfo= */ tokenExtras );
249248 if (SDK_INT >= 31 && broadcastReceiverComponentName != null ) {
@@ -261,6 +260,15 @@ public MediaSessionLegacyStub(
261260 sessionCompat .setCallback (thisRef , handler );
262261 }
263262
263+ public void setOptOutOfMediaButtonPlaybackResumption (
264+ boolean optOutOfMediaButtonPlaybackResumption ) {
265+ if (broadcastReceiverComponentName == null ) {
266+ throw new IllegalStateException (
267+ "Media button playback resumption is not enabled, cannot opt out." );
268+ }
269+ this .optOutOfMediaButtonPlaybackResumption = optOutOfMediaButtonPlaybackResumption ;
270+ }
271+
264272 /**
265273 * Sets the available commands for the platform session.
266274 *
@@ -460,22 +468,18 @@ public void start() {
460468
461469 @ SuppressWarnings ("PendingIntentMutability" ) // We can't use SaferPendingIntent.
462470 public void release () {
463- if (SDK_INT < 31 ) {
464- if (broadcastReceiverComponentName == null ) {
465- // No broadcast receiver available. Playback resumption not supported.
466- setMediaButtonReceiver (sessionCompat , /* mediaButtonReceiverIntent= */ null );
467- } else {
468- // Override the runtime receiver with the broadcast receiver for playback resumption.
469- Intent intent = new Intent (Intent .ACTION_MEDIA_BUTTON , sessionImpl .getUri ());
470- intent .setComponent (broadcastReceiverComponentName );
471- PendingIntent mediaButtonReceiverIntent =
472- PendingIntent .getBroadcast (
473- sessionImpl .getContext (),
474- /* requestCode= */ 0 ,
475- intent ,
476- PENDING_INTENT_FLAG_MUTABLE );
477- setMediaButtonReceiver (sessionCompat , mediaButtonReceiverIntent );
478- }
471+ if ((broadcastReceiverComponentName == null && SDK_INT < 26 )
472+ || optOutOfMediaButtonPlaybackResumption ) {
473+ // No broadcast receiver available. Playback resumption not supported.
474+ setMediaButtonReceiver (sessionCompat , /* mediaButtonReceiverIntent= */ null );
475+ } else if (SDK_INT < 26 ) {
476+ // Override the runtime receiver with the broadcast receiver for playback resumption.
477+ Intent intent = new Intent (Intent .ACTION_MEDIA_BUTTON , sessionImpl .getUri ());
478+ intent .setComponent (broadcastReceiverComponentName );
479+ PendingIntent mediaButtonReceiverIntent =
480+ PendingIntent .getBroadcast (
481+ sessionImpl .getContext (), /* requestCode= */ 0 , intent , PENDING_INTENT_FLAG_MUTABLE );
482+ setMediaButtonReceiver (sessionCompat , mediaButtonReceiverIntent );
479483 }
480484 if (runtimeBroadcastReceiver != null ) {
481485 sessionImpl .getContext ().unregisterReceiver (runtimeBroadcastReceiver );
@@ -2080,7 +2084,7 @@ public void onReceive(Context context, Intent intent) {
20802084 @ RequiresApi (31 )
20812085 private static final class Api31 {
20822086 public static void setMediaButtonBroadcastReceiver (
2083- MediaSessionCompat mediaSessionCompat , ComponentName broadcastReceiver ) {
2087+ MediaSessionCompat mediaSessionCompat , @ NonNull ComponentName broadcastReceiver ) {
20842088 try {
20852089 ((android .media .session .MediaSession ) checkNotNull (mediaSessionCompat .getMediaSession ()))
20862090 .setMediaButtonBroadcastReceiver (broadcastReceiver );
0 commit comments