MediaSessionService
abstract class MediaSessionService : Service
| kotlin.Any | ||||
| ↳ | android.content.Context | |||
| ↳ | android.content.ContextWrapper | |||
| ↳ | android.app.Service | |||
| ↳ | androidx.media3.session.MediaSessionService |
MediaLibraryService |
Superclass to be extended by services hosting |
Superclass to be extended by services hosting media sessions.
It's highly recommended for an app to use this class if media playback should continue while in the background. The service allows other apps to know that your app supports MediaSession even when your app isn't running. This way, a user voice command may be able start your app to play media.
To extend this class, declare the intent filter in your AndroidManifest.xml:
<service android:name="NameOfYourService" android:foregroundServiceType="mediaPlayback" android:exported="true"> <intent-filter> <action android:name="androidx.media3.session.MediaSessionService"/> </intent-filter> </service>
You may also declare the action android.media.browse.MediaBrowserService for compatibility with android.support.v4.media.MediaBrowserCompat. This service can handle the case automatically.
It's recommended for an app to have a single service declared in the manifest. Otherwise, your app might be shown twice in the list of the controller apps, or another app might fail to pick the right service when it wants to start a playback on this app. If you want to provide multiple sessions, take a look at Supporting Multiple Sessions.
Topics covered here:
Service Lifecycle
A media session service is a bound service and its foreground service type must include mediaPlayback. When a MediaController is created for the service, the controller binds to the service. onGetSession will be called from onBind.
After binding, the session's onConnect will be called to accept or reject the connection request from the controller. If it's accepted, the controller will be available and keep the binding. If it's rejected, the controller will unbind.
onUpdateNotification will be called whenever a notification needs to be shown, updated or cancelled. The default implementation will display notifications using a default UI or using a MediaNotification.Provider that's set with setMediaNotificationProvider. In addition, when playback starts, the service will become a foreground service. It's required to keep the playback after the controller is destroyed. The service will become a background service when all playbacks are stopped. Apps targeting SDK_INT >= 28 must request the permission, FOREGROUND_SERVICE, in order to make the service foreground. You can control when to show or hide notifications by overriding onUpdateNotification. In this case, you must also start or stop the service from the foreground, when playback starts or stops respectively.
The service will be destroyed when all sessions are released, or no controller is binding to the service while the service is in the background.
Supporting Multiple Sessions
Generally, multiple sessions aren't necessary for most media apps. One exception is if your app can play multiple media contents at the same time, but only for playback of video-only media or remote playback, since the audio focus policy recommends not playing multiple audio contents at the same time. Also, keep in mind that multiple media sessions would make Android Auto and Bluetooth devices with a display to show your apps multiple times, because they list up media sessions, not media apps.
However, if you're capable of handling multiple playbacks and want to keep their sessions while the app is in the background, create multiple sessions and add them to this service with addSession.
Note that a MediaController can be created with SessionToken to connect to a session in this service. In that case, onGetSession will be called to decide which session to handle the connection request. Pick the best session among the added sessions, or create a new session and return it from onGetSession.
Summary
Nested types |
|---|
@UnstableApiListener for |
@UnstableApiThe behavior for showing notifications when the |
Constants |
|
|---|---|
const Long |
The default timeout for a session to stay in a foreground service state after it paused, stopped, failed or ended. |
const String! |
SERVICE_INTERFACE = "androidx.media3.session.MediaSessionService"The action for |
const Int |
Shows a notification when the |
const Int |
Always show a notification when the |
const Int |
Never show a notification when the |
Public constructors |
|---|
|
Creates a service. |
Public functions |
|
|---|---|
Unit |
addSession(session: MediaSession!)Adds a |
Unit |
Clears the |
(Mutable)List<MediaSession!>! |
Returns the list of |
Boolean |
Returns whether there is a session with ongoing user-engaged playback that is run in a foreground service. |
Boolean |
isSessionAdded(session: MediaSession!)Returns whether |
IBinder? |
Called when a component is about to bind to the service. |
Unit |
Called when the service is created. |
Unit |
Called when the service is no longer used and is being removed. |
abstract MediaSession? |
onGetSession(controllerInfo: MediaSession.ControllerInfo!)Called when a |
Int |
@CallSuperCalled when a component calls |
Unit |
onTaskRemoved(rootIntent: Intent?)This method can be overridden to customize the behavior of when the app is dismissed from the recent apps. |
Unit |
This function is deprecated. Use |
Unit |
onUpdateNotification(Called when a notification needs to be updated. |
Unit |
Pauses the player of each session managed by the service, ensures the foreground service is stopped, and calls |
Unit |
removeSession(session: MediaSession!)Removes a |
Unit |
@UnstableApiSets the timeout for a session to stay in a foreground service state after it paused, stopped, failed or ended. |
Unit |
@UnstableApiSets the |
Unit |
@UnstableApiSets whether and when a notification for a |
Unit |
Manually trigger a notification update. |
Protected functions |
|
|---|---|
Unit |
@UnstableApiSets the |
Inherited Constants |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Constants
DEFAULT_FOREGROUND_SERVICE_TIMEOUT_MS
@UnstableApi
const val DEFAULT_FOREGROUND_SERVICE_TIMEOUT_MS = 600000: Long
The default timeout for a session to stay in a foreground service state after it paused, stopped, failed or ended.
SERVICE_INTERFACE
const val SERVICE_INTERFACE = "androidx.media3.session.MediaSessionService": String!
The action for Intent filter that must be declared by the service.
SHOW_NOTIFICATION_FOR_IDLE_PLAYER_AFTER_STOP_OR_ERROR
@UnstableApi
const val SHOW_NOTIFICATION_FOR_IDLE_PLAYER_AFTER_STOP_OR_ERROR = 3: Int
Shows a notification when the Player is in STATE_IDLE due to stop or an error, has media, and the notification wasn't explicitly dismissed.
SHOW_NOTIFICATION_FOR_IDLE_PLAYER_ALWAYS
@UnstableApi
const val SHOW_NOTIFICATION_FOR_IDLE_PLAYER_ALWAYS = 1: Int
Always show a notification when the Player is in STATE_IDLE, has media, and the notification wasn't explicitly dismissed.
SHOW_NOTIFICATION_FOR_IDLE_PLAYER_NEVER
@UnstableApi
const val SHOW_NOTIFICATION_FOR_IDLE_PLAYER_NEVER = 2: Int
Never show a notification when the Player is in STATE_IDLE.
Public constructors
Public functions
addSession
fun addSession(session: MediaSession!): Unit
Adds a MediaSession to this service. This is not necessary for most media apps. See Supporting Multiple Sessions for details.
The added session will be removed automatically when the session is released.
This method can be called from any thread.
| Parameters | |
|---|---|
session: MediaSession! |
A session to be added. |
| See also | |
|---|---|
removeSession |
|
getSessions |
clearListener
@UnstableApi
fun clearListener(): Unit
Clears the listener.
This method can be called from any thread.
getSessions
fun getSessions(): (Mutable)List<MediaSession!>!
Returns the list of sessions that you've added to this service via addSession or onGetSession.
This method can be called from any thread.
isPlaybackOngoing
@UnstableApi
fun isPlaybackOngoing(): Boolean
Returns whether there is a session with ongoing user-engaged playback that is run in a foreground service.
It is only possible to terminate the service with stopSelf if this method returns false.
Note that sessions are kept in foreground and this method returns true for the foreground service timeout after they paused, stopped, failed or ended. Use pauseAllPlayersAndStopSelf to pause all ongoing playbacks immediately and terminate the service.
This method must be called on the main thread.
isSessionAdded
fun isSessionAdded(session: MediaSession!): Boolean
Returns whether session has been added to this service via addSession or onGetSession.
This method can be called from any thread.
onBind
@CallSuper
fun onBind(intent: Intent?): IBinder?
Called when a component is about to bind to the service.
The default implementation handles the incoming requests from controllers. In this case, the intent will have the action SERVICE_INTERFACE. Override this method if this service also needs to handle actions other than SERVICE_INTERFACE.
This method will be called on the main thread.
onCreate
@CallSuper
fun onCreate(): Unit
Called when the service is created.
Override this method if you need your own initialization.
This method will be called on the main thread.
onDestroy
@CallSuper
fun onDestroy(): Unit
Called when the service is no longer used and is being removed.
Override this method if you need your own clean up.
This method will be called on the main thread.
onGetSession
abstract fun onGetSession(controllerInfo: MediaSession.ControllerInfo!): MediaSession?
Called when a MediaController is created with this service's SessionToken. Return a MediaSession that the controller will connect to, or null to reject the connection request.
Note: This method must not be called directly by app code.
The service automatically maintains the returned sessions. In other words, a session returned by this method will be added to the service, and removed from the service when the session is closed. You don't need to manually call addSession nor removeSession.
There are two special cases where the getPackageName returns a non-existent package name:
- When the service is started by a media button event, the package name will be
ACTION_MEDIA_BUTTON. If you want to allow the service to be started by media button events, do not returnnull. - When a legacy
android.media.browse.MediaBrowseror aandroid.support.v4.media.MediaBrowserCompattries to connect, the package name will beSERVICE_INTERFACE. If you want to allow the service to be bound by the legacy media browsers, do not returnnull.
For those special cases, the values returned by getUid and getConnectionHints have no meaning.
This method will be called on the main thread.
| Parameters | |
|---|---|
controllerInfo: MediaSession.ControllerInfo! |
The information of the controller that is trying to connect. |
| Returns | |
|---|---|
MediaSession? |
A |
| See also | |
|---|---|
MediaSession.Builder |
|
getSessions |
onStartCommand
@CallSuper
fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int
Called when a component calls startService.
The default implementation handles the incoming media button events. In this case, the intent will have the action ACTION_MEDIA_BUTTON. Override this method if this service also needs to handle actions other than ACTION_MEDIA_BUTTON.
This method will be called on the main thread.
onTaskRemoved
fun onTaskRemoved(rootIntent: Intent?): Unit
This method can be overridden to customize the behavior of when the app is dismissed from the recent apps.
The default behavior is that if playback is ongoing, which means the service is already running in the foreground, and at least one media session is playing, the service is kept running. Otherwise, playbacks are paused and the service is stopped by calling pauseAllPlayersAndStopSelf which terminates the service lifecycle and triggers onDestroy that an app can override to release the sessions and other resources.
An app can safely override this method without calling super to implement a different behaviour, for instance unconditionally calling pauseAllPlayersAndStopSelf to stop the service even when playing. However, if playback is not ongoing, the service must be terminated otherwise the service will be crashed and restarted by the system.
Note: The service can't be stopped until all media controllers have been unbound. Hence, an app needs to release all internal controllers that have connected to the service (for instance from an activity in onStop). If an app allows external apps to connect a MediaController to the service, these controllers also need to be disconnected. In such a scenario of external bound clients, an app needs to override this method to release the session before calling stopSelf.
onUpdateNotification
fun onUpdateNotification(
session: MediaSession!,
startInForegroundRequired: Boolean
): Unit
Called when a notification needs to be updated. Override this method to show or cancel your own notifications.
Note: This method must not be called directly by app code.
This method is called whenever the service has detected a change that requires to show, update or cancel a notification with a flag startInForegroundRequired suggested by the service whether starting in the foreground is required. The method will be called on the application thread of the app that the service belongs to.
Override this method to create your own notification and customize the foreground handling of your service.
The default implementation will present a default notification or the notification provided by the MediaNotification.Provider that is set by the app. Further, the service is started in the foreground when playback is ongoing and put back into background otherwise.
Apps targeting SDK_INT >= 28 must request the permission, FOREGROUND_SERVICE.
This method will be called on the main thread.
| Parameters | |
|---|---|
session: MediaSession! |
A session that needs notification update. |
startInForegroundRequired: Boolean |
Whether the service is required to start in the foreground. |
pauseAllPlayersAndStopSelf
@UnstableApi
fun pauseAllPlayersAndStopSelf(): Unit
Pauses the player of each session managed by the service, ensures the foreground service is stopped, and calls stopSelf.
This terminates the service lifecycle and triggers onDestroy that an app can override to release the sessions and other resources.
This method must be called on the main thread.
removeSession
fun removeSession(session: MediaSession!): Unit
Removes a MediaSession from this service. This is not necessary for most media apps. See Supporting Multiple Sessions for details.
This method can be called from any thread.
| Parameters | |
|---|---|
session: MediaSession! |
A session to be removed. |
| See also | |
|---|---|
addSession |
|
getSessions |
setForegroundServiceTimeoutMs
@UnstableApi
fun setForegroundServiceTimeoutMs(foregroundServiceTimeoutMs: Long): Unit
Sets the timeout for a session to stay in a foreground service state after it paused, stopped, failed or ended.
Can only be called once the Context of the service is initialized in onCreate.
Has no effect on already running timeouts.
The default and maximum value is DEFAULT_FOREGROUND_SERVICE_TIMEOUT_MS. If a larger value is provided, it will be clamped down to DEFAULT_FOREGROUND_SERVICE_TIMEOUT_MS.
This method must be called on the main thread.
| Parameters | |
|---|---|
foregroundServiceTimeoutMs: Long |
The timeout in milliseconds. |
setListener
@UnstableApi
fun setListener(listener: MediaSessionService.Listener!): Unit
Sets the listener.
This method can be called from any thread.
setShowNotificationForIdlePlayer
@UnstableApi
fun setShowNotificationForIdlePlayer(
@MediaSessionService.ShowNotificationForIdlePlayerMode showNotificationForIdlePlayerMode: Int
): Unit
Sets whether and when a notification for a Player in STATE_IDLE should be shown.
| Parameters | |
|---|---|
@MediaSessionService.ShowNotificationForIdlePlayerMode showNotificationForIdlePlayerMode: Int |
triggerNotificationUpdate
@UnstableApi
fun triggerNotificationUpdate(): Unit
Manually trigger a notification update.
In most cases, this should not be required unless an external event that can't be detected by the session itself requires to update the notification.
Protected functions
setMediaNotificationProvider
@UnstableApi
protected fun setMediaNotificationProvider(
mediaNotificationProvider: MediaNotification.Provider!
): Unit
Sets the MediaNotification.Provider to customize notifications.
This method can be called from any thread.