Flutter: FCM notifications on Mobile and Web

Guillaume Roux
4 min readOct 15, 2020

I have been recently asked to add notifications to a Flutter application I was working on. Problem is, we also had to make it available for the on development Flutter Web application. As it was an interesting challenge I decided to share how I have done my implementation.

Prerequisites

  • Create your initial Flutter app
  • Having created and configured a Firebase project for Android (or iOS) & Web

Set Up

First of all we are going to add Firebase to our Flutter application for mobile and web :

  • Open your pubspec.yaml and add the following dependencies:
dependencies:
firebase_core: ^0.5.0+1 # Works for both mobile & web
firebase_messaging: ^7.0.2 # This one is for the mobile part

Do not forget to execute flutter packages get afterwards.

  • Initialize your Firebase in your lib/main.dart :
lib/main.dart
  • As you want your Firebase to be web compatible you also need to edit your web/index.html :
web/index.html
  • Add your Firebase credential files to your mobile application. For Android I needed to add thegoogle-services.json downloaded from Firebase inside android/app/ . Also do not forget to add the necessary Android dependencies inside your android/build.gradle and android/app/build.gradle (you can refer to Firebase documentation to do so).

Coding classes for mobile & web

Now that your Firebase is ready to be used we can begin to code our implementation for both mobile & web.

We will first create an abstract class called NotificationHelper which will define our needed methods and a class NotificationModel which correspond to the parsed notification we will received from Firebase.

Feel free to edit the NotificationModel depending on what you expect from your notification.

So, to explain a bit what method are defined by NotificationHelper :

  • Future<bool> get isReady; this getter will help us to know if our singleton (which I will present after) has been correctly initialized.
  • Stream<NotificationModel> get stream; this getter will be used to be notified when we receive a new notification from Firebase.
  • void close(); is used to close our stream.
  • Future<String> getToken([bool force = false]); this method will allow us to fetch our FCM token from Firebase. If the token has already been fetched it will return it except if the force parameter is at true .
  • Future<dynamic> requestPermission(); is the method used to request notification permissions (push notification for mobile and browser notification on web).

Now that we have defined our method we can create our classes FirebaseMessagingHelper . Both will be singletons to avoid creating multiple instances and requesting more than one time the FCM token or listen to unused notifications stream.

Mobile implementation

lib/firebase_mobile_messaging.dart

This implementation relies on the package firebase_messaging which will configure a callback method _onMessageReceived when a notification is catched. This callback will update our stream so we can be notified when a new event is send.

Web implementation

As the package firebase_messaging is currently not compatible with Flutter Web we first need to register a service worker in the index.html .

web/index.html

We have uncommented the firebase-messaging script and added :

<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register("/firebase-messaging-sw.js");
});
}
</script>

And as precised in the index we are creating a file named firebase-messaging-sw.js inside the /web folder (it is important to keep this name as Firebase will look for it).

web/firebase-messaging-sw.js

If you are using Firebase version’s different from mine try to keep the same for both index.html and firebase-messaging-sw.js .

Now we can code our FirebaseMessagingHelper class for web inside a firebase_web_messaging.dart .

lib/firebase_web_messaging.dart

The PUBLIC_API_KEY I am refering to can be found in your Firebase project’s settings -> Cloud Messaging tab -> Web Configuration. You might need to generate a key if you did not already have one.

Implementing our classes

As you have seen above both of our files firebase_mobile_messaging.dart & firebase_web_messaging.dart have the same class so how can we use them together ?

My answer is : conditional import ! I am simply encapsulating my class in another abstract class which I will name NotificationEncapsulation to get the correct instance of FirebaseMessagingHelper depending of the platform.

lib/notification_encapsulation.dart

Here is a home_page.dart file example which will fetch the FCM token and display it, working both on mobile and web.

You can test the notification using a site like Push Tester to send notification to your application. Simply mention your server key which you can find in your Firebase project’s settings -> Cloud Messaging Tab (should be the first section) and your application’s FCM token.

lib/home_page.dart

Conclusion

Here it is folks ! Hope I was clear enough in explaining how to implement those push notifications (This is my first Medium story by the way). Do not hesitate to point out if some explanations were not with enough precision.

Firebase Messaging really is a useful tool but documentation and complete example for Flutter Web were missing so this is why I decided to make one myself.

--

--