Flutter onResume is detected too late for music pausing

826 views Asked by At

I have the following code, Im using just_audio as my audio player. My problem is I want to pause, unpause the audio when the user leaves the app. I successfully accomplished this with the following:

@override
  void initState() {
    WidgetsBinding.instance.addObserver(this);
    super.initState();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    audioPlayer.dispose();
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      if (isPaused) {
        isPaused = false;
        audioPlayer.play();
      }
    } else if (state == AppLifecycleState.paused) {
      if (audioPlayer.playing) {
        isPaused = true;
        audioPlayer.pause();
      }
    }
  }

My problem here is that when I hit the home button the app pauses the audio after finishing the app closing animation (ie the animation you get when you press home button inside an app, your app scales down to center from all sides and it disappears completely).

This feels so clunky as the audio stops when the animation is finished. Sometimes it stops after animation is finished + up to 1 more seconds passed. I tested it on release build and its the same. This is horrible! The problem is that Flutter detects AppLifecycleState.paused state too late, not as fast as native (no where close to native actually). Native Android detects it nearly the moment home key is hit. Is there another ways to pause and unpause the audio player in Flutter when user hits the home button? This is nowhere acceptable for a production ready app.

My flutter version: 1.22.0 stable

1

There are 1 answers

3
Ryan Heise On BEST ANSWER

Unfortunately, there is currently no way to react immediately to Android's onPause lifecycle event. This is due to the asynchronous nature of communication between Dart code running in the Flutter engine and native platform code provided by plugins. Whenever code in the Dart layer sends a message to the platform layer over a "platform channel", it gets added to a queue and scheduled. Response messages from the platform side to the Dart side are similarly added to a queue and scheduled. At times when there's a lot going on (e.g. when you press the home button), things will be particularly busy and you won't get an instant response. However, a recent document from the Flutter team outlines a plan to add synchronous communication between the Flutter engine and the platform which should solve that issue. If you want this feature, you can add your feedback directly to that document for the Flutter team to see.

In the meantime, the only way to react immediately to Android's onPause lifecycle is in native platform code. For example, a feature could be directly embedded in the plugin you're using to automatically pause the player in response to onPause, and it would be able to react instantly because the lifecycle event would be received and processed on the platform side without having to travel through the asynchronous platform channel mentioned above.