I'm working on an app for podcasts and, one of the features of the app is that it saves the position where a user leaves a podcast to play another or leaves the app entirely. I couldn't find a way to play a saved podcast from its lastPlayed
timestamp without first playing said podcast using audioHandler.play()
and the seeking to the position where the user left off using audioHandler.seek(lastPlayed)
. Using this method of playing, I get this error: and the podcast plays from the beginning instead of where it should. Any suggestions?
W/System.err(27454): com.google.android.exoplayer2.IllegalSeekPositionException W/System.err(27454): at com.google.android.exoplayer2.ExoPlayerImpl.seekTo(ExoPlayerImpl.java:611) W/System.err(27454): at com.google.android.exoplayer2.SimpleExoPlayer.seekTo(SimpleExoPlayer.java:1527) W/System.err(27454): at com.ryanheise.just_audio.AudioPlayer.seek(AudioPlayer.java:953) W/System.err(27454): at com.ryanheise.just_audio.AudioPlayer.onMethodCall(AudioPlayer.java:455) W/System.err(27454): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233) W/System.err(27454): at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:85) W/System.err(27454): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:818) W/System.err(27454): at android.os.MessageQueue.nativePollOnce(Native Method) W/System.err(27454): at android.os.MessageQueue.next(MessageQueue.java:335) W/System.err(27454): at android.os.Looper.loop(Looper.java:206) W/System.err(27454): at android.app.ActivityThread.main(ActivityThread.java:8512) W/System.err(27454): at java.lang.reflect.Method.invoke(Native Method) W/System.err(27454): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) W/System.err(27454): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130) E/flutter (27454): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: PlatformException(Illegal state: null, null, null, null)
You can achieve this in two ways:
seek
to complete before calling play
. Or,initialPosition
parameter of just_audio's setAudioSource
.I would try to handle the restoration of the player's saved position transparently, inside of your audio handler. That way, the client of your audio handler won't need to know how that is handled and simply calls audioHandler.play()
when it wants to play, and the audio handler will internally know which position to start playing at.
The way you could achieve this is to restore the player's state from the constructor of your audio handler. So for example, your audio handler's initialisation code could include:
player = AudioPlayer();
await player.setAudioSource(source,
initialPosition: savedPosition);
You're getting an IllegalSeekPositionException
because the ExoPlayer library on Android thinks you're seeking to a position that is not within the timeline of that file. You might want to inspect the value of the seek position compared to the duration and ensure that it's less.