Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

audioplayers resume sometimes crashes on iOS #764

Closed
MathiasSolling opened this issue Feb 12, 2021 · 8 comments
Closed

audioplayers resume sometimes crashes on iOS #764

MathiasSolling opened this issue Feb 12, 2021 · 8 comments
Labels

Comments

@MathiasSolling
Copy link

MathiasSolling commented Feb 12, 2021

Looking in Crashlytics I see that my app crashes sometimes on iOS caused by audioplayers resume function.

Crashed: com.apple.main-thread
EXC_BREAKPOINT 0x000000010462bc9c
0
audioplayers
$s12audioplayers23SwiftAudioplayersPluginC6resume8playerIdySS_tF + 356
1
audioplayers
$s12audioplayers23SwiftAudioplayersPluginC6handle_6resultySo17FlutterMethodCallC_yypSgctF015$syXlSgIeyBy_ypL7Iegn_TRyXlSgIeyBy_Tf1ncn_nTf4nng_n + 3816
2
audioplayers
$s12audioplayers23SwiftAudioplayersPluginC6handle_6resultySo17FlutterMethodCallC_yypSgctFTo + 76
3
Flutter
(Missing)
4
Flutter
(Missing)
5
Flutter
(Missing)
6
Flutter
(Missing)
7
Flutter
(Missing)
8
CoreFoundation
CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION + 28
9
CoreFoundation
__CFRunLoopDoTimer + 1004
10
CoreFoundation
__CFRunLoopDoTimers + 324
11
CoreFoundation
__CFRunLoopRun + 1912
12
CoreFoundation
CFRunLoopRunSpecific + 572
13
GraphicsServices
GSEventRunModal + 160
14
UIKitCore
-[UIApplication _run] + 1052
15
UIKitCore
UIApplicationMain + 164
16
Runner
AppDelegate.swift - Line 5
main + 5
17
libdyld.dylib
start + 4
Thread #1
0
libsystem_kernel.dylib
__workq_kernreturn + 8
2
libsystem_pthread.dylib
start_wqthread + 8
Thread #2
0
libsystem_pthread.dylib
start_wqthread + 190
com.apple.uikit.eventfetch-thread
0
libsystem_kernel.dylib
mach_msg_trap + 8
10
libsystem_pthread.dylib
thread_start + 8
Thread #3
0
libsystem_kernel.dylib
__workq_kernreturn + 8
2
libsystem_pthread.dylib
start_wqthread + 8
io.flutter.1.ui
0
libsystem_kernel.dylib
mach_msg_trap + 8
8
libsystem_pthread.dylib
thread_start + 8
io.flutter.1.raster
0
libsystem_kernel.dylib
semaphore_timedwait_trap + 8
27
libsystem_pthread.dylib
thread_start + 8
io.flutter.1.io
0
libsystem_kernel.dylib
mach_msg_trap + 8
8
libsystem_pthread.dylib
thread_start + 8
io.flutter.worker.1
0
libsystem_kernel.dylib
__psynch_cvwait + 8
5
libsystem_pthread.dylib
thread_start + 8
io.flutter.worker.2
0
libsystem_kernel.dylib
__psynch_cvwait + 8
5
libsystem_pthread.dylib
thread_start + 8
dart:io EventHandler
0
libsystem_kernel.dylib
kevent + 8
4
libsystem_pthread.dylib
thread_start + 8
com.google.firebase.crashlytics.MachExceptionServer
0
FirebaseCrashlytics
FIRCLSProcessRecordAllThreads + 180
5
libsystem_pthread.dylib
thread_start + 8
com.google.firebase.firestore.rpc
0
libsystem_kernel.dylib
poll + 8
12
libsystem_pthread.dylib
start_wqthread + 8
DartWorker
0
libsystem_kernel.dylib
__psynch_cvwait + 8
6
libsystem_pthread.dylib
thread_start + 8
Thread #4
0
libsystem_kernel.dylib
__psynch_cvwait + 8
7
libsystem_pthread.dylib
thread_start + 8
Thread #5
0
libsystem_kernel.dylib
__psynch_cvwait + 8
6
libsystem_pthread.dylib
thread_start + 8
Thread #6
0
libsystem_kernel.dylib
__psynch_cvwait + 8
6
libsystem_pthread.dylib
thread_start + 8
Thread #7
0
libsystem_kernel.dylib
__psynch_cvwait + 8
6
libsystem_pthread.dylib
thread_start + 8
com.apple.NSURLConnectionLoader
0
libsystem_kernel.dylib
mach_msg_trap + 8
8
libsystem_pthread.dylib
thread_start + 8
Thread #8
0
libsystem_kernel.dylib
__psynch_cvwait + 8
6
libsystem_pthread.dylib
thread_start + 8
Thread #9
0
libsystem_kernel.dylib
__workq_kernreturn + 8
2
libsystem_pthread.dylib
start_wqthread + 8
AudioPlayerIsolate.2.ui
0
libsystem_kernel.dylib
mach_msg_trap + 8
8
libsystem_pthread.dylib
thread_start + 8
AudioPlayerIsolate.2.raster
0
libsystem_kernel.dylib
mach_msg_trap + 8
8
libsystem_pthread.dylib
thread_start + 8
AudioPlayerIsolate.2.io
0
libsystem_kernel.dylib
mach_msg_trap + 8
8
libsystem_pthread.dylib
thread_start + 8
DartWorker
0
libsystem_kernel.dylib
__psynch_cvwait + 8
6
libsystem_pthread.dylib
thread_start + 8
DartWorker
0
libsystem_kernel.dylib
__psynch_cvwait + 8
6
libsystem_pthread.dylib
thread_start + 8
DartWorker
0
libsystem_kernel.dylib
__psynch_cvwait + 8
6
libsystem_pthread.dylib
thread_start + 8

I have no code to reproduce since I do not know when this happens. As seen in the logs it seems like it is when audioPlayers.resume() is called.

It works fine on Android.

@MathiasSolling MathiasSolling changed the title audioPlayers resume sometimes crashes on iOS audioplayers resume sometimes crashes on iOS Feb 12, 2021
@mikeesouth
Copy link

mikeesouth commented Feb 17, 2021

Hmm. Could this be related to this discussion? #745

We're experiencing something similar. We're not calling AudioPlayers.resume() at all, we're just using play() and stop() but we do experience some kind of crash on iOS (not on Android afaik) and we cannot reproduce it.

@MathiasSolling do you know if you can play other sounds after this crash? My experience is that when audioplayers "crashes" on iOS then we cannot play sounds at all and our app freezes when it's waiting for a sound to be played because the sound isn't played and we wait forever. Even if the user presses back or something else, no new sounds can be played until the app is stopped and restarted.

What version of audioplayers and flutter are you using? We're using audioplayers 0.16.1 (we cannot upgrade due to issue #671) and flutter stable (1.22.6).

@muarachmann
Copy link
Contributor

muarachmann commented Feb 17, 2021 via email

@mikeesouth
Copy link

@muarachmann No, unfortunately we do not get any logs from either try/catches around play() or the onPlayerError stream - it seems like the error is silent somehow.

In short we're just calling play() and then wait until player.onPlayerStateChanged stream sends an event with something else than "PLAYING" or player.onPlayerError stream sends an event. In those cases we tell the app that the sound has completed playing, we remove the temporary file (mp3) that we played and we open the audioplayer for next sound to be played. So we do not even call stop() in this case, just wait for the next play().

We log all errors from onPlayerError but we do not get any errors reported on that stream. I can mention that our app plays several thousands of sounds every day on several hundred devices without any real issues but we approximate that maybe 10-50% (?) of our iOS devices crashes within an hour of use or so. It's difficult to measure and know specifics but it seems like it could happen after 10 sounds or after 1000 sounds and sometimes not at all. It happens on different sounds and in different places in our app so it's not related to some specific audio file.

From the error reports (which our users have communicated manually to us) it seems like the app calls play('foo.mp3', isLocal: true) and no exception is thrown and the state is set to PLAYING but no sound is played and no state change is reported on the onPlayerStateChanged stream and no error is reported on the onPlayerError stream. It seems like we're stuck waiting for the sound to play but no sound is played. Our app waits for the audio to complete and it waits forever. Even if we queue new sounds (with a new audioplayer) no sound is played and that audioplayer also waits forever for the sound to play. The only solution is to kill the app and restart it. We cannot reproduce this in our tests on ipads or android slates and not on emulator either. But our customers run into this quite often unfortunately. We've created flutter driver tests that simulates user behavior in our app and that use the app for 30 minutes straight and it's working just fine on every test. This makes me believe that it's something that happens on the device that is causing the error. Maybe a push notification arrives just as a sound plays and that causes some bug in the iOS code. Or, the user minimizes the app when a sound is played and that triggers some bug. Or if the user changes the volume while a sound is playing or if the sound is muted while a sound is playing. I'm just guessing here but since we haven't reproduced it once it feels like it's some kind of device setting/signal that affects the ios code for audioplayers library.

After carefully walking through the code now I see these potential problems:

  1. We do not check the return code of AudioPlayer.play(). What does it mean if it does not return 1? How should we handle that? What should we do if we get 0 or 2 or 54 back from this method, what does those int codes mean? Should we call stop() and try again?
  2. I read in the troubleshooting.md that in order to play sounds in the background we should set "audio" as UIBackgroundModes in Info.plist for iOS. We have not set this variable but still, audio is played in the background. Not sure why sound is working in the background without this setting but maybe that could cause some kind of vioaltion in iOS that "crashes" the AudioPlayer without an error being reported to the onPlayerError stream?
  3. We do not have full coverage on PAUSED state, we do not call pause() or resume() in our code but maybe some iOS feature could cause the AudioPlayer to pause? That could cause an issue in our code. I will cover that better in the next version of our app.

Any tips and suggestions are more than welcome.

@mikeesouth
Copy link

@muarachmann I'm not sure that my issue is related so I created a separate issue for my problem with example code. I can see that play() is called, returns 1 but no sound is played and I do not get any duration. Please see #768 for my issue that may be related, not sure.

@MathiasSolling
Copy link
Author

MathiasSolling commented Mar 1, 2021

@mikeesouth I switched to just_audio plugin. Took just 10 minutes to switch and no errors reported from neither Crashlytics and users. Just the past week there has been 75.000 sounds played, no errors.

@mikeesouth
Copy link

@MathiasSolling glad that helped for you and I suggest that you stick to it if it works for you. But to be fair I will post my findings about just_audio.

I tried just_audio earlier and then again about 2 weeks ago, both times I had troubles with performance, sound effects in quick succession were much slower on just_audio than in audioplayers (especially compared to LOW_LATENCY mode). Furthermore I had troubles that some sounds were played double on iOS (rare but it happened). Finally sounds weren't playing correctly in parallell in all situations (some sounds could "cut" sounds that were already playing) - no errors though but the user experience was worse than audioplayers (when it was working).

Then I upgraded to the latest version of just_audio and that crashed 100% on Android devices (runtime) but still worked on iOS. Very strange. Furthermore there are a lot of issues reported on just_audio repo (i.e. open bugs).

I also tried flutter_sound lib, no errors with that either but the performance and general experience was worse.

I want to be clear: I would really like to find an alternative, just switch 10 minutes and be done with it. I have very few requirements on fancy features, just play sounds, get duration and get position in stream - that's all.

@erickzanardo
Copy link
Member

@MathiasSolling

I want to be clear: I would really like to find an alternative, just switch 10 minutes and be done with it. I have very few requirements on fancy features, just play sounds, get duration and get position in stream - that's all.

You could give a try on our sister library ocarina, it has quite a smaller feature set than audioplayers, but it is focused on performance and maybe it could fit your need

@erickzanardo
Copy link
Member

Regarding the original issue, there isn't enough information on this issue for us to act on. If anyone can get a reproducible way of this, feel free to comment here and we can re open this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants