Skip to main content

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