Closed serhii-k closed 1 year ago
I have squeezed the code to the bare minimum, where this bug is still reproducible.
Please see the following videos. The behaviour is the same as with the original main.dart example (or any other).
import 'dart:async';
import 'package:audio_service/audio_service.dart';
import 'package:flutter/material.dart';
late AudioHandler _audioHandler;
Future<void> main() async {
_audioHandler = await AudioService.init(
builder: () => AudioPlayerHandler(),
config: const AudioServiceConfig(
androidNotificationChannelId: 'com.ryanheise.myapp.channel.audio',
androidNotificationChannelName: 'Audio playback',
androidNotificationOngoing: true,
),
);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Audio Service Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
_audioHandler.play();
},
child: const Icon(Icons.play_arrow),
),
),
);
}
}
class AudioPlayerHandler extends BaseAudioHandler with SeekHandler {
static const _item = MediaItem(
id: 'mediaItem',
title: 'Test',
);
AudioPlayerHandler() {
mediaItem.add(_item);
}
@override
Future<void> play() async {
playbackState.add(playbackState.value.copyWith(
controls: [MediaControl.pause, MediaControl.stop],
processingState: AudioProcessingState.ready,
playing: true,
));
}
@override
Future<void> pause() async {
playbackState.add(playbackState.value.copyWith(
controls: [MediaControl.play, MediaControl.stop],
processingState: AudioProcessingState.ready,
playing: false,
));
}
@override
Future<void> stop() async {
playbackState.add(playbackState.value.copyWith(
controls: [],
processingState: AudioProcessingState.idle,
playing: false,
));
}
}
On a real device I don't have to press that fast. It happens easily after 3-4 consecutive presses with 1-2 seconds in between.
P.S. What a timing :)
I have just tried the main.dart example on my phone. The notification controls also got stuck in the Pause
state.
An explanation:
Pause
. And it breaks right away! It hasn't been changed to Play
.Pause
button still doesn't work properly. I hit several times the Pause
and nothing happens.My friend with Samsung Galaxy S22 Ultra (Android 13) also reports this issue on his device.
One more observation. If the second video is played at 0.25 speed, for a frame we can see that the controls actually change to Play, Stop
, but then for some reason they switch back to the Pause, Stop
state. In two cases when this control button breaks.
I'm sorry before I get through to the rest of your bug report:
Minimal reproduction project
Official example: In the next message, I'm going to put a very simple example that can be added to the official examples.
If you're going to submit a minimal reproduction project, please do so according to the instructions by forking this repo and sharing the link. I require that for my setup.
Hello @ryanheise I have edited my two initial comments for this issue. This issue is reproducible with the main.dart example. However, I'm also adding the minimum code that still reproduces this bug.
Solved by setting the compileSdkVersion and targetSdkVersion to 33.
I've decided to reopen this issue. I think the solution should be mentioned in the README. Because if we target SDK 31 the behaviour of notification controls on Android 33 is literally very disappointing.
Closing this issue because in Flutter 3.3.7 compileSdkVersion and targetSdkVersion are set to 33 by default.
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs, or use StackOverflow if you need help with audio_service.
Documented behaviour
Your audio handler must broadcast state changes so that the system notification and smart watches (etc) know what state to display. Your app's Flutter UI may also listen to these state changes so that it knows what state to display. Thus, the audio handler provides a single source of truth for your audio state to all clients.
Actual behaviour
Let's say we have MediaControl.pause, MediaControl.stop inside the notification. When a user presses the
Pause
icon theAudioHandler.pause()
is called. Let's say here we're addingcontrols: [MediaControl.play, MediaControl.stop]
to theplaybackStream
. Unfortunately, sometimes this doesn't change the controls inside the Android notification.It can be a bug inside the plugin implementation, or it can be a bug of Android...
Minimal reproduction project
Official example: main.dart
Reproduction steps
Please, see the next message for the code.
Play
orPause
state. For example: a) the audio service is playing b) we press "Pause" inside the notification c) the audio service pauses, but the "Pause" control inside the notification doesn't change to "Play" d) thus we can't resume the playback from the notificationHowever: We can resume the playback from the app UI, or by pressing a media button of headphones.
Output of flutter doctor
Devices exhibiting the bug
This issue is easily reproducible on my Samsung Galaxy A53 5G (Android 13). It takes 3-4 pause-play changes to appear. Or sometimes it's even enough to press the "Pause" once. It looks like the icon is changing, but then returns back to "Pause".
This issue is also quite easily reproducible on the API 33 emulator. Display the notification, and press quickly over the "Play/Pause" control. After a few seconds the control gets stuck in "Pause".
As well I could reproduce in on the API 29 emulator.