I'm stuck. My notification in the background show twice. But in the foreground only one notification. This is my code
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// If you're going to use other Firebase services in the background, such as Firestore,
// make sure you call `initializeApp` before using other Firebase services.
await Firebase.initializeApp();
if(
!AwesomeStringUtils.isNullOrEmpty(message.notification?.title, considerWhiteSpaceAsEmpty: true) ||
!AwesomeStringUtils.isNullOrEmpty(message.notification?.body, considerWhiteSpaceAsEmpty: true)
){
// print('message also contained a notification: ${message.notification.body}');
String imageUrl;
imageUrl ??= message.notification.android?.imageUrl;
imageUrl ??= message.notification.apple?.imageUrl;
print(imageUrl);
if(imageUrl == null){
var id = Random().nextInt(2147483647);
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: id,
title: message.notification.title,
body: message.notification.body,
color: Colors.orange,
customSound: 'resource://raw/alert',
notificationLayout: NotificationLayout.BigText,
channelKey: 'basic_channel_background',
payload: {'data':message.data['payload']}
),
actionButtons: [
NotificationActionButton(
label: 'Lihat Selengkapnya',
enabled: true,
buttonType: ActionButtonType.Default,
key: 'background',
)
]
);
}else{
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: Random().nextInt(2147483647),
title: message.notification.title,
body: message.notification.body,
bigPicture: imageUrl,
color: Colors.orange,
customSound: 'resource://raw/alert',
notificationLayout: NotificationLayout.BigPicture,
channelKey: 'basic_channel_background',
payload: {'data':message.data['payload']}
),
actionButtons: [
NotificationActionButton(
label: 'Lihat Selengkapnya',
enabled: true,
buttonType: ActionButtonType.Default,
key: 'background',
)
]
);
}
}
}
// End Background Message
and this is my foreground code
// Foreground Apps
Future<void> main() async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
if (!kIsWeb) {
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
await AwesomeNotifications().initialize(
'resource://mipmap/launcher_icon',
[
NotificationChannel(
channelGroupKey: 'basic_tests',
channelKey: 'basic_channel',
channelName: 'My Cahaya Notification',
channelDescription: 'Notification channel for basic tests',
icon: 'resource://mipmap/launcher_icon',
importance: NotificationImportance.High,
playSound: true,
soundSource: 'resource://raw/alert'
),
NotificationChannel(
channelGroupKey: 'basic_background',
channelKey: 'basic_channel_background',
channelName: 'My Cahaya Notification Background',
channelDescription: 'Notification channel for basic tests',
icon: 'resource://mipmap/launcher_icon',
importance: NotificationImportance.High,
playSound: true,
soundSource: 'resource://raw/alert'
),
], debug: true);
AwesomeNotifications().actionStream.listen((event) async{
print('event received!');
var data = event.toMap();
if(data['buttonKeyPressed'] == "background"){
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString("Navigate", data['payload']['data']);
}else{
_navigateToItemForeground(data['payload']['data']);
}
// do something based on event...
// AwesomeNotifications().actionSink.close();
});
}
FirebaseMessaging.onMessage.listen((RemoteMessage message) async{
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
if (notification != null && android != null && !kIsWeb) {
if(!AwesomeStringUtils.isNullOrEmpty(message.notification?.title, considerWhiteSpaceAsEmpty: true) ||
!AwesomeStringUtils.isNullOrEmpty(message.notification?.body, considerWhiteSpaceAsEmpty: true)){
print("something");
String imageUrl;
imageUrl ??= notification.android?.imageUrl;
imageUrl ??= notification.apple?.imageUrl;
if(imageUrl == null){
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: Random().nextInt(2147483647),
title: notification.title,
body: notification.body,
color: Colors.orange,
customSound: 'resource://raw/alert',
notificationLayout: NotificationLayout.BigText,
channelKey: 'basic_channel',
payload: {'data':message.data['payload']}
),
actionButtons: [
NotificationActionButton(
label: 'Lihat Selengkapnya',
enabled: true,
buttonType: ActionButtonType.Default,
key: 'test',
)
]
);
}else{
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: Random().nextInt(2147483647),
title: notification.title,
body: notification.body,
bigPicture: imageUrl,
color: Colors.orange,
customSound: 'resource://raw/alert',
notificationLayout: NotificationLayout.BigPicture,
channelKey: 'basic_channel',
payload: {'data':message.data['payload']}
),
actionButtons: [
NotificationActionButton(
label: 'Lihat Selengkapnya',
enabled: true,
buttonType: ActionButtonType.Default,
key: 'test',
)
]
);
}
}
}
});
runApp(MyApp());
}
// End Foreground Apps
and this is my screenshot
screenshot
I've tried changing the awesome notification but the result is the same. Could you help me to solve that? I hope you can help me. Thank you very much
FCM payload
{
"to":"_some_fcm_token_",
//remove this
"notification": {
"title": "this is title",
"body": "this is subtitle"
},
"type": "post_like",
"data": {
"model":{"id":"dsaflkdskfklgdkgjdksakdk"},
"body": "this is subtitle",
"title": "this is title",
"click_action": "FLUTTER_NOTIFICATION_CLICK"
},
"priority": "normal"
}
The first one is manually created (locally), and the other one is automatic by Firebase.
When sending a message to your device, make sure it is a notification rather than data. The documentation mentions that if you send data it will likely be ignored as a push notification. Only use it to send packets of data to the app instead.
If your Notification is sent while the App is in background, Firebase
automatically sends a Push-Notification, so you don't need to call the show Notification manually in the App.
I solved the problem like this:
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
if (message.notification != null) {
//No need for showing Notification manually.
//For BackgroundMessages: Firebase automatically sends a Notification.
//If you call the flutterLocalNotificationsPlugin.show()-Methode for
//example the Notification will be displayed twice.
}
return;
}
Solved)
**{
"to":"_some_fcm_token_",
//remove this
//"notification": {
// "title": "this is title",
// "body": "this is subtitle"
},
"type": "post_like",
"data": {
"model":{"id":"dsaflkdskfklgdkgjdksakdk"},
"body": "this is subtitle",
"title": "this is title",
"click_action": "FLUTTER_NOTIFICATION_CLICK"
},
"priority": "normal"
}**
payload: Platform.isAndroid?
json.encode(message.data):json.encode(message.notification)
set payload data like this
Related
I am building a Flutter app with Firebase Messaging. I am using AwesomeNotifications plugin to display the notifications.
My notifications contain the notification property, because sending data only message does not trigger the iOS if the device is rebooted.
The issue with the notification property is that it triggers flutter SDK and auto display the default notification alone with the custom notification I configured with AwesomeNotifications .
Below is my JSON code.
"message": {
"notification": {
"title": senderName,
"body": "Image Sent"
},
"token": recieverFcm,
"data": {
"name": senderName,
"body": "Image Sent",
"chatRoomId": chatRoomId,
"sender_profile_pic": senderProfilePic,
"senderUid": senderUid,
"data_type": messageType,
"image_link": message,
"click_action": "OPEN_CHAT_ROOM"
},
"android": {
"priority": "high"
},
"apns": {
"payload": {
"aps": {
"category": "OPEN_CHAT_ROOM",
"sound": "enable",
"content-available": 1,
}
}
}
}
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
NotificationController _notificationController = NotificationController();
//Initialize firebase
await Firebase.initializeApp();
await _notificationController.startNotificationService();
//Listen for the Token change
FirebaseMessaging.instance.onTokenRefresh.listen((String token) {
print("New token: $token");
});
//Apply MultiProvider
runApp(MultiProvider(
providers: [
//provider lists
],
child: MyApp(),
));
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
NotificationController _notificationController = NotificationController();
_notificationController.startAwesomeNotificationlistener();
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
textTheme: GoogleFonts.poppinsTextTheme(),
primaryColor: primaryColor,
backgroundColor: Colors.white,
scaffoldBackgroundColor: Colors.white,
accentColor: darkColor,
appBarTheme: AppBarTheme(
backgroundColor: Colors.white,
elevation: 0,
iconTheme: IconThemeData(color: Colors.black),
titleTextStyle: GoogleFonts.poppins(
fontSize: 16, color: darkColor, fontWeight: FontWeight.w500)),
textSelectionTheme: TextSelectionThemeData(cursorColor: darkColor),
outlinedButtonTheme: OutlinedButtonThemeData(style: outlineButtonStyle),
elevatedButtonTheme:
ElevatedButtonThemeData(style: elevatedButtonStyle),
),
routes: {
//Routes go here
},
home: LoadingScreen3(),
);
}
}
notification_controller.dart
class NotificationController {
///Start notification service
Future<void> startNotificationService() async {
NotificationService _notificationService = NotificationService();
await _notificationService.initializFirebaseeNotifications();
}
///Display a new notification in foreground
Future<void> displayNotification({
required String groupKey,
required String channelKey,
required String title,
required String body,
required String summary,
required NotificationLayout layout,
required bool displayOnBackground,
required bool displayOnForeground,
required String messageType,
String? clickAction,
String? chatRoomId,
String? chatMessageFrom,
}) async {
NotificationService _notificationService = NotificationService();
await _notificationService.createAwesomeNotification(
groupKey: groupKey,
channelKey: channelKey,
title: title,
body: body,
summary: summary,
layout: layout,
displayOnBackground: displayOnBackground,
displayOnForeground: displayOnForeground,
messageType: messageType,
clickAction: clickAction,
chatRoomId: chatRoomId,
chatMessageFrom: chatMessageFrom);
}
//Start awesome notification listener
void startAwesomeNotificationlistener() {
NotificationService _notificationService = NotificationService();
_notificationService.startAwesomeNotificationListener();
}
}
notification_service.dart
class NotificationService with ChangeNotifier {
FirebaseMessaging _messaging = FirebaseMessaging.instance;
///Start initializing the notification service
Future<void> initializFirebaseeNotifications() async {
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
//Request permission for firebase messaging
NotificationSettings settings = await _messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
print('User granted permission');
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
developer.log("REMOTE MESSAGE LISTENER");
print("REMOTE MESSAGE LISTENER");
if (message.data["data_type"] == "TEXT") {
await createAwesomeNotification(
groupKey: message.data["senderUid"],
channelKey: 'basic_channel',
title: message.data["name"],
body: message.data["body"],
summary: message.data["body"],
layout: NotificationLayout.Messaging,
displayOnBackground: true,
displayOnForeground: true,
messageType: message.data["data_type"],
clickAction: message.data["click_action"],
chatRoomId: message.data["chatRoomId"],
chatMessageFrom: message.data["senderUid"]);
} else if (message.data["data_type"] == "IMAGE") {
await createAwesomeNotification(
groupKey: message.data["senderUid"],
channelKey: 'basic_channel',
title: message.data["name"],
body: Emojis.art_framed_picture + " " + message.data["body"],
summary: message.data["body"],
layout: NotificationLayout.Messaging,
displayOnBackground: true,
displayOnForeground: true,
messageType: message.data["data_type"],
clickAction: message.data["click_action"],
chatRoomId: message.data["chatRoomId"],
chatMessageFrom: message.data["senderUid"],
);
}
});
} else {
print('User declined or has not accepted permission');
}
/// Update the iOS foreground notification presentation options to allow
/// heads up notifications.
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
FirebaseMessaging.instance
.getInitialMessage()
.then((RemoteMessage? message) {
developer.log("REMOTE MESSAGE");
if (message != null) {
developer.log(message.data.toString());
}
});
// For handling notification when the app is in background
// but not terminated
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print("onMessageOpenedApp executed");
});
await initializeAwesomeNotifications();
}
//Initialize the notification display plugin
Future<void> initializeAwesomeNotifications() async {
AwesomeNotifications().initialize('resource://drawable/logo', [
NotificationChannel(
channelGroupKey: 'basic_tests',
channelKey: 'basic_channel',
channelName: 'Basic notifications',
channelDescription: 'Notification channel for basic tests',
defaultColor: Color(0xFF9D50DD),
ledColor: Colors.white,
importance: NotificationImportance.High),
]);
}
//Create and display notification
Future createAwesomeNotification({
required String groupKey,
required String channelKey,
required String title,
required String body,
required String summary,
required NotificationLayout layout,
required bool displayOnBackground,
required bool displayOnForeground,
required String messageType,
String? clickAction,
String? chatRoomId,
String? chatMessageFrom,
}) async {
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: UniqueKey().hashCode,
groupKey: groupKey,
channelKey: channelKey,
title: title,
body: body,
summary: summary,
notificationLayout: layout,
displayOnBackground: displayOnBackground,
displayOnForeground: displayOnForeground,
payload: {
"messageType": messageType,
"clickAction": clickAction ?? "",
"chatRoomId": chatRoomId ?? "",
"chatMessageFrom": chatMessageFrom ?? ""
}),
);
}
//Start Awesome notification listener
void startAwesomeNotificationListener() {
AwesomeNotifications()
.actionStream
.listen((ReceivedNotification receivedNotification) {
developer.log("Notification clicked");
developer.log(receivedNotification.body ?? "no data");
});
}
}
// Declared as global, outside of any class
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// If you're going to use other Firebase services in the background, such as Firestore,
// make sure you call `initializeApp` before using other Firebase services.
await Firebase.initializeApp();
NotificationController _notificationController = NotificationController();
developer.log("background listener called");
print("Handling a background message: ${message.data}");
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
// Use this method to automatically convert the push data, in case you gonna use our data standard
//AwesomeNotifications().createNotificationFromJsonData(message.data);
if (message.data['data_type'].toString().toUpperCase() == "TEXT") {
print("Handling a background message: ${message.data['data_type']}");
await _notificationController.displayNotification(
groupKey: message.data["senderUid"],
channelKey: 'basic_channel',
title: message.data["name"],
body: message.data["body"],
summary: message.data["body"], // Anything you want here
layout: NotificationLayout.Messaging,
displayOnForeground: true,
displayOnBackground: true,
messageType: message.data["data_type"],
clickAction: message.data["click_action"],
chatRoomId: message.data["chatRoomId"],
chatMessageFrom: message.data["senderUid"]);
} else if (message.data['data_type'].toString().toUpperCase() == "IMAGE") {
Future.delayed(Duration(seconds: 2));
await _notificationController.displayNotification(
groupKey: message.data["senderUid"],
channelKey: 'basic_channel',
title: message.data["name"],
body: Emojis.art_framed_picture + " " + message.data["body"],
summary: message.data["body"], // Anything you want here
layout: NotificationLayout.Messaging,
displayOnBackground: true,
displayOnForeground: true,
messageType: message.data["data_type"],
clickAction: message.data["click_action"],
chatRoomId: message.data["chatRoomId"],
chatMessageFrom: message.data["senderUid"]);
}
}
How can I fix this issue and stop showing the custom created AwesomeNotifications only?
I'm using Firebase notifications, with flutter. I want the notification to be a heads-up notification. After much research, on Android this is possible when the app is in the background, only by using, "data" when sending the notification, not "notification". So I send it like this:
"to": "/topics/all",
"data": {
"title": "Alert",
"body": "App maintanance is underway.",
}
and it works great.
However, I am also sending messages to ios devices. Now with iOS, the "notification" field has to be in the notification, otherwise the notification will not show up.
The problem is that when I add the "notification" field to the request, on Android the notification is shown up twice. Once due to "notification", and once because I manually display the notification as I customised, to make it pop up.
So when I send the message like this:
{
"to": "/topics/all",
"data": {
"title": "Alert",
"body": "App maintanance is underway.",
}
"notification": {
"title": "Alert",
"body": "App maintanance is underway.",
}
}
It comes into android twice.
Now I could make two topics, one for Android and one for iOS, but sometimes I send messages to specific devices with token, and I don't know if its an Android device or iOS.
How can I cater for both?
Thanks
Here is my flutter code:
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'high_importance_channel', // id
'High Inportance Notifications', // title
'This channel is used for important notifications.', // description
playSound: true,
importance: Importance.high,
);
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
print('A message just showed up, id: ${message.messageId}');
showNotification(message); // without this it isn't heads-up when in background
}
Future<void> setUpFirebaseMessaging(BuildContext context) async {
print('2124: setUpFirebaseMessaging');
FirebaseMessaging.onBackgroundMessage(
_firebaseMessagingBackgroundHandler);
flutterLocalNotificationsPlugin.initialize;
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
// subscribe to topic on each app start-up
await FirebaseMessaging.instance.subscribeToTopic('all');
FirebaseMessaging.instance.getToken().then((value) {
String token = value;
print('2124: Firebase Token: ${token}');
});
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Got a message whilst in the foreground!');
// print('Message data: ${message.data}');
RemoteNotification notification = message.notification;
// AndroidNotification android = message.notification.android;
// AndroidNotification data = message.data;
// print('hashCode ${notification.hashCode}');
print('title ${message.data['title']}');
print('body ${message.data['body']}');
// if (notification != null) {
if (message.data != null) {
showNotification(message);
};
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('A new onMessageOpenedApp event was published');
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification.android;
if(notification != null && android != null){
showDialog(context: context, builder: (_){
return AlertDialog(
title: Text(notification.title),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(notification.body)
],
),
),
);
});
}
});
}
void showNotification(RemoteMessage message) {
flutterLocalNotificationsPlugin.show(
message.hashCode,
message.data['title'],
message.data['body'],
// message.notification.title,
// message.notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channel.description,
color: Colors.blue,
playSound: true,
importance: Importance.max,
priority: Priority.high,
icon: '#drawable/ic_stat_output_onlinepngtools',
),
));
}
You should remove the showNotification function from _firebaseMessagingBackgroundHandler as it triggers its own notification (from local_notification package) and firebase messaging package has its own notification so we have two!!
I want to display a widget in notification using flutter. I am using the awesome_notifications package but I am not able to achieve the same.
Future<void> triggerNotification() async{
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: 1,
channelKey: 'key1',
title: 'This is Notification title',
body: 'This is Body of Noti',
bigPicture: 'https://protocoderspoint.com/wp-content/uploads/2021/05/Monitize-flutter-app-with-google-admob-min-741x486.png',
notificationLayout: NotificationLayout.BigPicture
),
);
}
In this snippet there is the bigPicture parameter that requires the url of the image. I have converted the widget to an image using repaintBoundary. Is there any way I can pass the image widget instead of the url? Thank You.
You can use Uri.file constructor. Here's an example using a file from camera.
Future<void> triggerNotification() async {
final PickedFile pickedFile = await _picker.getImage(source: ImageSource.camera);
Uri uri = Uri.file(pickedFile.path);
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: 1,
channelKey: 'basic_channel',
title: 'This is Notification title',
body: 'This is Body of Noti',
bigPicture:
uri.toString(),
notificationLayout: NotificationLayout.BigPicture),
);
}
I have set up the Ionic/Capacitor app to receive push notifications following the capacitor tutorial,
I went through all the tutorial successfully and I receive test notifications sent from FCM both in foreground and background
I can successfully register to a topic
I can receive notifications sent to the topic
I can receive notifications sent to the token (test mode)
Now I'm trying to send notifications from a different device,
I just created a two test button to send notification in multicast to an array of tokens and another button to send notification to a given topic
In both cases from my device I receive the notifications in foreground, but not in background
I believe is something wrong with the format I'm using to send the notifications that is not correct in case of background (I can receive those from the FCM test tool)
Client
const send = functions.httpsCallable('sendPushNotificationToUsers');
const sendToTopic = functions.httpsCallable('sendPushNotificationToTopic');
const sendNotification = useCallback(
({
to,
title,
body,
onClick
}) => {
setLoading(true);
send({
to,
title,
body,
onClick
})
.then(() => setSuccess(true))
.catch(() => setError(true))
.finally(() => setLoading(false));
}, [send],
);
const sendNotificationToTopic = useCallback(
({
topic,
title,
body,
onClick
}) => {
setLoading(true);
sendToTopic({
topic,
title,
body,
onClick
})
.then(() => setSuccess(true))
.catch(() => setError(true))
.finally(() => setLoading(false));
}, [sendToTopic],
);
Server / Functions
exports.sendPushNotificationToUsers = functions.https.onCall(
(data, context) => {
if (!context.auth) {
throw new functions.https.HttpsError(
'failed-precondition',
'The function must be called ' + 'while authenticated.',
);
}
db.collection('users_meta')
.doc(data.to)
.collection('messagingTokens')
.get()
.then(messagingTokens => {
if (messagingTokens && messagingTokens.size) {
const to = messagingTokens.docs.map(i => i.data().token);
console.log(to); // I get to this console log and the tokens are printed correctly in an array
admin.messaging().sendMulticast({
title: data.title,
body: data.body,
data: {
title: data.title,
body: data.body,
onClick: data.onClick || '',
},
tokens: to,
});
}
});
},
);
exports.sendPushNotificationToTopic = functions.https.onCall(
(data, context) => {
if (!context.auth) {
throw new functions.https.HttpsError(
'failed-precondition',
'The function must be called ' + 'while authenticated.',
);
}
admin.messaging().send({
data: {
title: data.title,
body: data.body,
onClick: data.onClick || '',
},
topic: data.topic,
});
},
);
Notifications handler
const initNative = useCallback(() => {
PushNotifications.register();
PushNotifications.requestPermission().then(result => {
if (result.granted) {
// Register with Apple / Google to receive push via APNS/FCM
PushNotifications.register();
} else {
// Show some error
}
});
PushNotifications.addListener(
'registration',
(token: PushNotificationToken) => {
const device = new DeviceUUID().get();
registerTokenToUser(device, token.value);
alert('Push registration success, token: ' + token.value);
},
);
PushNotifications.addListener('registrationError', (error: any) => {
alert('Error on registration: ' + JSON.stringify(error));
});
PushNotifications.addListener(
'pushNotificationReceived',
(notification: PushNotification) => {
alert(JSON.stringify(notification));
// this array fires correctly with the app in foreground, but nothing on the notifications tray with the app in background if sent from my send functions, works correctly if sent from FCM
},
);
// Method called when tapping on a notification
PushNotifications.addListener(
'pushNotificationActionPerformed',
(notification: PushNotificationActionPerformed) => {
alert(JSON.stringify(notification));
},
);
}, [PushNotifications, history, registerTokenToUser]);
Any suggestion?
Thanks
I've found the error myself,
for the notifications be visible in background mode the notification object needs to have "notification" key populated, that was missing in my case,
correct send function should be
exports.sendPushNotificationToUsers = functions.https.onCall(
(data, context) => {
if (!context.auth) {
throw new functions.https.HttpsError(
'failed-precondition',
'The function must be called ' + 'while authenticated.',
);
}
db.collection('users_meta')
.doc(data.to)
.collection('messagingTokens')
.get()
.then(messagingTokens => {
if (messagingTokens && messagingTokens.size) {
const to = messagingTokens.docs.map(i => i.data().token);
console.log(to); // I get to this console log and the tokens are printed correctly in an array
admin.messaging().sendMulticast({
title: data.title,
body: data.body,
notification: {
title: data.title,
body: data.body,
},
data: {
title: data.title,
body: data.body,
onClick: data.onClick || '',
},
tokens: to,
});
}
});
},
);
exports.sendPushNotificationToTopic = functions.https.onCall(
(data, context) => {
if (!context.auth) {
throw new functions.https.HttpsError(
'failed-precondition',
'The function must be called ' + 'while authenticated.',
);
}
admin.messaging().send({
notification: {
title: data.title,
body: data.body,
},
data: {
title: data.title,
body: data.body,
onClick: data.onClick || '',
},
topic: data.topic,
});
},
);
I have built my own application in flutter and I have implemented Local notifications and also FirebaseMessaging:
final FirebaseMessaging firebaseMessaging = FirebaseMessaging();
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
#override
void initState() {
super.initState();
registerNotification();
configLocalNotification();
firebaseMessaging.requestNotificationPermissions();
}
void registerNotification() {
firebaseMessaging.requestNotificationPermissions();
firebaseMessaging.configure(onMessage: (Map<String, dynamic> message) {
print('onMessage: $message');
Platform.isAndroid
? showNotification(message['notification'])
: showNotification(message['aps']['alert']);
return ;
}, onResume: (Map<String, dynamic> message) {
print('onResume: $message');
return Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NotificationsScreen()));
}, onLaunch: (Map<String, dynamic> message) {
print('onLaunch: $message');
return;
});
firebaseMessaging.getToken().then((token) {
print('token: $token');
FirebaseFirestore.instance
.collection('Consultant')
.doc(firebaseUser.uid)
.update({'deviceToken': token});
}).catchError((err) {
//Fluttertoast.showToast(msg: err.message.toString());
});
}
Future selectNotification(String payload) async {
if (payload != null) {
debugPrint('notification payload: $payload');
}
await Navigator.push(
context,
MaterialPageRoute<void>(builder: (context) => NotificationsScreen(payload: payload,)),
);
}
void showNotification(message) async {
var androidPlatformChannelSpecifics = new AndroidNotificationDetails(
Platform.isAndroid
? 'it.wytex.vibeland_pro_app'
: 'it.wytex.vibeland_pro_app',
'Vibeland',
'Vibeland',
playSound: true,
enableVibration: true,
importance: Importance.max,
priority: Priority.high,
ongoing: true,
);
var iOSPlatformChannelSpecifics = new IOSNotificationDetails();
var platformChannelSpecifics = new NotificationDetails(
android: androidPlatformChannelSpecifics, iOS: iOSPlatformChannelSpecifics);
print(message);
print(message['body'].toString());
print(json.encode(message));
await flutterLocalNotificationsPlugin.show(0, message['title'].toString(),
message['body'].toString(), platformChannelSpecifics,
payload: json.encode(message));
await flutterLocalNotificationsPlugin.show(
0, '📩 Hai ricevuto un messaggio 📩 ', 'Controlla subito le Tue notifiche 🔔🔔', platformChannelSpecifics,
payload: 'item x',
);
}
void configLocalNotification() {
var initializationSettingsAndroid =
new AndroidInitializationSettings('vibeland_pro');
var initializationSettingsIOS = new IOSInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
var initializationSettings = new InitializationSettings(
android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
I wrote a function into index.js to push also firestore notification when user creates order etc..
Everything works fine, I got Localnotifications when all is open and FCM notifications when app is in background, the problem is when the app sleep...
after some minutes the app goes in sleep mode and to start it again you need to restart the application which keep my user Logged:
MultiProvider(
providers: [
Provider<AuthenticationProvider>(
create: (_) => AuthenticationProvider(FirebaseAuth.instance),
),
StreamProvider(
create: (context) => context.read<AuthenticationProvider>().authState,
)
],
child: MaterialApp(
theme: ThemeData(
pageTransitionsTheme: PageTransitionsTheme(
builders: {
TargetPlatform.android: CupertinoPageTransitionsBuilder(
),
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
}
)
),
debugShowCheckedModeBanner: false,
title: 'Vibeland Admin Authentication',
home: Authenticate(),
),
);
}
}
class Authenticate extends StatelessWidget {
#override
Widget build(BuildContext context) {
final firebaseUser = context.watch<User>();
if (firebaseUser != null) {
return StartScreenLogged();
}
return StartScreen();
}
}
but if I dont run again the app I dont get the notification because the app sleep.
what we need to do in this case?