Class: BaseMediaHandler
Defined in: packages/media-session/src/handler.ts:20
No-op implementation of every MediaHandler method.
Subclass and override only what the app supports; the set the app advertises
is PlaybackState.capabilities, so a no-op here is never reachable from a
correctly-broadcasting app — it exists so adding a method to the interface is
not a breaking change for every consumer.
Implements
Constructors
Constructor
new BaseMediaHandler(): BaseMediaHandler;
Returns
BaseMediaHandler
Methods
customAction()
customAction(_name: string, _extras?: Record<string, unknown>): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:60
One of PlaybackState.customActions was pressed.
Android only. MPRemoteCommandCenter's command set is fixed and carries
no app-defined identifier, so no iOS remote surface can invoke a custom
action and this is never called there by the session — see
MediaCustomAction. Call it from your own UI if you want one code
path on both platforms.
Parameters
| Parameter | Type |
|---|---|
_name | string |
_extras? | Record<string, unknown> |
Returns
void | Promise<void>
Implementation of
getChildren()
getChildren(_parentId: string): Promise<BrowseItem[]>;
Defined in: packages/media-session/src/handler.ts:106
Default: an empty tree.
Correct by construction rather than by luck: an empty list is what Google asks a browse node with no children to return, so an app that never implements this shows a car an app with nothing in it — not an error, not a crash, and not a browse entry that does nothing when tapped.
Parameters
| Parameter | Type |
|---|---|
_parentId | string |
Returns
Promise<BrowseItem[]>
Implementation of
getMediaItem()
getMediaItem(_id: string): Promise<BrowseItem | undefined>;
Defined in: packages/media-session/src/handler.ts:111
Default: no such item. See getChildren.
Parameters
| Parameter | Type |
|---|---|
_id | string |
Returns
Promise<BrowseItem | undefined>
Implementation of
onAdjustDeviceVolume()
onAdjustDeviceVolume(_direction: RemoteVolumeDirection): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:54
Default: nothing. Only ever called for a volumeControl: 'relative'
device — see MediaHandler.onAdjustDeviceVolume.
Parameters
| Parameter | Type |
|---|---|
_direction | RemoteVolumeDirection |
Returns
void | Promise<void>
Implementation of
MediaHandler.onAdjustDeviceVolume
onPlaybackResumption()
onPlaybackResumption(): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:82
Default: nothing.
Correct by design — by the time this fires the service has already put the
persisted track on screen and the user's play is queued for replay on
this same handler. Resumption works without a line of code here; the hook
exists for logging and for work that must happen before that replayed
play() (refreshing an expired stream token, say).
Returns
void | Promise<void>
Implementation of
MediaHandler.onPlaybackResumption
onSessionError()
onSessionError(error: SessionError): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:94
The one method here that is not a no-op, and the exception is the point: every other default is silent because the app advertises what it supports, but a silent default on an error channel would swallow the very failures the channel was added to stop swallowing (CLAUDE.md principle 6).
So the default logs — the same floor the service applies to a handler that
does not implement the method at all. Override it to render the failure;
call super.onSessionError(error) if you want the log as well.
Parameters
| Parameter | Type |
|---|---|
error | SessionError |
Returns
void | Promise<void>
Implementation of
onSetDeviceMuted()
onSetDeviceMuted(_muted: boolean): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:58
Default: nothing. See onSetDeviceVolume.
Parameters
| Parameter | Type |
|---|---|
_muted | boolean |
Returns
void | Promise<void>
Implementation of
onSetDeviceVolume()
onSetDeviceVolume(_volume: number): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:49
Default: nothing — and unreachable until the app publishes a remote device
with setRemotePlayback, so an app whose audio never leaves the phone can
ignore these three entirely.
With the usual volumeControl: 'absolute', this is also where a hardware
volume key lands: the library turns the notch into a level first (see
onAdjustDeviceVolume), so an absolute backend needs this method and
nothing else.
Parameters
| Parameter | Type |
|---|---|
_volume | number |
Returns
void | Promise<void>
Implementation of
MediaHandler.onSetDeviceVolume
onSetRepeatMode()
onSetRepeatMode(_mode: MediaRepeatMode): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:36
Default: nothing — and unlike the transport methods, doing nothing here is visible. The remote surface's repeat button will spring back to whatever the app last broadcast, because the state only moves when the app moves it. That is the same acknowledge-by-broadcast contract every other command follows; it is only more noticeable because the control is a toggle.
Parameters
| Parameter | Type |
|---|---|
_mode | MediaRepeatMode |
Returns
void | Promise<void>
Implementation of
onSetShuffle()
onSetShuffle(_enabled: boolean): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:38
Default: nothing. See onSetRepeatMode.
Parameters
| Parameter | Type |
|---|---|
_enabled | boolean |
Returns
void | Promise<void>
Implementation of
onSleepTimer()
onSleepTimer(): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:71
Default: nothing.
Correct by design — the pause has already happened natively by the time this is called (see MediaHandler.onSleepTimer), so an app that only wants "stop playing after 30 minutes" needs no code here at all.
Returns
void | Promise<void>
Implementation of
onTaskRemoved()
onTaskRemoved(): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:59
Android only: the app's task was swiped out of Recents.
The native default policy (keep playing if playing, otherwise stop the
service) has already been decided by the time this runs — overriding this
method is for side effects (persistence, analytics), not for changing that
decision. Call stopService() here to force a stop.
Returns
void | Promise<void>
Implementation of
pause()
pause(): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:22
Returns
void | Promise<void>
Implementation of
play()
play(): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:21
Returns
void | Promise<void>
Implementation of
playFromMediaId()
playFromMediaId(id: string): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:129
The second method here that is not a no-op, and for the same reason onSessionError is the first: the default that would be silent is the bug.
A handler that overrides getChildren and forgets this one hands a car a
full browse tree in which every single leaf does nothing when tapped —
no error, no log, no playback (ARCHITECTURE §27). There is nothing this
class can play on the app's behalf, so it says so on the channel the app
already reads.
Overriding it silences the report, which is the point: implementing the method is the fix.
Parameters
| Parameter | Type |
|---|---|
id | string |
Returns
void | Promise<void>
Implementation of
seekTo()
seekTo(_position: number): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:24
Parameters
| Parameter | Type |
|---|---|
_position | number |
Returns
void | Promise<void>
Implementation of
setRate()
setRate(_rate: number): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:28
Parameters
| Parameter | Type |
|---|---|
_rate | number |
Returns
void | Promise<void>
Implementation of
skipToNext()
skipToNext(): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:25
Returns
void | Promise<void>
Implementation of
skipToPrevious()
skipToPrevious(): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:26
Returns
void | Promise<void>
Implementation of
skipToQueueItem()
skipToQueueItem(_index: number): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:27
Play an arbitrary entry of the broadcast queue.
Reached from a remote surface on Android only — Android Auto, Wear, a
car head unit, any controller that renders the queue
(Player.COMMAND_SEEK_TO_MEDIA_ITEM). MPRemoteCommandCenter has no
queue-jump command, so no iOS remote surface can invoke this; it is still
part of the interface because your own UI calls it on both platforms.
Parameters
| Parameter | Type |
|---|---|
_index | number |
Returns
void | Promise<void>
Implementation of
stop()
stop(): void | Promise<void>;
Defined in: packages/media-session/src/handler.ts:23
Release resources. Does NOT end background execution — call stopService() for that.
Returns
void | Promise<void>