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
相关产品推荐
相关产品推荐

