Voice
Voice requests — Siri on iOS and Google Assistant on Android — arrive through a single handler: onPlayFromSearchRequest. You resolve the structured request into tracks; the library renders the result.
The handler
Register it via registerPlaybackService (from your bootstrap module):
import { getTrackPlayer, registerPlaybackService } from 'react-native-queue-player';
registerPlaybackService(() => ({
onPlayFromSearchRequest: async (request) => {
// request.query is the free-text utterance; structured fields
// (artist, album, song, genre, type, playShuffled, …) are populated
// when the assistant parsed them. request.origin is 'ios-siri' or
// 'android-assistant'.
const tracks = await resolve(request); // -> TrackItem[]
if (request.origin === 'ios-siri') {
// iOS: drive playback yourself, then return the tracks.
const player = getTrackPlayer();
await player.setQueue(tracks);
await player.play();
}
// Android: returning the tracks starts playback automatically.
return tracks; // an empty array signals "no match" (Siri shows its generic failure)
},
}));
Why the platform split: this applies only to voice play-from-search and comes from the platform frameworks. On Android, Media3 applies and plays the list you return. On iOS, the SiriKit INPlayMediaIntent flow has your handler set the queue and start playback before returning, so Siri can report the result. This is specific to resolving a voice request — it does not affect shuffleQueue() or the other transport calls, which behave the same on both platforms. For resume-style intents (request.resumePlayback === true or request.reference === 'currentlyPlaying'), return [] and call player.play() directly.
MediaSearchRequest carries query plus optional type, artist, album, song, playlist, genre, origin, reference, playShuffled, playbackRepeatMode, resumePlayback, and more — branch on origin before reading platform-specific fields.
iOS — Siri
Enable the plugin flag:
{ "expo": { "plugins": [["react-native-queue-player", { "siri": true }]] } }
This adds the Siri entitlement, the INPlayMediaIntent Info.plist keys, and an in-app intent handler (the integration uses the in-app application(_:handlerFor:) path — there is no separate Intents extension to create). Then:
- Override the placeholder
NSSiriUsageDescription/NSAppleMusicUsageDescriptionstrings inios.infoPlistwith your own copy. - For a local Xcode build without automatic signing, enable the Siri capability once in the target's Signing & Capabilities pane (EAS Build does this automatically).
Bare React Native: there's no plugin — add the com.apple.developer.siri entitlement + Siri capability, the SiriKit Info.plist keys, and the application(_:handlerFor:) handler in your AppDelegate by hand. See the bare-RN setup table.
Improve recognition with vocabulary
Seed Siri with the names it should recognize (iOS only; a no-op on Android):
getTrackPlayer().donateVoiceVocabulary({
artists: ['Pearl Jam', 'Radiohead'],
playlists: ['Chill', 'Focus'],
});
Phonetic aliases for hyphenated names
Hyphenated or initialism app names ("RNQP-Demo", "MyMu-Pro") are hard for speech recognition. Add INAlternativeAppNames to your Info.plist so Siri matches spoken aliases (the plugin does not set this for you):
{
"expo": {
"ios": {
"infoPlist": {
"INAlternativeAppNames": [
{ "INAlternativeAppName": "My Music" },
{
"INAlternativeAppName": "Music Pro",
"INAlternativeAppNamePronunciationHint": "My Mu Pro"
}
]
}
}
}
}
Android — Google Assistant
"Play … on YourApp" reaches onPlayFromSearchRequest through the media session when your app owns the active session — no extra setup beyond the handler above.
For richer, app-name-explicit recognition and cold-start launching, add Android App Actions in your app: a shortcuts.xml declaring actions.intent.PLAY_MUSIC, a BROWSABLE deep link, and a route that parses the deep link into a MediaSearchRequest and dispatches it to your resolver. This is configured on the app side; the library does not generate it.
Related
- Setup & manual configuration
- CarPlay / Android Auto — the browse handler model