React Native THEOplayer

Media Control API

Our Media Control API provides a unified way to customise the behaviour of the different media playback controls and media sessions across platforms (iOS, Android, and Web). It enables integration with platform-level media controls such as lock screen controls, notification controls, media session, …

What is it used for?

Platform Support

MediaControl API and MediaControl Action Reference

The Media Control API allows you to override the default player’s behaviour, by defining a handler for one of the MediaControl Actions:

setHandler(action: MediaControlAction, handler: MediaControlHandler | undefined): void;

Passing undefined as handler removes any previously set handler for that action, restoring the player’s default behaviour.

The MediaControlAction enum defines all actions that can be controlled by the Media Control API:

Play and pause are only enabled for VOD and when the stream is not displaying an ad. For LIVE streams this can be configured through allowLivePlayPause in the player’s MediaControlConfiguration.

If no handler is defined for an action, the player’s default behaviour is applied.

iOS: Track Control vs. Seek Behavior

On iOS, when you set handlers for SKIP_TO_NEXT or SKIP_TO_PREVIOUS, these handlers will take precedence over the seek behavior. This means:

This allows you to customize whether system controls are used for playlist navigation or for seeking within the current track.

Note: In both cases, you can always use the system’s time slider to adjust the playhead to seek to a location in the stream.

Multiple players: single media-session owner

Each platform exposes a single, process-wide media session and set of remote controls (iOS MPNowPlayingInfoCenter / MPRemoteCommandCenter, Android MediaSession + notification, Web navigator.mediaSession). When your app renders more than one THEOplayerView at the same time, they all share this single system session.

Because of that, only one player should own the media session at any given time. It is the application’s responsibility to designate that single owner and to ensure no other player simultaneously publishes Now Playing info or handles remote commands. If multiple players are allowed to take control at once:

Keep a single “active” player and toggle ownership so that exactly one player has the media session enabled at a time. You can update ownership across players using:

// Give this player exclusive ownership of the media session / remote commands.
player.mediaControl?.setEnabled(isActive);

where isActive is true for the player that should own the media session and false for all other players. The owner will have its state reflected on the media session widgets.

iOS: lock screen and Control Center play/pause state with multiple playing players

As a good practice, make sure only one player is actively playing at any given time. Shift the media session ownership (as demonstrated above) whenever a player starts playing (e.g. on a PLAY or PLAYING event) and pause all other players. On iOS, Control Center reflects the application’s overall audio session state, not that of a specific player, so if multiple players are playing at once its controls will act on all of them.

Configuration

You can add additional media control configuration using the MediaControlConfiguration interface:

export interface MediaControlConfiguration {
  mediaSessionEnabled?: boolean; // (Web/Android) Enable/disable media session (default: true)
  skipForwardInterval?: number;  // (Web/Android/iOS) Skip forward interval (defaults: 5s on Web, Android / 15s on iOS)
  skipBackwardInterval?: number; // (Web/Android/iOS) Skip backward interval (defaults: 5s on Web, Android / 15s on iOS)
  allowLivePlayPause?: boolean;  // (Android/iOS) Enable play/pause for live (defaults: false on Android / true on iOS)
}

Example Usage: Playlist Navigation

The Media Control API can be used to handle playlist navigation via system controls. For example, in a component that owns the playlist:

import { MediaControlAction } from 'react-native-theoplayer';

// ...
useEffect(() => {
  if (!player) return;

  const handleNext = () => { /* update player source ... */ };
  const handlePrevious = () => { /* update player source ... */ };

  player.mediaControl?.setHandler(MediaControlAction.SKIP_TO_NEXT, handleNext);
  player.mediaControl?.setHandler(MediaControlAction.SKIP_TO_PREVIOUS, handlePrevious);

  return () => {
    player.mediaControl?.setHandler(MediaControlAction.SKIP_TO_NEXT, undefined);
    player.mediaControl?.setHandler(MediaControlAction.SKIP_TO_PREVIOUS, undefined);
  };
}, [player, filteredSources]);

This enables users to skip tracks using lock screen or Bluetooth controls. If you do not set these handlers, the controls will perform seek actions instead.

Demo

As a demonstration, see the the PlaylistProvider in our example app.