Flutter: FCM notifications on Mobile and Web
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
:
- As you want your Firebase to be web compatible you also need to edit your
web/index.html
:
- Add your Firebase credential files to your mobile application. For Android I needed to add the
google-services.json
downloaded from Firebase insideandroid/app/
. Also do not forget to add the necessary Android dependencies inside yourandroid/build.gradle
andandroid/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.
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 theforce
parameter is attrue
.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
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
.
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).
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
.
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.
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.
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.