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

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
});

Related

Cannot navigate to a specific page when tapping a notification (when app is in background)

I am developing an app in flutter. I used awesome_notification package to show notifications. In awesome_notification, onActionReceivedMethod works fine when an app is in the foreground but does not work when an app is in the background. How to handle this?
#pragma("vm:entry-point")
static Future <void> onActionReceivedMethod(ReceivedAction receivedAction) async {
// code to navigate some page
} // not calling when user tap notification
Also, onMessageOpenedApp function is not triggered when tapping the notification. How to solve this? Kindly help me to resolve this.
FirebaseMessaging.onMessageOpenedApp.listen((message) async {
// code to navigate some page
}); // not calling when user tap notification
I encountered the same problem with local_notification, to pass an information from the vm entry point to the app.
I solved it by doing an isolate sent / receive like this:
//needed for isolate
import 'dart:isolate';
import 'dart:ui';
//outside main
const String channel = 'channel_key';
#pragma('vm:entry-point')
void onReceiveBackgroundResponse(NotificationResponse notificationResponse) async {
final sendPort = IsolateNameServer.lookupPortByName(channel);
sendPort?.send(notificationResponse.actionId);
}
...
//inside main
void listenNotification() {
final receivePort = ReceivePort();
IsolateNameServer.registerPortWithName(receivePort.sendPort, channel);
receivePort.asBroadcastStream().listen((event) {
print(event);
});
}

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();
}

Cannot find AwesomeNotifications().actionStream

I would like to add a button to my flutter notification. The button is shown but I can't catch the action.
AwesomeNotifications().createNotification(
content: NotificationContent(
id: 888,
channelKey: 'NetVideo',
title: 'NetVideo',
body: 'Server in ascolto'),
actionButtons: <NotificationActionButton>[
NotificationActionButton(key: 'yes', label: 'Yes'),
],
);
AwesomeNotifications().actionStream still exists?
According to documentation:
All streams (createdStream, displayedStream, actionStream and dismissedStream) was replaced by global static methods. You must replace your old stream methods by static and global methods, in other words, they must be static Future and use async/await and you MUST use #pragma("vm:entry-point") to preserve dart addressing.
In other words you should create a notification listener
class NotificationController {
/// Use this method to detect when a new notification or a schedule is created
#pragma("vm:entry-point")
static Future <void> onNotificationCreatedMethod(ReceivedNotification receivedNotification) async {
// Your code goes here
}
/// Use this method to detect every time that a new notification is displayed
#pragma("vm:entry-point")
static Future <void> onNotificationDisplayedMethod(ReceivedNotification receivedNotification) async {
// Your code goes here
}
/// Use this method to detect if the user dismissed a notification
#pragma("vm:entry-point")
static Future <void> onDismissActionReceivedMethod(ReceivedAction receivedAction) async {
// Your code goes here
}
/// Use this method to detect when the user taps on a notification or action button
#pragma("vm:entry-point")
static Future <void> onActionReceivedMethod(ReceivedAction receivedAction) async {
// Your code goes here
// Navigate into pages, avoiding to open the notification details page over another details page already opened
MyApp.navigatorKey.currentState?.pushNamedAndRemoveUntil('/notification-page',
(route) => (route.settings.name != '/notification-page') || route.isFirst,
arguments: receivedAction);
}
}
And register it inside the library
AwesomeNotifications().setListeners(
onActionReceivedMethod: (ReceivedAction receivedAction){
NotificationController.onActionReceivedMethod(context, receivedAction);
},
onNotificationCreatedMethod: (ReceivedNotification receivedNotification){
NotificationController.onNotificationCreatedMethod(context, receivedNotification);
},
onNotificationDisplayedMethod: (ReceivedNotification receivedNotification){
NotificationController.onNotificationDisplayedMethod(context, receivedNotification);
},
onDismissActionReceivedMethod: (ReceivedAction receivedAction){
NotificationController.onDismissActionReceivedMethod(context, receivedAction);
},
);

How to implement a communication chain in Flutter app with non-Flutter component

I'm trying to implement a communication chain in my app.
The app has at least to layer:
core, which is responsible for network communications. It's implemented as a Dart library
UI, which is responsible for communication with user. It's implemented as a Flutter app.
The core has a piece that handles invitations. Communication part is asynchronous and works in a way:
receive a request
handle request
send a response
void _handleMemberInviteRequest(AtNotification notification) async {
final sender = AtSignMember(atSign: notification.from);
if (await onMemberInvitation(sender)) {
send(notification.from, CommunicationVerbs.memberInviteRespond.name,
"accept");
} else {
send(notification.from, CommunicationVerbs.memberInviteRespond.name,
'reject');
}
}
onMemberInvitation is an event handler that in my understanding should be implemented in Flutter app. My problem is that I need user to accept an invitation. The whole chain of actions I see:
Request is received (core) -> onMemberInvitation is invoked (core) -> Confirmation dialog pops up (Flutter app) -> Response is returned by onMemberInvitation (core) -> Response is sent (core).
What I can't figure out is how to make Flutter to pop up the confirmation and answer with the result. I use BLoC patter for state management. So I though of having a separate Cubit that would emit a state that would be listened by a BlocListener on a top of application and pop up the dialog.
class Confirmation extends Cubit {
void askForConfirmation(sender) {
emit(ConfirmationState("InvitationConfirmation"));
}
void gotConfirmation(bool confirmation) {
emit(ConfirmationResponseState(confirmation));
}
}
and in app initialization implement an onMemberInvitation handler:
Future<bool> onMemberInvitation(sender) async {
askForConfirmation(sender);
await for (/* here somehow wait for `ConfirmationResponseState`*/) {
return confirmation;
}
}
But then I can't realise how do I wait for the response in onMemberInvitation handler.
Any ideas? Can BLoC be utilised here as well? Or because it's outside of Flutter app some custom streams have to be implemented? Or there is another way?
What you need is an async onMemberInvitation function that you can finish from outside the scope of the function itself.
You can achieve this using a Completer. This enables you to emit the result of the confirmation from anywhere while pausing the execution of onMemberInvitation until the result arrived. Check the sample below.
import 'dart:async';
Completer completer = new Completer<bool>();
void main() async {
String sender = 'test';
completer = new Completer();
if (await onMemberInvitation(sender)) {
print("accept");
} else {
print('reject');
}
}
Future<bool> onMemberInvitation(String sender) async {
askForConfirmation(sender);
print('UI event emitted');
return await completer.future;
}
void askForConfirmation(String sender) async {
// TODO: emit the state to the UI here
await Future.delayed(Duration(seconds: 3));
//TODO: call this when you get the confirmation event
gotConfirmation(true);
}
void gotConfirmation(bool confirmation) {
completer.complete(confirmation);
}

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