You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中使用just_audio播放音乐时如何显示媒体通知?

实现带媒体控制的通知栏播放器

要实现类似音乐APP的通知栏播放器,用flutter_local_notifications完全可行,核心是配置媒体样式通知,并和just_audio的播放状态联动,下面是具体实现步骤:

1. 添加依赖与权限配置

首先在pubspec.yaml中引入所需依赖:

dependencies:
  flutter_local_notifications: ^最新版本号
  just_audio: ^最新版本号

Android端配置

  • 在AndroidManifest.xml添加通知权限与后台播放权限:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

iOS端配置

  • 在Info.plist中开启后台音频权限:
<key>UIBackgroundModes</key>
<array>
  <string>audio</string>
</array>

2. 初始化通知插件

先完成通知插件的初始化,同时创建专属的媒体通知通道:

late FlutterLocalNotificationsPlugin notificationsPlugin;

void initNotifications() async {
  notificationsPlugin = FlutterLocalNotificationsPlugin();
  
  // 初始化配置
  const AndroidInitializationSettings androidInit = AndroidInitializationSettings('@mipmap/ic_launcher');
  const DarwinInitializationSettings iosInit = DarwinInitializationSettings(
    requestAlertPermission: false,
    requestBadgePermission: false,
    requestSoundPermission: false,
  );
  
  const InitializationSettings initSettings = InitializationSettings(
    android: androidInit,
    iOS: iosInit,
  );
  
  // 绑定通知点击回调
  await notificationsPlugin.initialize(
    initSettings,
    onDidReceiveNotificationResponse: (response) => handleNotificationAction(response.actionId!),
  );
  
  // 创建媒体专属通知通道(Android必填)
  const AndroidNotificationChannel mediaChannel = AndroidNotificationChannel(
    'music_player_channel',
    '音乐播放器',
    description: '显示音乐播放控制按钮',
    importance: Importance.high,
    playSound: false,
    enableVibration: false,
    groupKey: AndroidNotificationChannelGroup.mediaGroupId,
  );
  await notificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.createNotificationChannel(mediaChannel);
}

3. 创建并显示媒体通知

根据当前播放状态生成带控制按钮的通知,重点是配置MediaStyleInformation实现媒体样式:

void showMusicNotification({
  required String songTitle,
  required String artistName,
  String? albumArtLocalPath,
  required bool isPlaying,
}) async {
  // 定义通知操作按钮
  final List<AndroidNotificationAction> actions = [
    const AndroidNotificationAction(
      'prev',
      '上一曲',
      showsUserInterface: false,
      icon: DrawableResourceAndroidBitmap('ic_skip_previous'),
    ),
    AndroidNotificationAction(
      isPlaying ? 'pause' : 'play',
      isPlaying ? '暂停' : '播放',
      showsUserInterface: false,
      icon: DrawableResourceAndroidBitmap(isPlaying ? 'ic_pause' : 'ic_play'),
    ),
    const AndroidNotificationAction(
      'next',
      '下一曲',
      showsUserInterface: false,
      icon: DrawableResourceAndroidBitmap('ic_skip_next'),
    ),
  ];
  
  // Android媒体通知详情配置
  final AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
    'music_player_channel',
    '音乐播放器',
    importance: Importance.high,
    priority: Priority.high,
    ongoing: true, // 通知无法被滑动删除
    autoCancel: false,
    styleInformation: const MediaStyleInformation(
      mediaSessionId: 'music_session',
      showCancelButton: false,
    ),
    actions: actions,
    largeIcon: albumArtLocalPath != null ? FilePathAndroidBitmap(albumArtLocalPath) : null,
    smallIcon: const DrawableResourceAndroidBitmap('ic_music_note'),
  );
  
  // iOS通知配置
  final DarwinNotificationDetails iosDetails = DarwinNotificationDetails(
    categoryIdentifier: 'music_player',
    presentAlert: false,
    presentBadge: false,
    presentSound: false,
  );
  
  final NotificationDetails notificationDetails = NotificationDetails(
    android: androidDetails,
    iOS: iosDetails,
  );
  
  // 显示/更新通知(固定ID实现覆盖更新)
  await notificationsPlugin.show(
    1,
    songTitle,
    artistName,
    notificationDetails,
  );
}

4. 联动just_audio播放状态

监听AudioPlayer的状态变化,实时更新通知内容:

late AudioPlayer audioPlayer;

void initAudioPlayer() async {
  audioPlayer = AudioPlayer();
  
  // 监听播放状态变更,同步更新通知
  audioPlayer.playbackEventStream.listen((event) {
    final bool isPlaying = event.processingState == ProcessingState.playing;
    showMusicNotification(
      songTitle: '你的歌曲标题',
      artistName: '歌手名称',
      albumArtLocalPath: '本地封面图路径', // 网络图需先下载到本地再传入
      isPlaying: isPlaying,
    );
  });
  
  // 加载音频资源
  await audioPlayer.setUrl('音频文件URL');
}

5. 处理通知按钮点击事件

实现按钮对应的播放控制逻辑:

void handleNotificationAction(String actionId) async {
  switch (actionId) {
    case 'play':
      await audioPlayer.play();
      break;
    case 'pause':
      await audioPlayer.pause();
      break;
    case 'prev':
      // 自定义上一曲逻辑
      break;
    case 'next':
      // 自定义下一曲逻辑
      break;
  }
}

注意事项

  • Android通知图标需放在res/drawable或res/mipmap目录,确保为透明背景的符合系统规范的图标。
  • 网络封面图需先下载到本地存储,再通过FilePathAndroidBitmap传入。
  • iOS媒体通知样式相对简洁,控制按钮需提前在Info.plist配置通知类别。

内容的提问来源于stack exchange,提问作者mohammad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 02:18:18