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.
| Field | Type | Description |
|---|---|---|
mediaId | string | The mediaId of the currently playing item. |
position | number | Current playback position in seconds. |
duration | number | Total duration of the media item in seconds. |
timestamp | number | Unix 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.
| Field | Type | Description |
|---|---|---|
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).
| Event | Trigger |
|---|---|
RemotePlay | Play button pressed |
RemotePause | Pause button pressed |
RemoteStop | Stop button pressed |
RemoteNext | Next track button |
RemotePrevious | Previous track button |
RemoteSeek | Seek bar moved |
RemoteSkipForward | Skip forward button |
RemoteSkipBackward | Skip 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.