FCM Not working in flutter with firebase_messaging: ^11.4.2 - flutter

FCM Not working in flutter with firebase_messaging: ^11.4.2
I have try with both old and new data payload for implementing FCM with Topic but when we send the notification from firebase manually . It comes and hit the natively broadcast receiver and
message shows but when we send by code and response we get 200 which is fine but the problem in plugin is that is not hit that time broadcast receiver so that message not show.
//<--Here -- sendPushMessageRun Here-->
Future<void> sendPushMessage() async {
if (_token == null) {
print('Unable to send FCM message, no token exists.');
return;
}
try {
final response = await http.post(
Uri.parse('https://api.rnfirebase.io/messaging/send'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'key=A....Q'
},
body: constructFCMPayload(_token),
);
if(response.statusCode == 200){
print('Done!');
await Firebase.initializeApp();
///
await FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
if (notification != null && android != null && !kIsWeb) {
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channelDescription:channel.description,
// TODO add a proper drawable resource to android, for now using
// one that already exists in example app.
icon: 'launch_background',
),
),
);
}
});
}else{
print('Not Done!'+response.statusCode.toString());
}
} catch (e) {
print(e);
}
}
String constructFCMPayload(String? token) {
_messageCount++;
return jsonEncode({
'topic': "fcm_test", //also try with "to" : "/topics/fcm_test"
'data': {
'via': 'FlutterFire Cloud Messaging!!!',
'count': _messageCount.toString(),
},
'notification': {
'title': 'Hello FlutterFire!',
'body': 'This notification (#$_messageCount) was created via FCM!',
},
});`enter code here`
}

Related

How to push open a page from a notification flutter

I have my method that loads firebase cloud messaging and listens for incoming messages as follows.
void loadFCM() async {
if (!kIsWeb) {
channel = const AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
importance: Importance.high,
enableVibration: true,
);
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
/// Create an Android Notification Channel.
///
/// We use this channel in the `AndroidManifest.xml` file to override the
/// default FCM channel to enable heads up notifications.
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
/// Update the iOS foreground notification presentation options to allow
/// heads up notifications.
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
}
}
void listenFCM() async {
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
if (notification != null && android != null && !kIsWeb) {
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
icon: 'launch_background',
),
),
);
if (message.data['screen'] == 'chat') {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => ChatScreen(
uid: message.data['uid'],
),
),
);
}
}
});
}
As seen I'm storing the screen I want in the data of the screen I want when I send the message and have code in the listenFCM function to attempt to change the screen but it wont work, I receive the notification but dont change screen. I'm currently using this method to send a message to a specific user
void sendPushMessage(String token, String body, String title) async {
try {
await http.post(
Uri.parse('https://fcm.googleapis.com/fcm/send'),
headers: <String, String>{
'Content-Type': 'application/json',
'Authorization': 'key=${api}',
},
body: jsonEncode(
<String, dynamic>{
'notification': <String, dynamic>{'body': body, 'title': title},
'priority': 'high',
'data': <String, dynamic>{
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
'id': '1',
'status': 'done'
'screen': 'chat'
},
"to": token,
},
),
);
} catch (e) {
print("error push notification");
}
}
Im trying to modify it so I can send a push notification they open a chat page. it would be a chat(userid) sort of thing but I dont want to send the chatId in the body of the notification or anything so how can I have my app push open my chat page when tapped from app close/open etc, Thanks for reading!

iOS firebase getInitialMessage not working Flutter

I installed firebase notification package in my Flutter project and setup the necessary settings for sending data.
Everything works fine on android, when the app is completely closed, when I send a parameter via firebase, the page I want opens, but on the ios part, when I click on the notification, it does not catch the click and the page I want does not open.
I would be very happy if you could help me where is the main point I should pay attention to for the ios part.
Main.dart
initialMessage = await FirebaseMessaging.instance.getInitialMessage();
if (initialMessage != null) {
if (initialMessage!.data['type'] == 'notification') {
await Future.delayed(const Duration(seconds: 4));
navigatorKey.currentState?.pushNamed(
'/notification'); // navigate to login, with null-aware check
}
}
pushNotificationService.dart
class PushNotificationService {
Future<void> setupInteractedMessage() async {
await Firebase.initializeApp();
RemoteMessage? initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
if (initialMessage != null &&
initialMessage.data['type'] == 'notification') {
await Future.delayed(const Duration(seconds: 6));
navigatorKey.currentState?.pushNamed(
'/notification'); // navigate to login, with null-aware check
}
// Also handle any interaction when the app is in the background via a
// Stream listener
// This function is called when the app is in the background and user clicks on the notification
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
// Get.toNamed(NOTIFICATIOINS_ROUTE);
print(message.toMap().toString());
print(message.data['type'].toString());
if (message.data['type'] == 'notification') {
navigatorKey.currentState?.pushNamed('/notification');
}
});
await enableIOSNotifications();
await registerNotificationListeners();
}
registerNotificationListeners() async {
AndroidNotificationChannel channel = androidNotificationChannel();
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
var androidSettings =
const AndroidInitializationSettings('#mipmap/ic_launcher');
var iOSSettings = const IOSInitializationSettings(
requestSoundPermission: false,
requestBadgePermission: false,
requestAlertPermission: false,
);
var initSetttings =
InitializationSettings(android: androidSettings, iOS: iOSSettings);
flutterLocalNotificationsPlugin.initialize(initSetttings,
onSelectNotification: (message) async {
// This function handles the click in the notification when the app is in foreground
// Get.toNamed(NOTIFICATIOINS_ROUTE);
});
// onMessage is called when the app is in foreground and a notification is received
FirebaseMessaging.onMessage.listen((RemoteMessage? message) {
// Get.find<HomeController>().getNotificationsNumber();
print(message!.data['type'].toString());
print(message.toMap().toString());
if (message.data['type'] == 'notification') {
navigatorKey.currentState?.pushNamed('/notification');
}
RemoteNotification? notification = message.notification;
AndroidNotification? android = message.notification?.android;
// If `onMessage` is triggered with a notification, construct our own
// local notification to show to users using the created channel.
if (notification != null && android != null) {
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
icon: android.smallIcon,
playSound: true,
),
),
);
}
});
}
enableIOSNotifications() async {
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true, // Required to display a heads up notification
badge: true,
sound: true,
);
}
androidNotificationChannel() => const AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
importance: Importance.max,
);
}
info.plist background modules
UIBackgroundModes
fetch
processing
remote-notification

Notification being sent to every user instead of a specific user on flutter

I am trying to send notifications to a specific user by using tokens. However, the notification is broadcasted to every user.
This is my code.
For initialization (main.dart):
MessagingService.initialize();
I have 2 types of users and the type of user who is receiving the notification, has the code block below.
To display the notification(homescreen.dart of user receiving the notification):
FirebaseMessaging.instance.getInitialMessage();
FirebaseMessaging.onMessage.listen((event) {
MessagingService.display(event);
});
MessagingService.storeNotificationToken();
Process of sending notification to user:
final userFireStore = await FirebaseFirestore.instance.collection('users').doc(docID).get(); // sends notification
print('receiver ID');
print(userFireStore.data()!['token']);
await sendNotification('Booking Request', 'New booking request received.', userFireStore.data()!['token']);
This class has some of the logic to send notifications.I have the logic on how to display notifications and how users can set the token to receive the notification.
More methods to send notification:
class MessagingService {
static final FlutterLocalNotificationsPlugin
_flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
static void initialize() {
final InitializationSettings initializationSettings =
InitializationSettings(
android: AndroidInitializationSettings("#mipmap/ic_launcher"));
_flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
static void display(RemoteMessage message) async{
try {
print("In Notification method");
// int id = DateTime.now().microsecondsSinceEpoch ~/1000000;
Random random = new Random();
int id = random.nextInt(1000);
final NotificationDetails notificationDetails = NotificationDetails(
android: AndroidNotificationDetails(
"mychanel",
"my chanel",
importance: Importance.max,
priority: Priority.high,
)
);
print("my id is ${id.toString()}");
await _flutterLocalNotificationsPlugin.show(
id,
message.notification!.title,
message.notification!.body,
notificationDetails,);
} on Exception catch (e) {
print('Error>>>$e');
}
}
static storeNotificationToken() async {
try {
final user = await FirebaseAuth.instance.currentUser;
String? token = await FirebaseMessaging.instance.getToken();
await FirebaseFirestore.instance.collection('users').doc(user!.uid).set({
'token': token
}, SetOptions(merge: true));
} on FirebaseAuthException catch (e) {
print(e);
throw CustomException(e.message);
}
}
}
The code block below sends notification based on the token of the receiver:
Future sendNotification(String title, String body, String token) async {
final data = {
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
'id': '1',
'status': 'done',
'message': title
};
try {
http.Response response = await http.post(Uri.parse('https://fcm.googleapis.com/fcm/send'), headers: <String, String>{
'Content-Type': 'application/json',
'Authorization': 'key=',
},
body: jsonEncode(<String, dynamic>{
'notification': <String, dynamic>{'title': title, 'body': body},
'priority': 'high',
'data': data,
'to': '$token'
})
);
if(response.statusCode == 200) {
print('notification sent');
} else {
print('error');
}
} catch (e) {
print(e);
}
}
I can see on the console that every user has the same token. And even if I alter one token to see if this is the issue, notification is still getting broadcasted to every user instead of a specific user. Am I doing anything wrong?

why do not getting notification in ios with firebase_messaging plugin in flutter?

I'm trying to send notification to the android and Ios device as well.
It's working on android devcice but something fishy with ios token , not getting notification on ios devices , I have enabled background notification for ios. In fact it was working before few days ago but suddenly stopped working on ios device. I have updated firebase_messaging plugin but still not getting notification, also visited firebase_messaging issue ,this as well .
I think there is something wrong with my ios token , because I have tested from pushtry website and throw error saying Please check device token , but testing with android token , not getting any errors. so I could say that ios token is not generating properly.
I did everything what I could do but every time got disappointed.
Here's my test Code:
class PUSHTest extends StatefulWidget {
const PUSHTest({Key key}) : super(key: key);
#override
_PUSHTestState createState() => _PUSHTestState();
}
class _PUSHTestState extends State<PUSHTest> {
String token = '';
var serverKey =
'AAAAL4uGYoY:.............................';
#override
void initState() {
super.initState();
getToken();
showAlertNotification();
}
getToken() async {
String t = await FirebaseMessaging.instance.getToken();
print(
"FCM TOKEN: $t");
setState(() {
token = t;
});
}
showAlertNotification() {
FirebaseMessaging.instance
.getInitialMessage()
.then((RemoteMessage message) {
if (message != null) {
print("NOTIFICATIONNNNNNNNNN RESPONSE11${message.data}");
}
});
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
AppleNotification ios = message.notification?.apple;
print("ios ios ios:$ios");
if (notification != null && android != null && !kIsWeb) {
if (message != null) {
print("NOTIFICATIONNNNNNNNNN RESPONSE22${message.data}");
}
}
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
if (message != null) {
print("NOTIFICATIONNNNNNNNNN RESPONSE33${message.data}");
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () => sendNotification(),
child: Text("SEND NOTIFICATION"),
),
),
);
}
// My FCM Payload To send notification to the device:
sendNotification() async {
print("send notification button pressed");
try {
http.Response response = await http.post(
Uri.parse('https://fcm.googleapis.com/fcm/send'),
headers: <String, String>{
'Content-Type': 'application/json',
'Authorization': 'key=$serverKey',
},
body: jsonEncode(
<String, dynamic>{
'notification': <String, dynamic>{
'body': 'this is a body',
'title': 'this is a title',
"content_available": true
},
'priority': 'high',
'data': <String, dynamic>{
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
'id': '1',
'status': 'done'
},
'to': token,
},
),
);
if (response.statusCode == 200) {
print("SENT NOTIFICATION TO THE DEVICE :$token");
Fluttertoast.showToast(msg: "SENT NOTIFICATION TO THE DEVICE :$token");
} else {
print("error push notification");
Fluttertoast.showToast(msg: "error push notification");
}
} catch (e) {
print("error push notification");
}
}
}
Okay, finally I found my stupidity, what I exactly did. actually It was 2 major mistakes.
firstly, I used permission_hander and haven't ask for permission for the notification because I was thinking it will be auto ask , when I added remote notification to the plistfile.
secondly, My huge stupidity, I have created 2 firebase project , added configuration file for android (google-service.json) from the another and ios(google-service.plist) from the other projects. and added server-key to the backend from one of them. Nothing wrong with FCM token.
that's why it were working for android only.
Now I have recognised my silliness and deleted duplicate firebase project one, and added configuration file from the original one and updated my server-key to my backend. and also asking permission for notification using permission_handler. That's all.

Flutter firebase_messaging - flutter_local_notifications

when the app is opened (foreground) and I receive a notification I want to navigate to a screen. The other 2 cases are working fine (background & terminated). I'm using this example
https://pub.dev/packages/firebase_messaging/example
help please I'm stuck in this for 2 days now. I know that I should add payload on onMessage.listen ok but after I did this?!!
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
print('Handling a background message ${message.messageId}');
}
/// Create a [AndroidNotificationChannel] for heads up notifications
AndroidNotificationChannel channel;
/// Initialize the [FlutterLocalNotificationsPlugin] package.
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
FirebaseMessaging.instance.getToken().then((value) {
firebaseToken = value;
print('firebaseToken $firebaseToken');
});
if (!kIsWeb) {
channel = const AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
'This channel is used for important notifications.', // description
importance: Importance.high,
);
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
}
runApp(MyApp());
}
'my home state'
int _messageCount = 0;
String constructFCMPayload(String token) {
_messageCount++;
return jsonEncode({
'token': token,
'data': {
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
'via': 'FlutterFire Cloud Messaging!!!',
'count': _messageCount.toString(),
},
'notification': {
'title': 'Hello FlutterFire!',
'body': 'This notification (#$_messageCount) was created via FCM!',
},
});
}
#override
void initState() {
super.initState();
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
if (notification != null && android != null && !kIsWeb) {
print(message.data);
print('onMessage method');
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channel.description,
icon: 'launcher_icon',
),
),
);
}
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
print('A new onMessageOpenedApp event was published!');
print(message.data);
print('onMessageOpenedApp method');
if (loginState && message != null) {
if (message.data['module'] == 'article') {
articleID = await message.data['id'];
Navigator.pushNamed(context, 'ArticleDetails',
arguments: MessageArguments(message, true));
} else if (message.data['module'] == 'question') {
questionID = await message.data['id'];
Navigator.pushNamed(context, 'QuestionDetails',
arguments: MessageArguments(message, true));
} else if (message.data['module'] == 'reservation') {
Navigator.pushNamed(context, 'Reservations',
arguments: MessageArguments(message, true));
} else if (message.data['module'] == 'job') {
Navigator.pushNamed(context, 'Jobs',
arguments: MessageArguments(message, true));
} else if (message.data['module'] == 'addresses') {
Navigator.pushNamed(context, 'InterestedAddresses',
arguments: MessageArguments(message, true));
}
} else {
Splash();
}
});
FirebaseMessaging.instance
.getInitialMessage()
.then((RemoteMessage message) async {
if (loginState && message != null) {
if (message.data['module'] == 'article') {
articleID = await message.data['id'];
Navigator.pushNamed(context, 'ArticleDetails',
arguments: MessageArguments(message, true));
} else if (message.data['module'] == 'question') {
questionID = await message.data['id'];
Navigator.pushNamed(context, 'QuestionDetails',
arguments: MessageArguments(message, true));
} else if (message.data['module'] == 'reservation') {
Navigator.pushNamed(context, 'Reservations',
arguments: MessageArguments(message, true));
} else if (message.data['module'] == 'job') {
Navigator.pushNamed(context, 'Jobs',
arguments: MessageArguments(message, true));
} else if (message.data['module'] == 'addresses') {
Navigator.pushNamed(context, 'InterestedAddresses',
arguments: MessageArguments(message, true));
}
} else {
Splash();
}
});
}
When you display local notification from FCM message in Android, you have to configure a function that will handle this case: received message is tapped while Android app is in foreground.
So add this configuration where you initalize local notifications:
await _flutterLocalNotificationsPlugin!.initialize(
const InitializationSettings(
android: AndroidInitializationSettings(),
iOS: IOSInitializationSettings()),
onSelectNotification: _onSelectNotification);
And the function should look something like this:
Future<dynamic> _onSelectNotification(String? payload) async {
}
You can try to add you navigation inside onSelectNotification callback, which you can add on notification initialization
Like this:
// initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('app_icon');
final IOSInitializationSettings initializationSettingsIOS =
IOSInitializationSettings(
onDidReceiveLocalNotification: onDidReceiveLocalNotification);
final InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS);
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: (){
// Set your navigation code here!!
},
);