I have checked both firebase_dart and flutterfire packages but none of them provide a firebase FirebaseMessaging class to use. Is there any way I can use Cloud Messaging in my Flutter Windows app? I want to listen to events from the console in the app and send a Windows notification using the event data.
I have sort of found a workaround that is usable, at least for now. The answer by Allysson is about sending events as a Dart admin client, but I want to receive messages on my Flutter Windows application.
Workaround Steps:
class Message {
final String title;
final String subtitle;
final int id;
final String? url;
final String? operation;
final String? device;
@override
const Message(
{required this.title,
required this.subtitle,
required this.id,
this.url,
this.operation,
this.device});
@override
String toString() {
return 'Message{title: $title, subtitle: $subtitle, id: $id, url: $url, operation: $operation, device: $device}';
}
Map<String, dynamic> toMap() {
return {
'title': title,
'subtitle': subtitle,
'id': id,
'url': url,
'operation': operation,
'device': device,
};
}
factory Message.fromMap(Map<String, dynamic> map) {
return Message(
title: map['title'] as String,
subtitle: map['subtitle'] as String,
id: map['id'] as int,
url: map['url'] as String?,
operation: map['operation'] as String?,
device: map['device'] as String?,
);
}
}
In this Message class, we have non-nullable id, title, and subtitle fields, which are our static data structure from the RTDB. Other nullable fields are optional which I will explain.

As already pointed out, the id, title, and subtitle fields are mandatory and not nullable. id is a unique integer which is checked each time by our Windows client, optionally you can save the last id value on disk to prevent repetitive notifications on app restarts.
Each time id is changed in our database, the event is sent to clients listening to this RTDB, then clients check if id's value is new or not, then send a notification, there are multiple notification packages on pub.dev. title and subtitle are passed to our notification package's functions to actually send the notification.
StreamSubscription? startListening() {
FirebaseDatabase db = FirebaseDatabase(
app: app,
databaseURL:
'<Our RTDB URl>');
db.goOnline();
return db.reference().onValue.listen((event) async {
final data = event.snapshot.value;
if (data != null &&
data['title'] != null &&
data['subtitle'] != null &&
data['id'] != null &&
data['title'] != '' &&
data['subtitle'] != '') {
Message message = Message.fromMap(data);
if (widget.prefs.getInt('id') != message.id) {
if (message.device == (await deviceInfo.windowsInfo).computerName ||
message.device == null) {
var toast =
LocalNotification(title: message.title, body: message.subtitle)
..show();
toast.onClick = () {
if (message.url != null) {
launchUrl(Uri.parse(message.url!));
}
};
await widget.prefs.setInt('id', message.id);
}
}
}
});
}
In the code sample above, we are making an object for our database, listening to it and returning the StreamSubscription to handle listening states.
At last, we will actually start listening to our database:
StreamSubsricption? dbSub;
@override
void initState() {
super.initState();
dbSub = startListening(); //Start listening to our RTDB
}
@override
void dispose() {
dbSub?.cancel(); //Stop listening - Must be called to prevent a memory-leak
super.dispose();
}
This way, we are sending notifications to our Windows clients each time after changing id's value on the Firebase console, we can optionally define url field to open the URL in the browser when client clicks on the notification.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With