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

Flutter单AudioPlayer连续播放多音频报IllegalStateException异常

问题背景

在Dart/Flutter应用开发过程中,复用单个audioplayers库的AudioPlayer对象按顺序依次播放多个音频文件时,如果切换播放新音频前不对播放器实例执行重新初始化操作,会直接抛出异常,核心报错标识为attachNewPlayer called in state 4,完整错误日志如下:

E/MediaPlayerNative( 8096): attachNewPlayer called in state 4
D/AudioPlayers( 8096): Unexpected error!
D/AudioPlayers( 8096): java.lang.IllegalStateException
D/AudioPlayers( 8096): at android.media.MediaPlayer._setDataSource(Native Method)
D/AudioPlayers( 8096): at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1301)
D/AudioPlayers( 8096): at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1284)
D/AudioPlayers( 8096): at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1241)
D/AudioPlayers( 8096): at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1218)
D/AudioPlayers( 8096): at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1183)
D/AudioPlayers( 8096): at xyz.luan.audioplayers.source.UrlSource.setForMediaPlayer(UrlSource.kt:16)
D/AudioPlayers( 8096): at xyz.luan.audioplayers.player.MediaPlayerPlayer.setSource(MediaPlayerPlayer.kt:51)
D/AudioPlayers( 8096): at xyz.luan.audioplayers.player.WrappedPlayer.setSource(WrappedPlayer.kt:29)
D/AudioPlayers( 8096): at xyz.luan.audioplayers.AudioplayersPlugin.handler(AudioplayersPlugin.kt:87)
D/AudioPlayers( 8096): at xyz.luan.audioplayers.AudioplayersPlugin.access$handler(AudioplayersPlugin.kt:23)
D/AudioPlayers( 8096): at xyz.luan.audioplayers.AudioplayersPlugin$onAttachedToEngine$1$1.invoke(AudioplayersPlugin.kt:39)
D/AudioPlayers( 8096): at xyz.luan.audioplayers.AudioplayersPlugin$onAttachedToEngine$1$1.invoke(AudioplayersPlugin.kt:39)
D/AudioPlayers( 8096): at xyz.luan.audioplayers.AudioplayersPlugin$safeCall$1.invokeSuspend(AudioplayersPlugin.kt:58)
D/AudioPlayers( 8096): at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
D/AudioPlayers( 8096): at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
D/AudioPlayers( 8096): at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:39)
D/AudioPlayers( 8096): at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
D/AudioPlayers( 8096): at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
D/AudioPlayers( 8096): at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
D/AudioPlayers( 8096): at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
D/AudioPlayers( 8096): at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
E/flutter ( 8096): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: PlatformException(Unexpected error!, null, java.lang.IllegalStateException
E/flutter ( 8096): at android.media.MediaPlayer._setDataSource(Native Method)
E/flutter ( 8096): at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1301)
E/flutter ( 8096): at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1284)
E/flutter ( 8096): at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1241)
E/flutter ( 8096): at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1218)
E/flutter ( 8096): at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1183)
E/flutter ( 8096): at xyz.luan.audioplayers.source.UrlSource.setForMediaPlayer(UrlSource.kt:16)
E/flutter ( 8096): at xyz.luan.audioplayers.player.MediaPlayerPlayer.setSource(MediaPlayerPlayer.kt:51)
E/flutter ( 8096): at xyz.luan.audioplayers.player.WrappedPlayer.setSource(WrappedPlayer.kt:29)
E/flutter ( 8096): at xyz.luan.audioplayers.AudioplayersPlugin.handler(AudioplayersPlugin.kt:87)
E/flutter ( 8096): at xyz.luan.audioplayers.AudioplayersPlugin.access$handler(AudioplayersPlugin.kt:23)
E/flutter ( 8096): at xyz.luan.audioplayers.AudioplayersPlugin$onAttachedToEngine$1$1.invoke(AudioplayersPlugin.kt:39)
E/flutter ( 8096): at xyz.luan.audioplayers.AudioplayersPlugin$onAttachedToEngine$1$1.invoke(AudioplayersPlugin.kt:39)
E/flutter ( 8096): at xyz.luan.audioplayers.AudioplayersPlugin$safeCall$1.invokeSuspend(AudioplayersPlugin.kt:58)
E/flutter ( 8096): at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
E/flutter ( 8096): at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
E/flutter ( 8096): at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:39)
E/flutter ( 8096): at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
E/flutter ( 8096): at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
E/flutter ( 8096): at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
E/flutter ( 8096): at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
E/flutter ( 8096): at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
E/flutter ( 8096): , null)
E/flutter ( 8096): #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:607:7)
E/flutter ( 8096): #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:177:18)
E/flutter ( 8096):
E/flutter ( 8096): #2 AudioPlayer.play (package:audioplayers/src/audioplayer.dart:111:5)
E/flutter ( 8096):
E/flutter ( 8096): #3 AudioBloc._onAudioPicking (package:task4/blocs/audio_bloc/audio_bloc.dart:130:7)
E/flutter ( 8096):
E/flutter ( 8096): #4 Bloc.on..handleEvent (package:bloc/src/bloc.dart:211:13)
报错原因

这个异常由Android原生MediaPlayer的状态机校验机制触发。Android系统的MediaPlayer有严格的状态流转规则,只有播放器处于Idle空闲状态时,才能调用setDataSource设置新的音频源。如果播放器处于播放中、暂停、播放完成等非空闲状态,直接设置新音频源就会抛出IllegalStateException,也就是日志中看到的native层报错。
直接复用AudioPlayer实例切音频时,没有先将播放器重置回空闲状态,直接触发了设置新数据源的操作,必然会触发异常。

解决方案

不需要每次播放新音频都重新创建AudioPlayer实例,按以下流程操作即可正常复用实例:

  • 切换新音频前,先调用await audioPlayer.stop()停止当前正在进行的播放任务,将播放器状态切回可设置新源的状态,之后再传入新的音频路径调用play()即可正常播放。
  • 如果执行stop操作后仍然偶发状态异常,可以在stop之后额外调用await audioPlayer.release()释放底层占用的播放器资源,后续调用play方法时,audioplayers插件会自动重新初始化原生播放器实例,不会再触发状态校验错误。
  • 禁止在播放器处于播放、暂停、播放完成状态时,直接调用setSource或者直接传入新音频地址调用play(),这类操作会直接触发原生层的状态异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 09:15:35