Which API doesn't behave as documented, and how does it misbehave?
I'm seeing a MissingPluginException occasionally. I'm uncertain what is causing this yet or how to reproduce it, sorry! Just thought I would post this in case it was helpful to you - I don't see the word "cancel" in very many places in the code.
โโโโโโโโ Exception caught by services library โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The following MissingPluginException was thrown while de-activating platform stream on channel com.ryanheise.just_audio.events.e023926c-796e-4174-a2f8-5d17487a1884:
MissingPluginException(No implementation found for method cancel on channel com.ryanheise.just_audio.events.e023926c-796e-4174-a2f8-5d17487a1884)
When the exception was thrown, this was the stack
#0 MethodChannel._invokeMethod
package:flutter/โฆ/services/platform_channel.dart:160
<asynchronous suspension>
#1 EventChannel.receiveBroadcastStream.<anonymous closure>
package:flutter/โฆ/services/platform_channel.dart:561
<asynchronous suspension>
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Minimal reproduction project
https://github.com/pschuegr/audio_service/commit/924a0fc0e8f4fadba628627fb9cd032618c1eb3e
To Reproduce (i.e. user steps, not code)
Error messages
โโโโโโโโ Exception caught by services library โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The following MissingPluginException was thrown while de-activating platform stream on channel com.ryanheise.just_audio.events.e023926c-796e-4174-a2f8-5d17487a1884:
MissingPluginException(No implementation found for method cancel on channel com.ryanheise.just_audio.events.e023926c-796e-4174-a2f8-5d17487a1884)
When the exception was thrown, this was the stack
#0 MethodChannel._invokeMethod
package:flutter/โฆ/services/platform_channel.dart:160
<asynchronous suspension>
#1 EventChannel.receiveBroadcastStream.<anonymous closure>
package:flutter/โฆ/services/platform_channel.dart:561
<asynchronous suspension>
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Expected behavior
No exception thrown.
Screenshots
If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
Flutter SDK version
[โ] Flutter (Channel dev, 1.26.0-1.0.pre, on macOS 11.0.1 20B29 darwin-x64, locale en-CA)
[โ] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
[โ] Xcode - develop for iOS and macOS (Xcode 12.3)
[โ] Android Studio (version 4.1)
[โ] VS Code (version 1.52.1)
[โ] Connected device (1 available)
โข No issues found!
Additional context
Add any other context about the problem here.
Maybe related: https://github.com/flutter/flutter/issues/62006
However, your case might be different and it might be that the platform channels are working but then the error occurs when disposing the player. If that is the case, I look forward to your reproduction example.
You can also look in darwin/Classes/AudioPlayer.m and comment out these two lines at the bottom of the dispose method:
// Untested:
[_eventChannel setStreamHandler:nil];
[_methodChannel setMethodCallHandler:nil];
Although hopefully that wouldn't introduce a memory leak.
A better solution may be in _setPlatformActive in lib/just_audio.dart:
if (oldPlatformFuture != null) {
final oldPlatform = await oldPlatformFuture;
if (oldPlatform != _idlePlatform) {
await _disposePlatform(oldPlatform);
}
}
// ................ omitted code .......................
_playbackEventSubscription?.cancel();
Once I can reproduce the error, I will try reordering the steps in this sequence so that the subscription is cancelled before the platform is disposed.
Thanks for the context link, I've already seen a lot of this type of error but I assume lots of it is my fault. You're bang-on that it's not very descriptive though!
I've updated my original comment with repro steps. My commit is unfortunately difficult to parse because dartfmt reformatted a bunch of lines , but the only thing I changed from the audio_service example was to add an await player.stop(); before await player.dispose();. Obviously this is completely unnecessary in this example, but I saw this pretty consistently whenever I called player.stop() even if I wasn't about to dispose it.
Thanks @pschuegr , that will definitely be helpful. I will take a look.
Can you try the latest commit? Hopefully it should fix the issue.
Confirmed, thanks!
Great! You might like to pin your app to that git commit for now, as the next release might happen a few days later. I will post here once the next release comes out.
Thanks!
Was this fixed/closed? Or maybe there was a regression? I just switched over to just_audio after upgrading to flutter 2.0 and I am seeing the same crash. I am using just_audio 0.7.0.
Thanks!
Hi @adamkoch
Thanks for reporting. I had forgotten to close this issue even though it was fixed. If there is a regression, can you confirm that the above reproduction project causes the error with 0.7.0? If not, are you able to provide another reproduction example?
Thanks for the fast response. I found the issue actually, I converted over from the assets_audio_player package and was using this to dispose of the player, which I kept when switching to just_audio:
@override
void dispose() {
if (_audioPlayer != null) {
_audioPlayer.stop();
_audioPlayer.dispose();
}
super.dispose();
}
This shows error:
======== Exception caught by services library ======================================================
The following MissingPluginException was thrown while de-activating platform stream on channel com.ryanheise.just_audio.events.86784fe5-23a9-41fb-9908-9f0309510324:
MissingPluginException(No implementation found for method cancel on channel com.ryanheise.just_audio.events.86784fe5-23a9-41fb-9908-9f0309510324)
When the exception was thrown, this was the stack:
#0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:156:7)
<asynchronous suspension>
#1 EventChannel.receiveBroadcastStream.<anonymous closure> (package:flutter/src/services/platform_channel.dart:557:9)
<asynchronous suspension>
====================================================================================================
If I remove this or only call dispose() then the error doesn't show up. I guess as stop() the call may overlap with the dispose() call.
@adamkoch you have found the correct solution to your issue. The purpose of stop() in this plugin is to shut down the platform side of the plugin in a way that allows it to be resurrected later, but if you don't plan on resurrecting it, you would use dispose() instead. Although intuitively a stop followed by a dispose should also work without error. I suspect the reason you got an error was that you didn't await the first call before starting the second call. What I should probably do is guard against things like this inside the plugin, e.g. by queuing requests when order is important.
Makes sense, yes I didn't await the stop(). All is working for me now so you can close this issue. Although yes, ideally you would guard against things so this couldn't happen (block in dispose() if stop() is still running). Thanks for the fast and detailed responses!
I may leave this issue open still, just because I think I can improve things internally, and this will remind me to come back to this in the future.
Most helpful comment
Great! You might like to pin your app to that git commit for now, as the next release might happen a few days later. I will post here once the next release comes out.