Allow an app to decide to not start the service
Once a service is started as a foreground service, it must be started into the foreground. This means an app can not suppress a play command arriving from the `MediaButtonReceiver` once the receiver has started the service. This change adds a method to the `MediaButtonReceiver` that allows app to suppress starting the service to not get into this situation of wanting to suppress the play command after the service is already started. Issue: androidx/media#1528 PiperOrigin-RevId: 650280025
This commit is contained in:
parent
2377d7556f
commit
06d61ffaaa
@ -45,6 +45,12 @@
|
||||
* Muxers:
|
||||
* IMA extension:
|
||||
* Session:
|
||||
* Add `MediaButtonReceiver.shouldStartForegroundService(Intent)` to allow
|
||||
apps to suppress a play command coming in for playback resumption by
|
||||
overriding this method. By default, the service is always started and
|
||||
playback can't be suppressed without the system crashing the service
|
||||
with a `ForegroundServiceDidNotStartInTimeException`
|
||||
([#1528](https://github.com/google/ExoPlayer/issues/1528)).
|
||||
* UI:
|
||||
* Downloads:
|
||||
* OkHttp Extension:
|
||||
|
@ -118,11 +118,16 @@ public class MediaButtonReceiver extends BroadcastReceiver {
|
||||
return;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
KeyEvent keyEvent = checkNotNull(intent.getExtras()).getParcelable(Intent.EXTRA_KEY_EVENT);
|
||||
if (keyEvent == null
|
||||
|| keyEvent.getAction() != KeyEvent.ACTION_DOWN
|
||||
|| keyEvent.getRepeatCount() != 0) {
|
||||
// Only handle the intent once with the earliest key event that arrives.
|
||||
return;
|
||||
}
|
||||
if (Util.SDK_INT >= 26) {
|
||||
@Nullable
|
||||
KeyEvent keyEvent = checkNotNull(intent.getExtras()).getParcelable(Intent.EXTRA_KEY_EVENT);
|
||||
if (keyEvent != null
|
||||
&& keyEvent.getKeyCode() != KeyEvent.KEYCODE_MEDIA_PLAY
|
||||
if (keyEvent.getKeyCode() != KeyEvent.KEYCODE_MEDIA_PLAY
|
||||
&& keyEvent.getKeyCode() != KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
|
||||
// Starting with Android 8 (API 26), the service must be started immediately in the
|
||||
// foreground when being started. Also starting with Android 8, the system sends media
|
||||
@ -143,6 +148,14 @@ public class MediaButtonReceiver extends BroadcastReceiver {
|
||||
ComponentName mediaButtonServiceComponentName = getServiceComponentByAction(context, action);
|
||||
if (mediaButtonServiceComponentName != null) {
|
||||
intent.setComponent(mediaButtonServiceComponentName);
|
||||
if (!shouldStartForegroundService(intent)) {
|
||||
Log.i(
|
||||
TAG,
|
||||
"onReceive(Intent) does not start the media button event target service into the"
|
||||
+ " foreground on app request: "
|
||||
+ mediaButtonServiceComponentName.getClassName());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ContextCompat.startForegroundService(context, intent);
|
||||
} catch (/* ForegroundServiceStartNotAllowedException */ IllegalStateException e) {
|
||||
@ -161,6 +174,28 @@ public class MediaButtonReceiver extends BroadcastReceiver {
|
||||
"Could not find any Service that handles any of the actions " + Arrays.toString(ACTIONS));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether to start the {@linkplain Intent#getComponent() media button event target
|
||||
* service} into the foreground.
|
||||
*
|
||||
* <p>Returns true by default. Apps can override this method to decide to not start a service when
|
||||
* receiving an event with {@link KeyEvent#KEYCODE_MEDIA_PLAY} or {@link
|
||||
* KeyEvent#KEYCODE_MEDIA_PLAY_PAUSE} that should be suppressed.
|
||||
*
|
||||
* <p>Note: Once the service is started into the foreground by the receiver, the app must start
|
||||
* playback to get into the foreground or the system will crash the service with a {@code
|
||||
* ForegroundServiceDidNotStartInTimeException} or an {@link IllegalStateException}.
|
||||
*
|
||||
* @param intent The intent that {@linkplain #onReceive(Context, Intent) was received by the media
|
||||
* button event receiver}.
|
||||
* @return true if the service should be {@linkplain ContextCompat#startForegroundService(Context,
|
||||
* Intent) started as a foreground service}. If false is returned the service is not started
|
||||
* and the receiver call is a no-op.
|
||||
*/
|
||||
protected boolean shouldStartForegroundService(Intent intent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when an exception is thrown when calling {@link
|
||||
* Context#startForegroundService(Intent)} as a result of receiving a media button event.
|
||||
|
Loading…
x
Reference in New Issue
Block a user