flutter_spotify_remote
Control the Spotify app from Flutter. flutter_spotify_remote wraps the official
Spotify App Remote SDK on both platforms and gives you one Dart API for
playback commands, a real-time player-state stream, and OAuth with silent token
refresh.
await FlutterSpotifyRemote.instance.play('spotify:track:6rqhFgbbKwnb9MLmUQDhG6');
Features
- π Playback control β play, pause, resume, skip, seek, shuffle, repeat
- π‘ Real-time state β a
Stream<SpotifyEvent>of player state and connection changes - π OAuth with silent refresh β backend token swap/refresh on both iOS and Android, so users approve once and never app-switch again
- π§© Sealed event hierarchy β handle every
SpotifyEventexhaustively withswitch - π¨ Typed exceptions β
SpotifyNotInstalledException,SpotifyAuthException, and friends - π¦ iOS framework bundled β
SpotifyiOS.xcframeworkships with the plugin; no extra Podfilesourceneeded
Platform support
| Platform | Supported | Min version | Underlying SDK |
|---|---|---|---|
| Android | β | API 21 | Spotify Android App Remote SDK (.aar) |
| iOS | β | iOS 14 | SpotifyiOS 5.0.1 (xcframework, bundled) |
The Spotify app must be installed and logged in on the device β this plugin remote-controls it, it does not stream audio itself.
Installation
dependencies:
flutter_spotify_remote: ^0.0.4
Then register your app in the
Spotify Developer Dashboard to get a
client ID, and add your redirect URI (e.g. yourapp://callback) there.
iOS setup
1. Install pods
The SpotifyiOS.xcframework is vendored by the plugin's podspec, so a plain
pod install is all that is required:
cd ios && pod install
2. Register the redirect URI scheme
In ios/Runner/Info.plist, declare the scheme half of your redirect URI and allow querying the Spotify app:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>spotify</string>
</array>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleURLSchemes</key>
<array>
<string>yourapp</string>
</array>
</dict>
</array>
The redirect callback is forwarded automatically through Flutter's plugin
registrar β no AppDelegate changes are needed.
Android setup
The Spotify Android App Remote SDK .aar cannot be redistributed via Maven and
must be added to your app manually.
1. Download the SDK
Grab spotify-app-remote-release-*.aar from the
Spotify Android SDK releases.
2. Place the .aar in your app
android/
app/
libs/
spotify-app-remote-release-0.8.0.aar
3. Reference it in android/app/build.gradle(.kts)
dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.aar"))))
}
4. Add the internet permission
<uses-permission android:name="android.permission.INTERNET" />
5. Declare the redirect URI placeholders
Authorization runs through the Spotify auth library, which registers a redirect
receiver activity built from two manifest placeholders. The manifest merge
fails without them. Set both to match your redirectUrl β for
yourapp://callback that is scheme yourapp, host callback:
android {
defaultConfig {
manifestPlaceholders["redirectSchemeName"] = "yourapp"
manifestPlaceholders["redirectHostName"] = "callback"
}
}
Package visibility (<queries> for com.spotify.music, required on Android 11+)
is contributed by the plugin, so no host-app entry is needed.
Quick start
import 'package:flutter_spotify_remote/flutter_spotify_remote.dart';
final spotify = FlutterSpotifyRemote.instance;
// 1. Listen for events *before* connecting
spotify.onEvent.listen((event) {
switch (event) {
case SpotifyPlayerStateChangedEvent(:final playerState):
print('Now playing: ${playerState.track.name}');
case SpotifyConnectionChangedEvent(:final status):
print('Connection: $status');
case SpotifyAccessTokenEvent(:final accessToken, :final expiresIn):
prefs.setString('spotify_token', accessToken); // persist it
}
});
// 2. Authorize (see "Authentication" below for the production path)
await spotify.connectAndAuthorize(
clientId: 'YOUR_CLIENT_ID',
redirectUrl: 'yourapp://callback',
);
// 3. Control playback
await spotify.play('spotify:track:6rqhFgbbKwnb9MLmUQDhG6');
await spotify.pause();
await spotify.resume();
await spotify.skipNext();
await spotify.skipPrevious();
await spotify.seekTo(30000); // 30 seconds
await spotify.setShuffle(true);
await spotify.setRepeatMode(1); // 0=off 1=track 2=context
await spotify.disconnect();
A complete runnable app lives in example/.
Authentication
Recommended: initializeSession with a backend
Call initializeSession() on every app start with your token swap and refresh
endpoints. The native SDK then performs first-time OAuth, and refreshes the
token silently (~every 55 minutes) with no further app-switch:
await spotify.initializeSession(
clientId: 'YOUR_CLIENT_ID',
redirectUrl: 'yourapp://callback',
tokenSwapURL: 'https://your-backend.example.com/swap',
tokenRefreshURL: 'https://your-backend.example.com/refresh',
);
// Later, to force a refresh:
await spotify.renewSession();
Both endpoints take a form-encoded POST and return standard Spotify JSON
(access_token, expires_in, optional refresh_token):
| Endpoint | Request body |
|---|---|
tokenSwapURL |
grant_type=authorization_code&code=β¦&redirect_uri=β¦ |
tokenRefreshURL |
grant_type=refresh_token&refresh_token=β¦ |
Your client secret stays on the backend β never ship it in the app.
Without a tokenSwapURL, Android falls back to the implicit grant:
initializeSession still emits an access token, but there is no refresh token,
so renewSession() fails with NO_SESSION.
Silent reconnect on later launches
Persist the token from SpotifyAccessTokenEvent and reconnect without any
app-switch:
await spotify.connectWithToken(
clientId: 'YOUR_CLIENT_ID',
redirectUrl: 'yourapp://callback',
accessToken: storedToken,
);
Tokens are never stored natively β persistence is yours to control, in
SharedPreferences or secure storage:
case SpotifyAccessTokenEvent(:final accessToken, :final expiresIn, :final source):
await prefs.setString('spotify_token', accessToken);
await prefs.setInt(
'spotify_token_expires',
DateTime.now().millisecondsSinceEpoch + expiresIn * 1000,
);
source tells you how the token arrived: firstAuth, silentRefresh, or
directAuth.
API reference
FlutterSpotifyRemote.instance
| Method | Description |
|---|---|
initializeSession(...) |
Configure OAuth with backend swap/refresh (recommended) |
renewSession() |
Force a silent token refresh |
connectAndAuthorize(...) |
OAuth app-switch without a backend |
connectWithToken(...) |
Silent connect using a stored token |
disconnect() |
Disconnect and release SDK resources |
isConnected() |
Whether the App Remote is connected |
getAccessToken() |
The current access token |
canPlayOnDemand() |
Whether the account may play an individual track URI |
play(uri) |
Play a Spotify URI |
pause() / resume() |
Pause / resume playback |
skipNext() / skipPrevious() |
Track navigation |
seekTo(ms) |
Seek within the current track |
setShuffle(bool) |
Enable/disable shuffle |
setRepeatMode(int) |
0=off, 1=track, 2=context |
onEvent |
Stream<SpotifyEvent> of all events |
Events
| Event | Fields |
|---|---|
SpotifyPlayerStateChangedEvent |
playerState (SpotifyPlayerState) |
SpotifyConnectionChangedEvent |
status, message? |
SpotifyAccessTokenEvent |
accessToken, expiresIn, source |
Exceptions
| Exception | When thrown |
|---|---|
SpotifyNotInstalledException |
Spotify is not installed |
SpotifyAuthException |
Token expired or auth failed |
SpotifyConnectionException |
Connection attempt failed |
SpotifyCommandException |
Playback command rejected by the SDK |
Known limitations
- Spotify must be installed and logged in; this plugin does not stream audio.
- Spotify Free accounts cannot play a single track URI on demand β check
canPlayOnDemand()and fall back to a playlist or album context. - The first authorization always app-switches to Spotify. Every later launch
is silent if you use
initializeSessionor a stored token. - The Android
.aarmust be added manually β Spotify's terms prevent distribution through Maven Central.
Contributing
Issues and pull requests are welcome on
GitHub. Please run
flutter analyze and flutter test before opening a PR.
License
MIT β see LICENSE.
Libraries
- flutter_spotify_remote
- A Flutter plugin for Spotify App Remote SDK.