Documentation Index
Fetch the complete documentation index at: https://mintlify.com/afkcodes/react-native-audio-pro/llms.txt
Use this file to discover all available pages before exploring further.
React Native Audio Pro uses an event-driven architecture to communicate playback changes from the native layer to JavaScript. Rather than polling for state, your app subscribes to a stream of typed events and reacts as they arrive. Every meaningful change — a state transition, a progress tick, a track change, a remote button press — is delivered as a discrete event with a typed payload. This keeps your UI reactive and decoupled from the internal player implementation.
Adding an Event Listener
Use AudioPro.addEventListener(callback) to subscribe to all player events. It returns a subscription object with a .remove() method that you must call to clean up — typically in the cleanup function of a useEffect.
import { useEffect } from 'react';
import { AudioPro, AudioProEventType } from 'react-native-audio-pro';
import type { AudioProEvent } from 'react-native-audio-pro';
useEffect(() => {
const subscription = AudioPro.addEventListener((event: AudioProEvent) => {
switch (event.type) {
case AudioProEventType.STATE_CHANGED:
console.log('State:', event.payload?.state);
break;
case AudioProEventType.PROGRESS:
console.log('Position:', event.payload?.position);
break;
case AudioProEventType.TRACK_ENDED:
console.log('Track ended');
break;
}
});
return () => {
subscription.remove();
};
}, []);
Event Types
Every event object has the shape:
interface AudioProEvent {
type: AudioProEventType;
track: AudioProTrack | null; // null for REMOTE_NEXT and REMOTE_PREV
payload?: { /* varies by event type — see below */ };
}
STATE_CHANGED
Emitted whenever the player transitions to a new AudioProState. This is the primary event to observe for updating play/pause buttons and showing loading indicators.
Payload:
| Field | Type | Description |
|---|
state | AudioProState | The new playback state |
position | number | Current position in milliseconds |
duration | number | Total track duration in milliseconds |
case AudioProEventType.STATE_CHANGED: {
const { state, position, duration } = event.payload!;
console.log(`State changed to ${state} at ${position}ms / ${duration}ms`);
break;
}
PROGRESS
Emitted periodically during active playback at the progressIntervalMs interval (default 1000 ms). Use this to drive seek bars, elapsed-time labels, and buffering indicators.
Payload:
| Field | Type | Description |
|---|
position | number | Current position in milliseconds |
duration | number | Total track duration in milliseconds |
bufferedPosition | number | How far ahead the buffer has loaded (ms) |
case AudioProEventType.PROGRESS: {
const { position, duration, bufferedPosition } = event.payload!;
setProgress({ position, duration, bufferedPosition });
break;
}
TRACK_ENDED
Emitted when the current track plays through to the end. After this event, native automatically pauses, seeks to position 0, and emits STATE_CHANGED: STOPPED. In a queue with multiple items, TRACK_CHANGED will follow as the next track loads.
Payload:
| Field | Type | Description |
|---|
position | number | Final position in milliseconds |
duration | number | Track duration in milliseconds |
TRACK_CHANGED
Emitted when playback moves to a different track in the queue — either automatically (auto-advance) or by calling seekToMediaItem(), seekToNextMediaItem(), or seekToPreviousMediaItem().
Payload:
| Field | Type | Description |
|---|
index | number | Zero-based index of the new track |
position | number | Starting position in milliseconds |
duration | number | Duration of the new track in milliseconds |
case AudioProEventType.TRACK_CHANGED: {
const { index } = event.payload!;
const newTrack = event.track;
console.log(`Now playing track ${index}: ${newTrack?.title}`);
break;
}
SEEK_COMPLETE
Emitted after a seek operation initiated from TypeScript (seekTo(), seekBy()) completes. Not emitted for seeks triggered by lock screen controls.
Payload:
| Field | Type | Description |
|---|
position | number | Resolved position after the seek |
duration | number | Track duration in milliseconds |
triggeredBy | AudioProTriggerSource | 'USER' or 'SYSTEM' |
PLAYBACK_SPEED_CHANGED
Emitted when the playback rate changes, either from calling AudioPro.setPlaybackSpeed() or from a system-level change.
Payload:
| Field | Type | Description |
|---|
speed | number | New playback rate (0.25 – 2.0) |
REMOTE_NEXT
Emitted when the user taps the Next button on the lock screen or a media notification. The native layer does not handle this automatically — your app must respond by calling AudioPro.seekToNextMediaItem() or loading a new track.
Payload: none. event.track will be null.
REMOTE_NEXT and REMOTE_PREV are informational only. Native does not advance the track automatically when these events fire. Your app is responsible for handling them by calling AudioPro.seekToNextMediaItem() or AudioPro.seekToPreviousMediaItem() (or your own queue navigation logic).
case AudioProEventType.REMOTE_NEXT:
AudioPro.seekToNextMediaItem();
break;
REMOTE_PREV
Emitted when the user taps the Previous button on the lock screen or media notification. Your app must respond by calling AudioPro.seekToPreviousMediaItem() or implementing your own back-navigation logic.
Payload: none. event.track will be null.
case AudioProEventType.REMOTE_PREV:
AudioPro.seekToPreviousMediaItem();
break;
PLAYBACK_ERROR
Emitted when a playback error occurs. This event may be emitted independently of the ERROR state — a PLAYBACK_ERROR with recoverable: true means the player will retry and remains usable. Only a STATE_CHANGED: ERROR event means the player has entered a terminal failure state.
Payload:
| Field | Type | Description |
|---|
error | string | Human-readable error message |
errorCode | AudioProErrorCode | number | Numeric error code (see AudioProErrorCode enum) |
recoverable | boolean | true if the player will retry automatically |
cause | string | Optional underlying exception message |
index | number | Queue index of the track that failed |
REPEAT_MODE_CHANGED
Emitted when the repeat mode changes — either from AudioPro.setRepeatMode() or from a user action on the media notification.
Payload: none. Use event.track to identify which track was active when the mode changed.
SHUFFLE_MODE_CHANGED
Emitted when shuffle is toggled — either from AudioPro.setShuffleModeEnabled() or from a user action.
Payload: none. Use event.track to identify which track was active when shuffle was toggled.
CUSTOM_ACTION
Emitted when the user taps a custom notification button such as Like, Save, Bookmark, Rewind 30, or Forward 30. Your app is responsible for handling the action.
Payload:
| Field | Type | Description |
|---|
action | string | One of 'LIKE', 'SAVE', 'BOOKMARK', 'REWIND_30', 'FORWARD_30' |
case AudioProEventType.CUSTOM_ACTION: {
const action = event.payload?.action;
if (action === 'LIKE') toggleLike(event.track?.id);
if (action === 'FORWARD_30') AudioPro.seekBy(30000);
if (action === 'REWIND_30') AudioPro.seekBy(-30000);
break;
}
SLEEP_TIMER_COMPLETE
Emitted when a sleep timer started with AudioPro.startSleepTimer() expires. After this event, the player pauses automatically.
Payload:
| Field | Type | Description |
|---|
timerDuration | number | The duration (in seconds) the timer was set to |
QUEUE_CHANGED
Emitted whenever the queue is modified — items added, removed, moved, or cleared.
Payload:
| Field | Type | Description |
|---|
size | number | Total number of tracks in the queue |
currentIndex | number | Zero-based index of the active track |
AUDIO_SESSION_CHANGED
Emitted when the native audio session ID changes. Useful when integrating with audio visualizers or equalizer effects that need the session ID.
Payload:
| Field | Type | Description |
|---|
audioSessionId | number | The new audio session ID |
Complete Event Listener Example
import { useEffect } from 'react';
import {
AudioPro,
AudioProEventType,
AudioProState,
} from 'react-native-audio-pro';
import type { AudioProEvent } from 'react-native-audio-pro';
function usePlayerEvents() {
useEffect(() => {
const subscription = AudioPro.addEventListener((event: AudioProEvent) => {
switch (event.type) {
case AudioProEventType.STATE_CHANGED:
console.log('[Player] State:', event.payload?.state);
break;
case AudioProEventType.PROGRESS:
// Update seek bar — fires at progressIntervalMs
break;
case AudioProEventType.TRACK_ENDED:
console.log('[Player] Track ended');
break;
case AudioProEventType.TRACK_CHANGED:
console.log('[Player] Track changed to index', event.payload?.index);
break;
case AudioProEventType.SEEK_COMPLETE:
console.log('[Player] Seek complete at', event.payload?.position);
break;
case AudioProEventType.REMOTE_NEXT:
// App must handle — native does not advance automatically
AudioPro.seekToNextMediaItem();
break;
case AudioProEventType.REMOTE_PREV:
AudioPro.seekToPreviousMediaItem();
break;
case AudioProEventType.PLAYBACK_ERROR: {
const { error, errorCode, recoverable } = event.payload!;
console.warn(`[Player] Error (code ${errorCode}): ${error}`, { recoverable });
break;
}
case AudioProEventType.CUSTOM_ACTION: {
const action = event.payload?.action;
if (action === 'LIKE') console.log('[Player] Like pressed');
if (action === 'FORWARD_30') AudioPro.seekBy(30000);
if (action === 'REWIND_30') AudioPro.seekBy(-30000);
break;
}
case AudioProEventType.QUEUE_CHANGED:
console.log('[Player] Queue size:', event.payload?.size);
break;
case AudioProEventType.AUDIO_SESSION_CHANGED:
console.log('[Player] Audio session ID:', event.payload?.audioSessionId);
break;
}
});
return () => {
subscription.remove();
};
}, []);
}
Ambient Events
Ambient audio (played via AudioPro.ambientPlay()) uses a separate event channel. Subscribe with AudioPro.addAmbientListener():
import { useEffect } from 'react';
import { AudioPro, AudioProAmbientEventType } from 'react-native-audio-pro';
import type { AudioProAmbientEvent } from 'react-native-audio-pro';
useEffect(() => {
const subscription = AudioPro.addAmbientListener((event: AudioProAmbientEvent) => {
switch (event.type) {
case AudioProAmbientEventType.AMBIENT_TRACK_ENDED:
console.log('[Ambient] Track ended');
break;
case AudioProAmbientEventType.AMBIENT_ERROR:
console.error('[Ambient] Error:', event.payload?.error);
break;
}
});
return () => {
subscription.remove();
};
}, []);
Ambient event types:
| Event | Description |
|---|
AMBIENT_TRACK_ENDED | The ambient audio track finished playing (or loop ended) |
AMBIENT_ERROR | An error occurred in the ambient audio player |
Ambient events are completely separate from main player events. Adding a listener with addEventListener will not receive ambient events, and vice versa.