ryanheise / just_audio

Audio Player
1.04k stars 667 forks source link

There seems to be no way when using justaudio_background to catch errors -> All Unhandled #870

Open matecode opened 1 year ago

matecode commented 1 year ago

First of all thanks for solving #832, i tried it and everything seems to work as expected so far. As i cannot write in the old bug report anymore (yes github, i was off for holiday for 14 days :) ) I use a new one.

But now I'm facing a new issue:

Which API doesn't behave as documented, and how does it misbehave? I cannot catch the errors thrown by the async methods of an AudioPlayer instance if justaudio_background is used, namely load() and play(). The errors are uncaught even if i surround the method calls. I tried with AudioSource.uri and LockCachingAudioSource ... i first thought the problem is LockCachingAudioSource (thats why i named the demo branch) but it seems it is more the justaudio_background handler.

Also playbackEventStream does not give an Error (should it!?)

Minimal reproduction project https://github.com/matecode/just_audio/tree/Lock_Caching_Error_Handling_Bug

To demonstrate I changed the urls of audioSources to not existent links.

As you can see in main.dart in line 72 -> setAudioSource should be catched (preload must be true) because load() is called internally 321 -> play method should be catched

To Reproduce (i.e. user steps, not code) Steps to reproduce the behavior:

  1. set breakpoints in catch blocks line 75/324
  2. run in debug mode

Error messages -> please watch the log for "Unhandled Exception:"

Expected behavior There should be at least one way to handle errors to reflect them to reactions.

Smartphone (please complete the following information):

Flutter SDK version

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.3.5, on macOS 12.6 21G115 darwin-arm, locale de-DE)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 14.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.2)
[✓] VS Code (version 1.72.1)
[✓] Connected device (5 available)
[✓] HTTP Host Availability

• No issues found!

Additional context Some sweets for you! Thanks for your work. sweets

matecode commented 1 year ago

@ryanheise I found out that:

Nico04 commented 1 year ago

Same error here (I'm also using just_audio_background). On Android, if I start player with play() then cut-off internet, I have no errors in playbackEventStream, but I can see an error beeing thrown in console :

E/ExoPlayerImplInternal(16005): Playback error
E/ExoPlayerImplInternal(16005):   UnknownHostException (no network)

Similar happens if you play() when no internet is available : W/ExponenentialBackoff(17999): network unavailable, sleeping.

And because player stays in playing position, it's quite hard to handle theses errors properly.

ryanheise commented 1 year ago

Is it also the case for you that the problem is not present when just_audio_background is not used?

Nico04 commented 1 year ago

Is it also the case for you that the problem is not present when just_audio_background is not used?

I've just re-tested, and I confirm that when I don't call JustAudioBackground.init, player.playbackEventStream.onError is properly called (here where trying to seek in a local file that has been deleted), whereas when initiated, onError is not called.

SpongeManiac commented 1 year ago

I'm having this exact same issue. When seeking or playing a file that doesn't exist. This is when using just_audio_background.

Edit: Just spent a while debugging and trying to figure out where the error is originating from. Here is the stack traces I have so far:

Java:

E/ExoPlayerImplInternal(10192): Playback error
E/ExoPlayerImplInternal(10192):   com.google.android.exoplayer2.ExoPlaybackException: Source error
E/ExoPlayerImplInternal(10192):       at com.google.android.exoplayer2.ExoPlayerImplInternal.handleIoException(ExoPlayerImplInternal.java:632)
E/ExoPlayerImplInternal(10192):       at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:604)
E/ExoPlayerImplInternal(10192):       at android.os.Handler.dispatchMessage(Handler.java:102)
E/ExoPlayerImplInternal(10192):       at android.os.Looper.loopOnce(Looper.java:226)     
E/ExoPlayerImplInternal(10192):       at android.os.Looper.loop(Looper.java:313)
E/ExoPlayerImplInternal(10192):       at android.os.HandlerThread.run(HandlerThread.java:67)
E/ExoPlayerImplInternal(10192):   Caused by: com.google.android.exoplayer2.upstream.FileDataSource$FileDataSourceException: java.io.FileNotFoundException: /data/user/0/com.rpgrogan.free.woodbirdmp3/cache/file_picker/song.mp3: open failed: ENOENT (No such file or 
directory)
E/ExoPlayerImplInternal(10192):       at com.google.android.exoplayer2.upstream.FileDataSource.openLocalFile(FileDataSource.java:201)
E/ExoPlayerImplInternal(10192):       at com.google.android.exoplayer2.upstream.FileDataSource.open(FileDataSource.java:112)
E/ExoPlayerImplInternal(10192):       at com.google.android.exoplayer2.upstream.DefaultDataSource.open(DefaultDataSource.java:258)
E/ExoPlayerImplInternal(10192):       at com.google.android.exoplayer2.upstream.StatsDataSource.open(StatsDataSource.java:84)
E/ExoPlayerImplInternal(10192):       at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1005)
E/ExoPlayerImplInternal(10192):       at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:412)
E/ExoPlayerImplInternal(10192):       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
E/ExoPlayerImplInternal(10192):       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
E/ExoPlayerImplInternal(10192):       at java.lang.Thread.run(Thread.java:1012)
E/ExoPlayerImplInternal(10192):   Caused by: java.io.FileNotFoundException: /data/user/0/com.rpgrogan.free.woodbirdmp3/cache/file_picker/song.mp3: open failed: ENOENT (No such file or directory)

Flutter:

I/flutter ( 7400): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:652:7)
I/flutter ( 7400): #1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:310:18)
I/flutter ( 7400): <asynchronous suspension>
I/flutter ( 7400): #2      MethodChannelAudioPlayer.load (package:just_audio_platform_interface/method_channel_just_audio.dart:58:34)
I/flutter ( 7400): <asynchronous suspension>
I/flutter ( 7400): #3      _PlayerAudioHandler.customLoad (package:just_audio_background/just_audio_background.dart:387:18)
I/flutter ( 7400): <asynchronous suspension>
I/flutter ( 7400): #4      AudioPlayer._load (package:just_audio/just_audio.dart:823:24) 
I/flutter ( 7400): <asynchronous suspension>
I/flutter ( 7400): #5      AudioPlayer._setPlatformActive.setPlatform (package:just_audio/just_audio.dart:1396:24)
I/flutter ( 7400): <asynchronous suspension>
E/flutter ( 7400): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(0, Source error, null, null)
E/flutter ( 7400):
E/flutter ( 7400): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(0, Source error, null, null)
E/flutter ( 7400):
E/flutter ( 7400): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(0, Source error, null, null)
E/flutter ( 7400):
E/flutter ( 7400): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(0, Source error, null, null)
E/flutter ( 7400):

I took a look at _PlayerAudioHandler.customLoad and MethodChannelAudioPlayer.load. I tried wrapping it them a try catch statement. The error seems to be coming from MethodChannelAudioPlayer.load, however I still get those four Unhandled Exception: PlatformException(0, Source error, null, null) lines.

I can't figure out why errors aren't getting caught by AudioPlayer.subscribeToEvents when using just_audio_background. I can't event catch theses errors when wrapping a call to AudioPlayer.play() with a try.

dickermoshe commented 12 months ago

@ryanheise Any update? Wrapping a AudioPlayer.play() in try works, I just can't listen for errors. There is no way to pause a ConcatenatingAudioSource when internet is cut off . It tries each one until reaching the end. It only then at the end raises an exception.

Placing an onError here does work, I don't know where it's getting lost from there. https://github.com/ryanheise/just_audio/blob/3622d11f14d4191e4c1326c32c7a025941af40ec/just_audio_background/lib/just_audio_background.dart#L171-L173 E.G:

playbackEventMessageStream.listen((event) {
  _justAudioEvent = event;
  _broadcastState();
}, onError: (e, s) {
  print("Error!")
});