What I needed to do was to create another isolate in the main isolate to communicate using ReceiverPort() and SendPort() between FCM isolate and main isolate.
the new isolate:
ReceivePort? _receivePort;
void startReceivePort() {
// Unregister the previous SendPort if it exists
IsolateNameServer.removePortNameMapping('background_send_port');
_receivePort = ReceivePort();
IsolateNameServer.registerPortWithName(
_receivePort!.sendPort, 'background_send_port');
_receivePort!.listen((message) async {
// print("Received message from background isolate: $message");
if (message is Map<String, dynamic>) {
ChatMessage chatMessage = ChatMessage.fromJson(message['message']);
String action = message['action'];
if (action == "saveMessage") {
// Save the message to the database in the main isolate
await saveMessageToDatabase(chatMessage.chatId, chatMessage);
bool chatExists = await checkIfChatExists(chatMessage.chatId);
if (chatExists) {
ChatController chatController = Get.find<ChatController>();
chatController.addMessageToChat(chatMessage.chatId, chatMessage);
int totalUnreadMessagesCount = await getTotalUnreadMessages();
int totalUnreadChatsCount = await getTotalUnreadChats();
// Push a notification with unread messages data
NotificationService().pushNotification(
id: 100,
body:
"$totalUnreadMessagesCount unread messages from $totalUnreadChatsCount chats",
title: "Conversations",
category: NotificationCategory.Message,
payload: {
"screen": "chat",
},
);
}
}
}
});
}
// Unregister the SendPort when the app terminates to prevent memory
leaks
void stopReceivePort() {
IsolateNameServer.removePortNameMapping('background_send_port');
_receivePort?.close(); // Close the ReceivePort
}
You will need to call startReceivePort() before runApp(const MyApp()) in main.dart and stopReceivePort() in the dispose() in your main stateful widget of your app and voila!