ryanheise / audio_service

Flutter plugin to play audio in the background while the screen is off.
803 stars 480 forks source link

Service doesn't get stopped after setting `idle` state with `androidStopForegroundOnPause` disabled #1083

Open Zensonaton opened 3 months ago

Zensonaton commented 3 months ago

Documented behaviour

AudioServiceConfig.androidStopForegroundOnPause: Whether the Android service should switch to a lower priority state when playback is paused allowing the user to swipe away the notification. Note that while in this lower priority state, the operating system will also be able to kill your service at any time to reclaim resources.

BaseAudioHandler.stop: Stop playback and release resources. The default implementation (which may be overridden) updates playbackState by setting the processing state to AudioProcessingState.idle which disables the system notification.

Actual behaviour

Changing androidStopForegroundOnPause from true (default) to false no longer allows stopping foreground service (and notification) by setting AudioProcessingState.idle:

playbackState.add(
  PlaybackState(
    playing: false,
    processingState: AudioProcessingState.idle,
  )
);

Minimal reproduction project

Official example: main.dart

Reproduction steps

Proper behavior:

  1. Press "play".
  2. Press "stop".
  3. Notification gets destroyed, and Android task manager no longer shows app in its "task manager".

Wrong behavior.

  1. Change androidStopForegroundOnPause to false.
  2. Press "play".
  3. Press "stop".
  4. Notification does not get dismissed, and Android "task manager" shows that app is still running.

Output of flutter doctor

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.22.2, on Microsoft Windows [Version 10.0.22631.3958], locale ru-RU)
[✓] Windows Version (Installed version of Windows is version 10 or higher)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✗] Chrome - develop for the web (Cannot find Chrome executable at .\Google\Chrome\Application\chrome.exe)
    ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.
[✓] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.8.3)
[✓] Android Studio (version 2022.3)
[✓] VS Code (version 1.91.1)
[✓] Connected device (3 available)
[✓] Network resources

Devices exhibiting the bug

Google Pixel 8, Android 14 (AP2A.240705.005)

Context

I'm forced to use androidStopForegroundOnPause = false because my app can pause playback due to interruptions. After setting androidStopForegroundOnPause = true, my app can pause playback, but it gets ForegroundServiceStartNotAllowedException exception.

ryanheise commented 3 months ago

Changing androidStopForegroundOnPause from true (default) to false no longer allows stopping foreground service (and notification) by setting AudioProcessingState.idle:

That's the correct behaviour. If you want to instruct Android to call stopForeground on pause, you have to set this to true (the default).

Zensonaton commented 3 months ago

Yeah, that makes sense, but the problem I'm facing - no way to get rid of that notification by setting the state to idle. There is no method like "destroyNotification", and this is a problem for me.

Zensonaton commented 3 months ago

So, I want to clarify a bit: I'm not asking "why doesn't service stop when player is paused", but rather "why doesn't service stop when player is in idle state".

After digging a bit, I found this issue: #996. This comment explains the exact same issue I have. I'm strongly against ignoring battery optimizations, so I can't use this here.

jagged91 commented 2 months ago

I'm facing a similar issue @Zensonaton. I feel like as things currently stand, there are two options:

  1. Keep androidStopForegroundOnPause = true and risk the service being killed in the background (this seems to happen when receiving notifications or calls during playback - possibly the switch to the lower priority state makes it a good candidate to be killed by the OS)
  2. Set androidStopForegroundOnPause = false which seems to keep the service alive correctly but has the downside of the audio notification lingering after playback has finished. It does (obviously) get dismissed when you swipe the app away, but not ideal. I know exactly where in the app logic I'd want to dismiss the notification (i.e. when navigating away from my in-app audio player UI).

I also agree that the battery optimization option isn't great, but I also understand that we're kinda fighting against flaws in the OS at this point.

rootd commented 2 months ago

Is it possible to integrate a "destroyNotification" function to manually dismiss the notification?

nateshmbhat commented 1 month ago

I'm using the default AudioServiceConfig but still the notification behavior is inconsistent after stopping the audio and calling the stop method of BaseAudioHandler. let's say 5 out of 10 times the notification gets dismissed while the rest of times it stays there.

AudioServiceConfig(
        androidNotificationChannelId: 'test Notifications',
        androidNotificationChannelName: 'test Notifications',
        androidShowNotificationBadge: false)