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. Version 3 requires React Native 0.88 or later. With Expo, use version 3 (3.0.0 or later) on Expo SDK 58 and later. Expo SDK 58 starts React Native from its scene delegate when a window connects, and its app delegate no longer creates a window. Version 2's CarPlay scene setup takes the phone window's content from the app delegate's window, so it does not work on SDK 58, and version 2 is not supported on SDK 58 in any configuration. Version 3 is built for SDK 58's start-up and, with the carplay or siri option, also starts JavaScript for CarPlay and Siri when no phone window is open.

On Expo SDK 57 and earlier, or React Native older than 0.88, use 2.0.4-rc.6, the last version 2 release (tested with Expo SDK 57 and React Native 0.86). It is a prerelease, so install it by exact version: npm install react-native-queue-player@2.0.4-rc.6. See Upgrading to v3.

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, the CarPlay scene in the scene manifest, and the start-up code for a launch from CarPlay (see the CarPlay guide)
siriSiriKit entitlement, Info.plist intent keys, multiple scenes (iOS calls the in-app intent handler only in apps that support them), the in-app intent handler, and the start-up code for a launch from Siri (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 adding the plugin or changing any of its options, regenerate native projects with npx expo prebuild --clean. A prebuild without --clean adds to the existing native files and does not remove code an option no longer needs (Expo: config plugins and mods).

With carplay or siri on, the plugin also adds code to the generated AppDelegate.swift and SceneDelegate.swift so the app keeps one React root whether it starts from the phone, CarPlay or Siri — see How the app starts from CarPlay or Siri.

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>

The library needs iOS 16 or later. The React Native template's ios/Podfile uses React Native's own minimum (platform :ios, min_ios_version_supported, iOS 15.1 in 0.88), so raise it:

platform :ios, '16.0'

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, turn on multiple scenes and add the CarPlay scene to Info.plist, and move the React Native factory into your AppDelegate with the start-up code — 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), an application(_:handlerFor:) handler in your AppDelegate that routes INPlayMediaIntent to the library, UIApplicationSupportsMultipleScenes set to true, and the start-up code from the CarPlay guide — 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 (unregisterPlaybackService() removes the handler again — mainly for tests and clean shutdown); 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.