Interface: NativePlaybackState
Defined in: packages/media-session/src/specs/media-session.nitro.ts:703
Everything a surface needs to render "now", except the metadata.
Broadcast wholesale (never patched): a partial update would need a merge policy on three platforms, and the app already holds the full state.
Properties
bufferedPosition?
optional bufferedPosition?: number;
Defined in: packages/media-session/src/specs/media-session.nitro.ts:719
Buffered position in ms. Omit when unknown.
Android only. media3 renders it as the secondary bar behind the
scrubber (SimpleBasePlayer.State.setContentBufferedPositionMs). iOS has no
key for it: MPNowPlayingInfoCenter's complete metadata key set was read
for one and the nearest thing,
MPNowPlayingInfoPropertyPlaybackProgress, is documented as a
watched-so-far indicator ("A value of 0.0 indicates the item isn't
watched, while a value of 1.0 indicates the item was fully watched"), not a
buffer level (developer.apple.com/documentation/mediaplayer/mpnowplayinginfocenter,
read 2026-08-16). Broadcasting it on iOS is harmless and renders nothing.
capabilities
capabilities: MediaCapability[];
Defined in: packages/media-session/src/specs/media-session.nitro.ts:723
Commands to accept. See MediaCapability.
compactControlIndices?
optional compactControlIndices?: number[];
Defined in: packages/media-session/src/specs/media-session.nitro.ts:743
Android only: indices into controls that get the ≤3 slots of the collapsed notification. Omit to let the platform take the first three.
Not in the spec doc's sketch, which folded the two concepts together; they
have to be separable because Android 13+ derives the expanded layout from
the session while the compact layout stays an explicit choice
(audio_service calls this androidCompactActionIndices).
iOS has no notion of button layout at all — MPRemoteCommandCenter is a
flat set of commands that are either enabled or not, and the system decides
what to draw — so controls and capabilities are simply unioned there and
this field is ignored.
controls
controls: MediaControl[];
Defined in: packages/media-session/src/specs/media-session.nitro.ts:721
Buttons to offer, in order.
customActions
customActions: MediaCustomAction[];
Defined in: packages/media-session/src/specs/media-session.nitro.ts:728
Extra buttons with app-defined meanings. Android only — see MediaCustomAction for why iOS cannot have them.
errorMessage?
optional errorMessage?: string;
Defined in: packages/media-session/src/specs/media-session.nitro.ts:767
Only meaningful when status === 'error'.
Android only. It becomes the PlaybackException message on the facade
player's state, which a MediaController can read
(PlaybackException.ERROR_CODE_UNSPECIFIED, because the app's error
taxonomy does not map onto media3's codes and guessing one would be worse
than admitting we do not know).
iOS drops it, and there is nowhere to put it. MPNowPlayingInfoCenter
has no error key anywhere in its metadata set and MPRemoteCommandCenter
has no error channel; the whole key space was enumerated
(developer.apple.com/documentation/mediaplayer/mpnowplayinginfocenter, read
2026-08-16). Combined with MediaPlaybackStatus's note that iOS
cannot distinguish error from paused at all, an errored session simply
looks paused on an iOS remote surface. Surface the message in your own UI.
position
position: PositionAnchor;
Defined in: packages/media-session/src/specs/media-session.nitro.ts:705
queueIndex?
optional queueIndex?: number;
Defined in: packages/media-session/src/specs/media-session.nitro.ts:749
Index into the last RnMediaMediaSession.setQueue array that
mediaItem corresponds to. Omit (or -1) when playback is not queue-backed;
Android then presents a single-item timeline built from the media item.
repeatMode
repeatMode: MediaRepeatMode;
Defined in: packages/media-session/src/specs/media-session.nitro.ts:781
Current repeat mode, as the remote surfaces should draw it.
Additive field: it rides the existing playbackState channel rather than
introducing a fourth one, because it is state a surface renders next to the
transport controls and it changes on exactly the same discontinuities.
Only drawn when the app also advertises setRepeatMode in
capabilities — media3 greys out a control whose command is missing,
and iOS never enables a command with no target. Broadcasting a mode without
the capability is legal and means "this is my state, but do not offer to
change it".
shuffleEnabled
shuffleEnabled: boolean;
Defined in: packages/media-session/src/specs/media-session.nitro.ts:783
Current shuffle state. Same rules as repeatMode.
status
status: MediaPlaybackStatus;
Defined in: packages/media-session/src/specs/media-session.nitro.ts:704