mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
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:
|
* Muxers:
|
||||||
* IMA extension:
|
* IMA extension:
|
||||||
* Session:
|
* 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:
|
* UI:
|
||||||
* Downloads:
|
* Downloads:
|
||||||
* OkHttp Extension:
|
* OkHttp Extension:
|
||||||
|
@ -118,11 +118,16 @@ public class MediaButtonReceiver extends BroadcastReceiver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Util.SDK_INT >= 26) {
|
|
||||||
@Nullable
|
@Nullable
|
||||||
KeyEvent keyEvent = checkNotNull(intent.getExtras()).getParcelable(Intent.EXTRA_KEY_EVENT);
|
KeyEvent keyEvent = checkNotNull(intent.getExtras()).getParcelable(Intent.EXTRA_KEY_EVENT);
|
||||||
if (keyEvent != null
|
if (keyEvent == null
|
||||||
&& keyEvent.getKeyCode() != KeyEvent.KEYCODE_MEDIA_PLAY
|
|| 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) {
|
||||||
|
if (keyEvent.getKeyCode() != KeyEvent.KEYCODE_MEDIA_PLAY
|
||||||
&& keyEvent.getKeyCode() != KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
|
&& keyEvent.getKeyCode() != KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
|
||||||
// Starting with Android 8 (API 26), the service must be started immediately in the
|
// 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
|
// 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);
|
ComponentName mediaButtonServiceComponentName = getServiceComponentByAction(context, action);
|
||||||
if (mediaButtonServiceComponentName != null) {
|
if (mediaButtonServiceComponentName != null) {
|
||||||
intent.setComponent(mediaButtonServiceComponentName);
|
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 {
|
try {
|
||||||
ContextCompat.startForegroundService(context, intent);
|
ContextCompat.startForegroundService(context, intent);
|
||||||
} catch (/* ForegroundServiceStartNotAllowedException */ IllegalStateException e) {
|
} 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));
|
"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
|
* This method is called when an exception is thrown when calling {@link
|
||||||
* Context#startForegroundService(Intent)} as a result of receiving a media button event.
|
* Context#startForegroundService(Intent)} as a result of receiving a media button event.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user