Quick start
This guide gets a track playing. It works in both Expo and bare React Native (New Architecture enabled).
1. Install
npm install react-native-queue-player react-native-nitro-modules
react-native-nitro-modules is a required peer dependency — the library is built on Nitro Modules. The library autolinks; there is nothing to register.
2. Native setup
Android needs no manual native config in either workflow — the library ships its own manifest, merged in automatically. iOS needs a little setup, which differs by workflow.
Expo
Add the config plugin to your app config:
{
"expo": {
"plugins": [
["react-native-queue-player", { "carplay": false, "siri": false, "chromecast": false }]
]
}
}
For basic playback leave all three flags false — enable them when you add CarPlay, Siri / voice, or Chromecast. The plugin sets the iOS background-audio mode automatically, along with the Info.plist keys, entitlements, and AppDelegate hooks for any integration you enable. Then regenerate native projects:
npx expo prebuild
Bare React Native
There's no plugin step. Add the one required iOS key — background audio — to ios/<YourApp>/Info.plist, then install pods:
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
cd ios && pod install
That's everything for basic playback. See Setup & manual configuration for the full per-feature native setup (CarPlay, Siri, Chromecast) in both workflows.
3. Configure the player from a bootstrap module
getTrackPlayer() returns a singleton — the same instance every time; there is no class to construct. Always call configure() once, early, from a dedicated bootstrap module that runs before your app's UI:
// src/playerBootstrap.ts
import { getTrackPlayer } from 'react-native-queue-player';
void getTrackPlayer().configure({ audioContentType: 'music' });
// index.js — import the bootstrap BEFORE your app entry so it always runs first
import './src/playerBootstrap';
import 'expo-router/entry'; // or your bare-RN AppRegistry entry
This is the recommended pattern for every app: it guarantees the player is ready on every launch, including cold starts where the system (a lock-screen widget, CarPlay, Android Auto, or an assistant) can wake your JavaScript before any screen mounts. See Setup & manual configuration for the full pattern, including registerPlaybackService() for automotive / voice.
4. Load a queue and play
Each track needs only a url (http(s):// or file://). All other fields are optional metadata.
const player = getTrackPlayer();
await player.setQueue([
{ url: 'https://stream.example/track1.mp3', title: 'One', artist: 'Artist', album: 'Album', duration: 180 },
{ url: 'https://stream.example/track2.mp3', title: 'Two', artist: 'Artist', album: 'Album', duration: 200 },
]);
await player.play();
Transport is a handful of promises:
await player.pause();
await player.skipToNext();
await player.skipToPrevious();
await player.skipToIndex(0);
await player.seekTo(30); // seconds into the current track
await player.setVolume(0.8); // 0.0 – 1.0
5. Build your UI with hooks
Hooks subscribe to the native event streams directly:
import {
useActiveTrack,
usePlaybackState,
useProgress,
useCanSkip,
} from 'react-native-queue-player';
function NowPlaying() {
const { track } = useActiveTrack();
const { state } = usePlaybackState(); // 'playing' | 'paused' | 'buffering' | …
const { position, duration } = useProgress(); // seconds
const { canSkipNext, canSkipPrevious } = useCanSkip();
if (track == null) return <Text>No track loaded</Text>;
return (
<View>
<Text>{track.title} — {track.artist}</Text>
<Text>{state} · {position.toFixed(0)} / {duration.toFixed(0)}s</Text>
</View>
);
}
Next steps
- Setup & manual configuration — background audio, plugin flags, the bootstrap init, runtime permissions.
- Custom HTTP headers — auth tokens and a custom user agent for your media.
- API reference — the full surface, including playback modes, repeat, and shuffle.