Radio Player

A Flutter plugin to play streaming audio content with background support and lock screen controls.

flutter platform pub package

Installation

To enable background playback on iOS, add the following permissions to your ios/Runner/Info.plist:

<key>UIBackgroundModes</key>
<array>
    <string>audio</string>
    <string>processing</string>
</array>

To allow non-secure HTTP streams on iOS, add the following as well:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

Usage

All methods in RadioPlayer are static, so you don't need to create an instance.

Setting a Station

Configure the player with your station details. You can provide a logo from local assets or a network URL.

import 'package:radio_player/radio_player.dart';

RadioPlayer.setStation(
    title: "My Awesome Radio",         // Station name
    url: "YOUR_STREAM_URL_HERE",       // Stream URL (MP3, AAC, HLS)
    logoAssetPath: "assets/logo.png",  // Optional: Local asset path
    logoNetworkUrl: "https://...",     // Optional: Network URL
    parseStreamMetadata: true,         // Optional: Parse ICY metadata
    lookupOnlineArtwork: false,        // Optional: Look up artwork on iTunes
);

Player Controls

Control playback with these simple methods:

RadioPlayer.play();
RadioPlayer.pause();

Resetting Player

To completely stop playback, remove the media notification, and reset the player to an idle state, use reset():

RadioPlayer.reset();

Playback State

Subscribe to playbackStateStream to get updates on the player's state.

// Possible states for playbackState:
//
// - PlaybackState.playing
// - PlaybackState.paused
// - PlaybackState.buffering
// - PlaybackState.unknown
PlaybackState? playbackState;

RadioPlayer.playbackStateStream.listen((value) {
    setState(() { playbackState = value; });
});

Metadata

Subscribe to metadataStream to receive metadata updates from the stream (artist, title, artwork).

// The Metadata object can contain the following fields:
//
// - artist (String?): The artist of the current track.
// - title (String?): The title of the current track.
// - artworkUrl (String?): A URL for the track's artwork.
// - artworkData (Uint8List?): Raw image data for the artwork.
Metadata? _metadata;

RadioPlayer.metadataStream.listen((value) {
    setState(() { _metadata = value; });
});

Setting Custom Metadata

You can manually set the metadata that will be displayed in the notification and lock screen.

RadioPlayer.setCustomMetadata(
    artist: "Custom Artist Name",
    title: "Custom Song Title",
    artworkUrl: "https://example.com/custom_artwork.png" // Optional
);

To avoid conflicts where stream metadata overwrites your custom values, disable automatic metadata parsing by setting parseStreamMetadata: false in the RadioPlayer.setStation() call.

The plugin allows you to display next and previous track buttons on the lock screen and in the media notification. When a user taps these buttons, your app receives a command to handle the action, such as switching to a different radio station.

The process involves two steps:

  1. Enable the buttons: Use setNavigationControls to make the buttons visible.

    RadioPlayer.setNavigationControls(
        showNextButton: true,
        showPreviousButton: false,
    );
    
  2. Listen for commands: Enabling the buttons connects them to the remoteCommandStream. Your app must subscribe to this stream to react when a user presses a button.

    // Possible values for the command:
    //
    // - RemoteCommand.nextTrack
    // - RemoteCommand.previousTrack
    // - RemoteCommand.unknown
        
    RadioPlayer.remoteCommandStream.listen((command) {
        if (command == RemoteCommand.nextTrack) {
            // Your logic to switch to the next station
        } else if (command == RemoteCommand.previousTrack) {
            // Your logic to switch to the previous station
        }
    });
    

Audio Visualizer

The plugin can process the audio stream in real-time to provide data for an audio visualizer. The visualizerStream emits a List<int> containing 16 frequency band amplitudes (0-255).

To simplify implementation and handle streams that don't support real-time data (like some HLS streams on iOS), use the built-in RadioVisualizer widget. It automatically manages the stream lifecycle and provides a smooth fallback animation when needed.

RadioVisualizer(
  fallbackEnabledIOS: true,
  fallbackTimeout: Duration(milliseconds: 500),
  builder: (context, data) {
    return MyVisualizerUI(visualizerData: data);
  },
)

If you prefer to handle the stream manually:

List<int>? _visualizerData;

RadioPlayer.setVisualizerEnabled(true);
RadioPlayer.visualizerStream.listen((data) {
    setState(() => _visualizerData = data);
});

Volume Control

For controlling the device's audio volume, it is currently recommended to use a dedicated plugin. You can use the volume_regulator plugin (also by this author) to manage system volume.

Requirements

  • iOS: 15.0 or later
  • Android: API Level 23 or later

License

This project is licensed under the CC BY-NC-SA 4.0.