Skip to main content

Setup & manual configuration

This is not an Expo-only library — it works in Expo and in bare React Native. Most native wiring is automatic; this page covers the setup that differs between the two workflows, and lists everything the library handles for you.

What's automatic (Expo and bare React Native)

  • Native module linking — the library is a Nitro module, so it autolinks. There is no react-native.config.js and nothing to register.
  • Android — the library ships its own AndroidManifest.xml (playback foreground service, media-session components, media-button receiver, Cast components, and the permissions it needs). The Android manifest merger folds it into your app, so there are no manual Android manifest edits in either workflow.
  • Lock-screen / Now Playing / remote commands — handled natively once the player is configured. You do not register a service to receive play/pause/next/seek from the lock screen, headset, or Bluetooth.

Install

npm install react-native-queue-player react-native-nitro-modules

react-native-nitro-modules is a required peer dependency.

iOS native configuration

iOS is the only platform that needs native configuration. How you apply it depends on your workflow.

Expo

Add the config plugin to your app config:

{
"expo": {
"plugins": [
["react-native-queue-player", {
"carplay": false,
"siri": false,
"chromecast": false,
"chromecastReceiverAppId": "CC1AD845"
}]
]
}
}
OptionWhat the plugin does
(always on)Sets UIBackgroundModes: ["audio"] for background playback, and AVInitialRouteSharingPolicy: LongFormAudio so a cold start routes to the user's last long-form output (AirPods, AirPlay 2, CarPlay)
enableIosBGAudioControls the background-audio mode above — on by default; set false only if your app declares UIBackgroundModes itself
carplayCarPlay audio entitlement + scene configuration (see the CarPlay guide)
siriSiriKit entitlement, Info.plist intent keys, and the in-app intent handler (see the Voice guide)
chromecastThe Chromecast pod, Bonjour / local-network Info.plist keys, and the AppDelegate Cast init (see the Casting guide)
chromecastReceiverAppIdThe iOS Chromecast receiver application ID (defaults to Google's Default Media Receiver)

After changing plugin flags, regenerate native projects with npx expo prebuild (add --clean if you change native config materially).

Bare React Native

There is no config plugin — apply the same iOS configuration by hand. The only step required for basic playback is background audio, in ios/<YourApp>/Info.plist:

<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
<key>AVInitialRouteSharingPolicy</key>
<string>LongFormAudio</string>

Then install pods:

cd ios && pod install

The optional integrations need the extra native config the plugin would otherwise apply for you:

FeatureBare-RN iOS setup
CarPlayAdd the com.apple.developer.carplay-audio entitlement + enable the CarPlay capability, and add the UIApplicationSceneManifest (phone + CarPlay scenes) to Info.plist — see the CarPlay guide
Siri / voiceAdd the com.apple.developer.siri entitlement + Siri capability, the SiriKit Info.plist keys (NSSiriUsageDescription, NSAppleMusicUsageDescription, INIntentsSupported, NSUserActivityTypes, INSupportedMediaCategories, LSApplicationCategoryType), and an application(_:handlerFor:) handler in your AppDelegate that routes INPlayMediaIntent to the library — see the Voice guide
ChromecastAdd pod 'QueuePlayer/Chromecast' to your Podfile, the Info.plist keys (NSLocalNetworkUsageDescription, NSBonjourServices, QueuePlayerChromecastReceiverApplicationID), and call ChromecastSupport.installWithDefaults() in your AppDelegate — see the Casting guide

Android needs no manual native config in either workflow.

Initialize the player early

Always initialize the player from a dedicated bootstrap module that runs before your app's UI. This is the recommended pattern for every app — not just automotive or voice apps. It guarantees the player is configured on every launch, including cold starts where the system can wake your JavaScript before any screen mounts (a lock-screen widget, CarPlay, Android Auto, or an assistant request). Initializing inside a React component or effect only runs when UI mounts, so those cold-start paths would find the player unconfigured.

Create a bootstrap module and import it before your app entry:

// index.js
import './src/playerBootstrap';
import 'expo-router/entry'; // or your bare-RN AppRegistry entry
// src/playerBootstrap.ts
import { getTrackPlayer, registerPlaybackService } from 'react-native-queue-player';

void (async () => {
await getTrackPlayer().configure({ audioContentType: 'music' });

// Only needed for automotive / voice — the handlers serve browse trees,
// search, and play-from-search/id requests. See the automotive & voice guides.
registerPlaybackService(() => ({
onBrowseRequest: async (parentId) => [/* BrowseItem[] */],
onPlayFromSearchRequest: async (request) => [/* TrackItem[] */],
onPlayFromIdRequest: async (mediaId) => [/* TrackItem[] */],
}));
})();

configure() runs once and fully (re)initializes the engine, audio session, and observers — calling it early from a module (not inside a React effect) is what makes playback reliable across every launch path. registerPlaybackService is for automotive / voice browse + search only; lock-screen controls are automatic.

Android runtime permissions

The library declares the permissions it needs, but your app must request the runtime grants where applicable:

  • POST_NOTIFICATIONS (Android 13+) — for the media notification.
  • Local-network access (newer Android versions) — for Cast discovery.

Request these from your app using your preferred permissions flow.

Per-feature manual notes

  • CarPlay — the CarPlay audio entitlement requires approval from Apple before it can be used in a distributed build. See the CarPlay guide.
  • Siri (local Xcode builds) — EAS Build toggles the Siri capability automatically; a local Xcode build without automatic signing needs a one-time toggle in the target's Signing & Capabilities pane. See the Voice guide.
  • Usage-description strings — on Expo the plugin sets defensive defaults for NSSiriUsageDescription / NSAppleMusicUsageDescription; override them with your own copy (in bare RN, set your own from the start).
  • Android Google Assistant / App Actions — assistant deep-linking is configured in your app (a shortcuts.xml, a BROWSABLE deep-link, and a route that dispatches the request). See the Voice guide.
  • Native Android Automotive OS (AAOS) is not supported; Android Auto here is phone-projected Auto.