Flutter app only receiving FCM messages to specific token - flutter

I am updating my Flutter app in order to receive Firebase Cloud Messaging messages.
I have followed all needed changes in the app and on Firebase console.
Now I am trying to send a test message from FCM to my android device, but it only receives a message when sent using the test message option with an specific token.
It doesn't receive a normal message to all devices.
This is the main.dart code I am using:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
},
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
},
onResume: (Map<String, dynamic> message) async {
print("onResume: $message");
},
);
_firebaseMessaging.requestNotificationPermissions(
const IosNotificationSettings(
sound: true, badge: true, alert: true, provisional: false));
_firebaseMessaging.onIosSettingsRegistered
.listen((IosNotificationSettings settings) {
print("Settings registered: $settings");
});
_firebaseMessaging.getToken().then((String token) {
assert(token != null);
print("token firebase " + token);
});
runApp(new MaterialApp(
home: new MyApp(),
));
What am I doing wrong?

Make sure that all devices are subscribed to topic.

Related

Flutter - firebase FirebaseMessaging.onMessageOpenedApp doesn't fire when i click on notification

I use firebase messaging for chats on a Flutter app. I added configuration part for firebase and notification, but when the user click on notification, the screen not opened and the FirebaseMessaging.onMessageOpenedApp method doesn't fired
I added firebase configuration on main method
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
await SessionManagement.init();
await SessionManagement.setUser();
DioUtil.getInstance();
if (!kIsWeb) {
channel = const AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
description: 'This channel is used for important notifications.',
importance: Importance.high,
);
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
await firebaseMessaging
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
}
runApp(AppProvider(child: MyApp()));
}
AndroidNotificationChannel channel;
FirebaseMessaging firebaseMessaging = FirebaseMessaging.instance;
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
if(kDebugMode)
print('Handling a background message ${message.data}');
}
Then I added notification configuration on main screen.
#override
void initState() {
super.initState();
initFirebaseConfig();
}
void initFirebaseConfig() async {
requestPermission();
FirebaseMessaging.instance
.getInitialMessage()
.then((RemoteMessage message) {
if (message != null) {
_handleMessage(message);
}
});
FirebaseMessaging.onMessage.listen(showFlutterNotification);
FirebaseMessaging.onMessageOpenedApp.listen((event) {
print('Just received a notification when app is opened');
_handleMessage(event);
});
}
void showFlutterNotification(RemoteMessage message) {
print("heeeey onMessage" + message.toString());
RemoteNotification notification = message.notification;
AndroidNotification android = message.notification?.android;
if (notification != null && android != null && !kIsWeb) {
flutterLocalNotificationsPlugin.show(
notification.hashCode,
"New message from ${notification.title}",
notification.body,
NotificationDetails(
iOS: IOSNotificationDetails(subtitle: notification.title),
android: AndroidNotificationDetails(
channel.id,
channel.name,
channelDescription: channel.description,
icon: 'ic_notifications_icon',
),
),
);
}
}
void _handleMessage(RemoteMessage message) async {
print("heeeey onMessageOpenedApp" + message.toString());
NotificationModel notificationData =
NotificationModel.fromJson(message.data);
print(notificationData.data.toString());
if (notificationData.screen == "chats") {
Chat chat = Chat.fromJson(data: jsonDecode(notificationData.data));
print(chat.toString());
Navigator.of(context, rootNavigator: true)
.pushNamed(ChatScreen.routeName, arguments: chat);
// MyApp.navigatorKey.currentState.pushNamed('contact');
}
}
void requestPermission() async {
try {
NotificationSettings settings = await firebaseMessaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
print('User granted permission: ${settings.authorizationStatus}');
if (Platform.isIOS) {
await firebaseMessaging.setForegroundNotificationPresentationOptions(
alert: true, // Required to display a heads up notification
badge: true,
sound: true,
);
}
} catch (error) {
print('permission rejected');
}
}
After sending message I request firebase send message
static Future<void> sendNotification(
Chat chat, String deviceToken, String title) async {
final postUrl = 'https://fcm.googleapis.com/fcm/send';
NotificationModel notificationData = NotificationModel(
id: chat.id,
clickAction: "FLUTTER_NOTIFICATION_CLICK",
screen: "chats",
data: jsonEncode(chat.toJson()));
final data = {
"notification": {"body": chat.lastMessage.body, "title": title},
"priority": "high",
"data": notificationData.toJson(),
"to": deviceToken,
};
final headers = {
'content-type': 'application/json',
'Authorization':
'key=FIREBASE_KEY',
};
final response = await http.post(Uri.parse(postUrl),
body: json.encode(data),
encoding: Encoding.getByName('utf-8'),
headers: headers);
if (response.statusCode == 200) {
if (kDebugMode) print("true");
} else {
if (kDebugMode) print("heeeey!" + response.statusCode.toString());
}
}
I tried many code but it's still not working, could you please help me to find the issue

How can we send push notification to an specific user while app is exited. - FLUTTER

I am actually working with a e-commerce app and want to send notification to a delivery boy when order is placed from user app.
How can we identify the specific delivery boy app from backgroud (when app is exited).
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage
message) async {
await Firebase.initializeApp();
SharedPreferences _prefs = await SharedPreferences.getInstance();
print('A message just showed : ${message.messageId}');
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
// <------------Local Notification Initilization-------------->
FirebaseMessaging.onBackgroundMessage(
_firebaseMessagingBackgroundHandler);
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
runApp(MyApp());
}
Use http request to send notifications, and use topic parameter for specific user selection, check the code example that I've used in my case:
final String serverToken = 'YOUR_SERVER_TOKEN_HERE';
FirebaseMessaging firebaseMessaging = FirebaseMessaging.instance;
Future<Map<String, dynamic>> sendAndRetrieveMessage(String typeOfNotification,
{String? sellerId, String? chatId, String? postId}) async {
NotificationSettings settings = await firebaseMessaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
String notification = getNotificationMessage(typeOfNotification);
notificationMsg.value = notification;
addToNotifications(sellerId!, notification, postId ?? "$userId", chatId ?? "$userId");
print('User granted permission: ${settings.authorizationStatus}');
String topic = '';
if (typeOfNotification == 'live') {
topic = "/topics/$userId";
} else if (typeOfNotification == 'post') {
topic = "/topics/$userId";
} else {
topic = "/topics/${sellerId}_personal";
}
await http.post(
Uri.parse('https://fcm.googleapis.com/fcm/send'),
headers: <String, String>{
'Content-Type': 'application/json',
'Authorization': 'key=$serverToken',
},
body: jsonEncode(
<String, dynamic>{
'notification': <String, dynamic>{
'body': "${userIsASeller.value ? shopName.value : userName.value} $notification",
'title': "Shopenlive",
},
'priority': 'high',
'data': <String, dynamic>{
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
'id': '1',
'status': 'done',
'title': "Shopenlive",
'body': "${userIsASeller.value ? shopName.value : userName.value} $notification",
},
'to': topic,
},
),
);
final Completer<Map<String, dynamic>> completer = Completer<Map<String, dynamic>>();
/* firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
completer.complete(message);
},
); */
return completer.future;
}

flutter How to intercept the notification and do some processing before displaying it to user

// I am trying to decode the encoded title and message body received from the FCM notification before fire it up by the system.
_firebaseMessaging.configure(onMessage: (Map<String, dynamic> message) async {
// when app is running on foreground
},
onBackgroundMessage: myBackgroundMessageHandler,
onLaunch: (Map<String, dynamic> message) async {
//when app is terminated or not running
},
onResume: (Map<String, dynamic> message) async {
//when app is running in background
},
);

to enable or disable the notification flutter

I want to enable/disable the notification service with help of a button when this button is enabled, the user receives the notification, and when it's disabled he won't receive any notifications.
import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';
class FirebaseNotifications {
FirebaseMessaging _firebaseMessaging;
void setUpFirebase() {
_firebaseMessaging = FirebaseMessaging();
firebaseCloudMessaging_Listeners();
}
void firebaseCloudMessaging_Listeners() {
if (Platform.isIOS) iOS_Permission();
_firebaseMessaging.getToken().then((token) {
print(token);
});
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print('on message $message');
},
onResume: (Map<String, dynamic> message) async {
print('on resume $message');
},
onLaunch: (Map<String, dynamic> message) async {
print('on launch $message');
},
);
}
void iOS_Permission() {
_firebaseMessaging.requestNotificationPermissions(
IosNotificationSettings(sound: true, badge: true, alert: true));
_firebaseMessaging.onIosSettingsRegistered
.listen((IosNotificationSettings settings) {
print("Settings registered: $settings");
});
}
}
what you should do is that when implementing the notifications subscribe the user to a topic with
FirebaseMessaging.instance.subscribeToTopic ('news');
If this user wants to deactivate notifications, you only unsubscribe from the topic with
FirebaseMessaging.instance.unsubscribeFromTopic ('news');
Obviously when you send the notifications from the backend or console, you must specify this topic "news" or the name that you decide to put it

Firebase Message Receive only on login Flutter

I am using flutter firebase cloud messaging plug in and it is working fine. I want to receive the message only when user is logged in . I am receiving notification even after user is logged off.
I have following code . which runs even after user is logged off. How to stop following code when user is logged off.
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
_showItemDialog(message);
},
onBackgroundMessage: myBackgroundMessageHandler,
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
_navigateToItemDetail(message);
},
onResume: (Map<String, dynamic> message) async {
print("onResume: $message");
_navigateToItemDetail(message);
},
);
just check if the user is logged in your app or not by checking the value of your shared preferences as soon as you receive the push notification,
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
if (myPref.get('isLoggedin')){// here you check if user is logged in or not
_showItemDialog(message);
}
else
//do nothing
},
FirebaseAuth.instance.currentUser().then((firebaseUser){
if(firebaseUser == null) {
//signed out
}
else{
//signed in
showMessage();
} });