Events

addEventListener

Subscribe to player events in your React components:

import TrackPlayer, { EventType } from '@rntp/player';
import { useEffect } from 'react';

useEffect(() => {
  const sub = TrackPlayer.addEventListener(EventType.PlaybackError, (event) => {
    console.error('Playback error', event.error);
  });
  return () => sub.remove();
}, []);

Event types

PlaybackStateChanged

Fires when the playback state transitions.

TrackPlayer.addEventListener(EventType.PlaybackStateChanged, ({ state }) => {
  console.log('New state:', state);
});

IsPlayingChanged

Fires when playing status toggles.

TrackPlayer.addEventListener(EventType.IsPlayingChanged, ({ playing }) => {
  console.log('Playing:', playing);
});

MediaItemTransition

Fires when the active queue item changes.

TrackPlayer.addEventListener(EventType.MediaItemTransition, ({ mediaItem }) => {
  console.log('Now playing:', mediaItem?.title);
});

MetadataReceived

Fires when ICY stream metadata is received (live streams).

TrackPlayer.addEventListener(EventType.MetadataReceived, ({ metadata }) => {
  console.log('Stream metadata:', metadata);
});

PlaybackError

Fires when a playback error occurs.

TrackPlayer.addEventListener(EventType.PlaybackError, ({ error }) => {
  console.error('Error:', error);
});

PlaybackProgressUpdated

Fires periodically during playback when progressSync is configured. Contains the same payload sent to the HTTP endpoint and saved natively.

FieldTypeDescription
mediaIdstringThe mediaId of the currently playing item.
positionnumberCurrent playback position in seconds.
durationnumberTotal duration of the media item in seconds.
timestampnumberUnix timestamp in milliseconds when the snapshot was taken.
TrackPlayer.addEventListener(EventType.PlaybackProgressUpdated, ({ mediaId, position, duration, timestamp }) => {
  console.log(`${mediaId}: ${position}/${duration}s at ${timestamp}`);
});

SleepTimerTriggered

Fires when a sleep timer pauses playback.

FieldTypeDescription
type'time' \| 'mediaItem'Which timer mode triggered.
TrackPlayer.addEventListener(EventType.SleepTimerTriggered, ({ type }) => {
  console.log(`Sleep timer fired (${type})`);
});

QueueChanged

Fires when the queue is modified.

TrackPlayer.addEventListener(EventType.QueueChanged, () => {
  const queue = TrackPlayer.getQueue();
});

Remote control events

These fire in response to hardware buttons, lock screen controls, and notification actions. Handle them in your background event handler (see Quick Start).

EventTrigger
RemotePlayPlay button pressed
RemotePausePause button pressed
RemoteStopStop button pressed
RemoteNextNext track button
RemotePreviousPrevious track button
RemoteSeekSeek bar moved
RemoteSkipForwardSkip forward button
RemoteSkipBackwardSkip backward button

Background event handler

By default (handling: 'native'), the system handles remote control events automatically — play, pause, skip, and seek all work without any JavaScript code. You do not need to register a background event handler for basic playback to work.

Register a handler when you need to intercept events yourself — for example, to update metadata, implement custom skip logic, or use handling: 'js' / 'hybrid':

TrackPlayer.registerBackgroundEventHandler(() => async (event: BackgroundEvent) => {
  switch (event.type) {
    case EventType.RemotePlay:
      await TrackPlayer.play();
      break;
    case EventType.RemotePause:
      await TrackPlayer.pause();
      break;
    case EventType.RemoteNext:
      await TrackPlayer.skipToNext();
      break;
    case EventType.RemotePrevious:
      await TrackPlayer.skipToPrevious();
      break;
    case EventType.RemoteSeek:
      await TrackPlayer.seekTo(event.position);
      break;
  }
});

If registered, it must be called before setupPlayer, in a file loaded at app startup — not inside a component.

ende