搜索插件、代码仓与 APP 分类

插件详情v4.1.0

flutter_radio_player

适用于 Flutter 的在线收音机播放器,支持后台播放、锁屏控制以及 Android 和 iOS 的流媒体支持。

AndroidiOS
近 30 天下载
109
喜欢数
137
Pub 分数
160

安装插件

flutter pub add flutter_radio_player

插件介绍

基于插件公开信息、社区数据与项目使用情况整理的选型参考。

Flutter Radio Player 是一个 Flutter 包,可让开发者在应用中集成在线广播流媒体功能,支持在 Android 和 iOS 上的后台播放和锁屏控制。它提供无缝的音频流媒体体验,让用户能够不间断地收听网络广播电台。该包设计简洁易用,提供清晰的 API 来管理播放、元数据显示以及媒体会话集成。它利用原生平台功能,确保在各种设备上都能实现流畅的性能。

适合场景

  • 流媒体互联网广播电台
  • 构建支持后台播放的音乐或播客应用
  • 创建带有锁屏媒体控制的应用程序
  • 开发面向移动设备的音频应用
  • 在应用挂起期间启用连续播放

主要特点

  • 背景音频播放
  • 锁屏媒体控制
  • 跨平台支持(Android 和 iOS)
  • 实时流媒体集成
  • 媒体会话管理
  • 播放期间的元数据显示

适合对象

  • 移动音频应用开发者
  • 广播电台应用开发者
  • 需要持续音频播放的应用程序
  • 同时针对 Android 和 iOS 的开发者
  • 需要最少设置即可流式传输音频的项目

使用建议

  • 需要适当的权限以在后台执行
  • 可能需要为iOS后台模式进行额外配置
  • 依赖稳定的互联网连接进行流媒体播放
  • 仅限音频内容
  • 平台特定的行为可能会略有不同

原始 README

以下为关联源码仓库的 README 原文快照,最新内容请访问源码仓库。

logo

Flutter Radio Player

Pub Version Pub Likes Pub Points CI

A Flutter plugin for playing streaming radio with background playback, lock screen controls, and platform-native media integrations.

Example Player

Android iOS
Support SDK 21+ iOS 14+

Features

  • Background audio playback with no extra configuration
  • Lock screen and notification media controls
  • ICY/Shoutcast metadata extraction
  • Multiple source queue with next/previous/jump-to navigation
  • Volume control with stream updates
  • Artwork support (asset paths and remote URLs)
  • watchOS, WearOS, CarPlay, and Android Auto integration
  • Swift Package Manager and CocoaPods support on iOS

Quick Start

Installation
flutter pub add flutter_radio_player
Minimal Example
import 'package:flutter_radio_player/flutter_radio_player.dart';

final player = FlutterRadioPlayer();

await player.initialize([
  const RadioSource(url: 'https://example.com/stream'),
], playWhenReady: true);

Working with Sources

Define your radio stations using the RadioSource model:

const sources = [
  RadioSource(url: 'https://example.com/stream'),
  RadioSource(
    url: 'https://example.com/jazz',
    title: 'Jazz FM',
    artwork: 'assets/jazz_cover.jpg', // bundled asset
  ),
  RadioSource(
    url: 'https://example.com/rock',
    title: 'Rock Radio',
    artwork: 'https://example.com/rock_cover.png', // remote URL
  ),
];

await player.initialize(sources, playWhenReady: true);
Field Type Description
url String Stream URL (required)
title String? Display name for lock screen
artwork String? Asset path or URL for album artwork

Working with Playback Controls

await player.play();
await player.pause();
await player.playOrPause(); // toggle

// Navigate sources
await player.nextSource();
await player.previousSource();
await player.jumpToSourceAtIndex(2);

// Volume (0.0 to 1.0)
await player.setVolume(0.8);
final volume = await player.getVolume();

// Clean up when done
await player.dispose();

Working with Streams

Listen to real-time player state changes using streams:

Playback State
player.isPlayingStream.listen((bool isPlaying) {
  print(isPlaying ? 'Playing' : 'Paused');
});
Now Playing / ICY Metadata
player.nowPlayingStream.listen((NowPlayingInfo info) {
  print('Now playing: ${info.title}');
});

The nowPlayingStream automatically extracts ICY metadata from Shoutcast/Icecast streams. If the stream provides metadata (e.g., artist and song title), it will appear here without any extra configuration.

Volume Changes
player.volumeStream.listen((VolumeInfo vol) {
  print('Volume: ${vol.volume}, Muted: ${vol.isMuted}');
});

Full Example

A complete player widget with play/pause, skip controls, metadata display, and volume slider:

import 'package:flutter/material.dart';
import 'package:flutter_radio_player/flutter_radio_player.dart';

class RadioPlayerWidget extends StatefulWidget {
  const RadioPlayerWidget({super.key});

  @override
  State<RadioPlayerWidget> createState() => _RadioPlayerWidgetState();
}

class _RadioPlayerWidgetState extends State<RadioPlayerWidget> {
  final _player = FlutterRadioPlayer();
  double _volume = 0.5;

  @override
  void initState() {
    super.initState();
    _player.initialize([
      const RadioSource(
        url: 'https://s2-webradio.antenne.de/chillout?icy=https',
        title: 'Antenne Chillout',
      ),
      const RadioSource(
        url: 'https://radio.lotustechnologieslk.net:2020/stream/sunfmgarden?icy=https',
        title: 'SunFM - Sri Lanka',
      ),
    ], playWhenReady: true);
  }

  @override
  void dispose() {
    _player.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        // Now playing info
        StreamBuilder<NowPlayingInfo>(
          stream: _player.nowPlayingStream,
          builder: (context, snapshot) {
            final title = snapshot.data?.title ?? 'No track info';
            return Text(title, style: Theme.of(context).textTheme.titleLarge);
          },
        ),
        const SizedBox(height: 24),

        // Transport controls
        StreamBuilder<bool>(
          stream: _player.isPlayingStream,
          builder: (context, snapshot) {
            final isPlaying = snapshot.data ?? false;
            return Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                IconButton(
                  iconSize: 36,
                  onPressed: _player.previousSource,
                  icon: const Icon(Icons.skip_previous_rounded),
                ),
                IconButton(
                  iconSize: 48,
                  onPressed: () => isPlaying ? _player.pause() : _player.play(),
                  icon: Icon(isPlaying ? Icons.pause_rounded : Icons.play_arrow_rounded),
                ),
                IconButton(
                  iconSize: 36,
                  onPressed: _player.nextSource,
                  icon: const Icon(Icons.skip_next_rounded),
                ),
              ],
            );
          },
        ),
        const SizedBox(height: 16),

        // Volume slider
        Row(
          children: [
            const Icon(Icons.volume_down_rounded),
            Expanded(
              child: Slider(
                value: _volume,
                onChanged: (value) {
                  setState(() => _volume = value);
                  _player.setVolume(value);
                },
              ),
            ),
            const Icon(Icons.volume_up_rounded),
          ],
        ),
      ],
    );
  }
}

See the example app for the full runnable project.

Platform Setup

Android

Add the following permissions to your AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />

FOREGROUND_SERVICE and FOREGROUND_SERVICE_MEDIA_PLAYBACK are already declared by the plugin. INTERNET must be declared by the host app.

If your radio streams use plain HTTP (not HTTPS), opt in to cleartext traffic. Either add the attribute to your <application> tag:

<application
    android:usesCleartextTraffic="true"
    ...>

Or, preferred, whitelist only the streaming domains via a network security config (res/xml/network_security_config.xml):

<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">your-stream-host.example.com</domain>
    </domain-config>
</network-security-config>

Then reference it from your <application> tag: android:networkSecurityConfig="@xml/network_security_config".

iOS
  1. Enable Audio, AirPlay, and Picture in Picture under your target's Signing & Capabilities > Background Modes in Xcode:

Xcode Configuration

  1. If your radio streams use plain HTTP, add the following to your Info.plist:
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
  1. Swift Package Manager is supported alongside CocoaPods (Flutter 3.24+). No additional configuration is needed.

API Reference

Methods
Method Description
initialize(sources) Set sources and optionally auto-play
play() Resume playback
pause() Pause playback
playOrPause() Toggle play/pause
setVolume(double) Set volume (0.0 to 1.0)
getVolume() Get current volume
nextSource() Skip to next source
previousSource() Skip to previous source
jumpToSourceAtIndex(i) Jump to source at index
dispose() Release player resources
Streams
Stream Type Description
isPlayingStream Stream<bool> Playback state changes
nowPlayingStream Stream<NowPlayingInfo> Track metadata updates
volumeStream Stream<VolumeInfo> Volume and mute changes
Models
Model Fields
RadioSource url (String), title (String?), artwork (String?)
NowPlayingInfo title (String?)
VolumeInfo volume (double), isMuted (bool)

Architecture

This is a federated plugin split into four packages:

Package Description
flutter_radio_player App-facing API
flutter_radio_player_platform_interface Shared interface and models
flutter_radio_player_android Android implementation (Media3/ExoPlayer)
flutter_radio_player_ios iOS implementation (AVFoundation)

Platform communication uses Pigeon for type-safe code generation.

Migration from v3

See the Migration Guide for detailed upgrade instructions.

Support the Plugin

If you find this plugin useful:

  • Give it a star on GitHub
  • Leave a like on pub.dev
  • Buy me a coffee via USDT-TR20: TNuTkL1ZJGu2xntmtzHzSiH5YdVqUeAujr

Contributing

Contributions are welcome. Please open an issue first to discuss what you would like to change.

License

MIT

所属分类

依赖

依赖清单 3 项

  • flutter_radio_player_android^4.1.0
  • flutter_radio_player_ios^4.1.0
  • flutter_radio_player_platform_interface^4.1.0

源码仓库

使用此插件的项目

暂无相关数据。