spotikit 2.0.1
spotikit: ^2.0.1 copied to clipboard
Flutter plugin for Spotify App Remote integration on Android.
Spotikit #
A Flutter plugin for controlling Spotify playback on Android via the Spotify App Remote SDK.
Version 2.0.0 — App Remote only. No Web API, no client secret required.
Highlights #
- Connect to the Spotify App Remote with just a
clientIdandredirectUri - Play / pause / resume / next / previous / seek / skip ±N seconds
- Realtime playback state stream (track, artist, progress, paused status, image URL)
- No client secret, no OAuth server-side flow, no token management
Platform Support #
| Platform | Status | Notes |
|---|---|---|
| Android | ✅ | Spotify App Remote SDK |
| iOS | ⏳ | Planned |
| Web/Desktop | ❌ | Not targeted |
Prerequisites #
- A Spotify Developer account.
- Create an app → copy the Client ID.
- Add a redirect URI (e.g.
your.app://callback) in the dashboard. - The Spotify app must be installed on the device.
No client secret is needed — Spotikit uses the App Remote SDK only.
Installation & Required Android Init #
-
Add to
pubspec.yaml:dependencies: spotikit: ^2.0.0 -
Fetch packages:
flutter pub get -
Required (once per clone / after cleaning android dir): run the init script to download the Spotify App Remote AAR and insert the Gradle include:
dart run spotikit:android_initTo use a custom redirect URI:
dart run spotikit:android_init --fallback-url=your.app://callback -
(Optional) To clean and re-initialise:
dart run spotikit:android_clean && dart run spotikit:android_init -
Ensure
minSdkVersion >= 21.
Intent Filter (only if using a custom scheme/host) #
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="your.app" android:host="callback" />
</intent-filter>
Quick Start #
import 'package:spotikit/spotikit.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final spotikit = Spotikit.instance;
spotikit.configureLogging(loggingEnabled: true);
await spotikit.initialize(
clientId: 'YOUR_CLIENT_ID',
redirectUri: 'your.app://callback',
);
await spotikit.connectToSpotify();
await spotikit.playUri(spotifyUri: 'spotify:track:4cOdK2wGLETKBW3PvgPWqT');
spotikit.onPlaybackStateChanged.listen((state) {
print('Now playing: ${state.name} by ${state.artist} — ${(state.progress * 100).toStringAsFixed(1)}%');
});
}
Initialization #
await Spotikit.instance.initialize(
clientId: 'YOUR_CLIENT_ID',
redirectUri: 'your.app://callback',
connectToRemote: true, // optionally connect immediately
);
| Parameter | Required | Description |
|---|---|---|
clientId |
✅ | Spotify app Client ID from the developer dashboard |
redirectUri |
✅ | Redirect URI registered in the developer dashboard |
connectToRemote |
❌ | Connect to App Remote immediately (default: false) |
Playback State Stream #
spotikit.onPlaybackStateChanged.listen((state) {
print('Track : ${state.name}');
print('Artist: ${state.artist}');
print('Paused: ${state.isPaused}');
print('Progress: ${state.positionMs}/${state.durationMs} ms');
print('Image URL: ${state.imageUrl}');
});
SpotifyPlaybackState fields:
| Field | Type | Description |
|---|---|---|
uri |
String |
Full Spotify URI of the track |
name |
String |
Track name |
artist |
String |
Primary artist name |
isPaused |
bool |
Whether playback is paused |
positionMs |
int |
Current playback position (ms) |
durationMs |
int |
Total track duration (ms) |
imageUrl |
String? |
Album art URL (HTTPS) |
progress |
double |
positionMs / durationMs (0.0–1.0) |
id |
String |
Track ID extracted from uri |
Control API #
| Action | Method |
|---|---|
| Connect to App Remote | spotikit.connectToSpotify() |
| Play by URI | spotikit.playUri(spotifyUri: ...) |
| Pause | spotikit.pause() |
| Resume | spotikit.resume() |
| Next track | spotikit.skipTrack() |
| Previous track | spotikit.previousTrack() |
| Seek to position | spotikit.seekTo(positionMs: ...) |
| Skip forward N seconds | spotikit.skipForward(seconds: 10) |
| Skip backward N seconds | spotikit.skipBackward(seconds: 10) |
| Get current track info | spotikit.getPlayingTrackInfo() |
| Is playing? | spotikit.isPlaying() |
| Disconnect | spotikit.disconnect() |
| Logout & disconnect | spotikit.logout() |
Track Info #
getPlayingTrackInfo() returns a SpotifyTrackInfo? with fields:
| Field | Type | Description |
|---|---|---|
name |
String |
Track name |
artist |
String |
Primary artist name |
uri |
String |
Full Spotify URI |
isPaused |
bool |
Whether playback is paused |
Logging #
spotikit.configureLogging(
loggingEnabled: true, // verbose info logs (default: false)
errorLoggingEnabled: true, // error logs (default: true)
);
Error Handling #
Native issues surface as PlatformException. Spotikit wraps initialization failures in a SpotikitException.
Common error codes from native:
| Code | Cause |
|---|---|
SPOTIFY_NOT_INSTALLED |
Spotify app is not installed on the device |
CONNECTION_ERROR |
App Remote failed to connect |
NOT_CONNECTED |
A control method was called before connecting |
NOT_INIT |
connectToSpotify called before initialize |
INIT_FAILED |
Missing clientId or redirectUri |
NO_TRACK |
getTrackInfo called while nothing is playing |
Dev Scripts #
dart run spotikit:android_init # REQUIRED after adding plugin / fresh clone / cleaning android
dart run spotikit:android_clean # Optional helper (then rerun android_init)
Roadmap #
- iOS support
- Shuffle / repeat control
- Queue management
- Volume control
- Context metadata
Contributing #
- Fork / branch
- Implement + update example / docs
flutter format .& fix analyser warnings- Open a PR with a description and test notes
License #
MIT © 2026 spotikit contributors
Attribution #
Uses the Spotify App Remote SDK. Not affiliated with or endorsed by Spotify AB.
Support #
Issues / ideas: https://github.com/ArdaKoksall/spotikit/issues
Enjoy building with Spotikit! 🎧