Flutter audio_service media resume - flutter

I have custom queuing logic using MediaItem which works properly when the UI is active. I am stopping the audio playback using onTaskRemoved method.
#override
Future<void> onTaskRemoved() async {
//if (!AudioServiceBackground.state.playing) {
logger.v("Task Removed");
await stop();
//}
}
#override
Future<void> stop() async {
await _player.stop();
await playbackState.firstWhere(
(state) => state.processingState == AudioProcessingState.idle);
}
However after swiping the task, notification is still visible and when I click the notification to resume nothing happens and app is stuck in splash screen.

Related

Flutter audio_service does not start when the app is not in the foreground on iOS

I've been building a Flutter app that needs to trigger an alarm while in the background.
I am using audio_service in combination with just_audio (latest versions of both) but am only hearing the alarm if it is triggered when the app is in the foreground.
My handler always recieves the callback to start playing, and no exceptions are thrown by the audio player.
I've tried using the IsolatedAudioHandler class as explained in the FAQ and it behaves exactly the same way: sound is only heard when in the foreground.
The alarm is triggered by GPS location updates when the user leaves a guard-zone.
Any advice would be greatly appreciated.
This is my handler code:
class AudioPlayerHandler extends BaseAudioHandler {
final _player = AudioPlayer();
AudioPlayerHandler() {
_player.setUrl("https://s3.amazonaws.com/scifri-episodes/scifri20181123-episode.mp3");
}
#override
Future<void> play() {
try {
print("****** play *******");
return _player.play();
} catch (e) {
print(e);
return Future.value(null);
}
}
#override
Future<void> pause() {
return _player.pause();
}
}```

flutter firebase onclick redirection when app is open

in my app firebase push notification is implemented.
on click event works when app is terminated.
but how to achieve notification on click of redirection when app is open.
class _Application extends State<Application> {
// It is assumed that all messages contain a data field with the key 'type'
Future<void> setupInteractedMessage() async {
// Get any messages which caused the application to open from
// a terminated state.
RemoteMessage? initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
// If the message also contains a data property with a "type" of "chat",
// navigate to a chat screen
if (initialMessage != null) {
_handleMessage(initialMessage);
}
// Also handle any interaction when the app is in the background via a
// Stream listener
FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
}
void _handleMessage(RemoteMessage message) {
if (message.data['type'] == 'chat') {
Navigator.pushNamed(context, '/chat',
arguments: ChatArguments(message),
);
}
}
#override
void initState() {
super.initState();
// Run code required to handle interacted messages in an async function
// as initState() must not be async
setupInteractedMessage();
}

The method 'onSelectNotifications' isn't defined using flutter local notification plugin

in flutter_local_notification 12.0.2
The onSelectNotification parameter is not anymore.
So what is the alternative of this. So that we can handle callback when we click on notification.
you can stream the notification
import 'package:rxdart/rxdart.dart';
...
// use this
class MyNotifManager {
static final onNotifications = BehaviorSubject<String?>();
...
// then add the payload to your local notification
// exampel for the foreground notif
onDidReceiveNotificationResponse: (payload) async {
onNotifications.add(payload.payload); // add payload to the stream
},
then to handle the callback:
Future<void> listenNotification() async =>
MyNotifManager.onNotifications.stream.listen(onClickNotification);
and for your action after click
void onClickNotification(String? payload) {
Navigator.push();
}
call the stream on your initState
#override
void initState() {
super.initState();
MyNotifManager.init();
listenNotification();
}
with this method, you will able to handle calback when click on notification.
It has onDidReceiveNotificationResponse callback when plugin initialize.
_plugin.initialize(
initializationSettings,
onDidReceiveNotificationResponse: (details) {
// Click Notification Event Here
},
);
If you click notification when app is terminated,
_plugin.getNotificationAppLaunchDetails().then((value) {
// Click Notification Event Here
});

Can I hide Android Notification bar if I used Audio Service in Flutter?

I used the latest Dart package of audio_service (0.18.4). My use case is different. I have main menu on the first screen and another sub-menu to play music in the other screen. I just want to hide the Notification bar after user click on close button to music player. Close here means that user stops playing music and goes directly to main menu.
I started and used get_it package as singleton to run AudioPlayerHandler class in all screens.
import 'package:audio_player_final/audio/audio_handler.dart';
import 'package:get_it/get_it.dart';
GetIt getThem = GetIt.instance;
Future<void> setup() async {
getThem.registerSingleton<AudioPlayerHandler>(await initAudio(), dispose: (audio) => audio.customAction("dispose"));
}
This is the code if user click close button in Music Player:
Future<void> customAction(String name, [Map<String, dynamic>? extras]) async {
if (name == "close") {
await stop();
await setShuffleMode(AudioServiceShuffleMode.none);
await setRepeatMode(AudioServiceRepeatMode.none);
playbackState.add(playbackState.value.copyWith(
repeatMode: AudioServiceRepeatMode.none,
shuffleMode: AudioServiceShuffleMode.none,
));
if (_playlist.children.isNotEmpty) {
for (int i = _playlist.children.length - 1; i >= 0; i--) {
await removeQueueItemAt(i);
}
dev.log("Cleaning previous playlist");
}
}
}
What I want is to hide Notification bar so user won't press it since there are no more queue of music inside it. I had removed them all in above function if user click close button. If user press the Playback button on Notification bar, the error will get displayed that the queue is empty. I don't want that to happen.
If I use dispose function, the Notification will be disappeared, but audio_service is not meant to restart the init function. So it will be impossible to run the music player again if user want to play music again as it has been disposed.
Future<void> customAction(String name, [Map<String, dynamic>? extras]) async {
if (name == "dispose") {
await stop();
await _player.dispose();
}
}
Is there anyway to hide the Notification bar of Music Player from audio_service?
Any tips and trick will be welcomed.
Thanks

Flutter Riverpod: Refresh Page Offscreen using State Notifier

I'm using StateNotifier and Riverpod.
I have a notification page, which contains a list of notification. When a notification arrives, I trigger a refresh for notification. However, when I navigate to notification page, it still using the old (cached?) list.
How do I refresh a page offscreen?
Foreground Message
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
_localNotification.showLocalNotification(message);
ProviderContainer().read(notificationProvider).getNotification();
});
Background Message
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
final LocalNotification localNotification = LocalNotification();
await localNotification.init();
localNotification.showLocalNotification(message);
ProviderContainer().read(notificationProvider).getNotification();
}
NotificationProvider
Future<void> getNotification() async {
try {
state = const NotificationLoadingState();
_notificationList = await _notificationRepository.getNotification();
state = NotificationLoadedState(_notificationList); // ==> I get a new list here
} catch (e, s) {
state = const NotificationErrorState('error fetching notification');
}
}
UI
final state = watch(notificationProvider.state);
if (state is NotificationLoadingState) {
return _buildLoading();
} else if (state is NotificationLoadedState) {
return _buildLoaded(state.notificationList); // ==> I still get the old list here
} else if (state is NotificationErrorState) {
return _buildError(state.message);
}
Edit:
I managed to solve the foreground message handler by using navigatorKey.currentContext.
However, I still haven't solved background message handler.
I've tried changing my main.dart to use UncontrolledProviderScope with a global ProviderContainer, which then was called from background message handler. It's still not refreshing.
With this line you are creating a new instance for your providers :
ProviderContainer().read(notificationProvider).getNotification();
you need to use a context to get the existing instance of ProviderContainer:
context.read(notificationProvider).getNotification();
or if you are not inside ui make dependencies between your providers