Firebase notifications in Flutter (Part II)

Manage the notifications in your Flutter app

Bernardo Iribarne
Nerd For Tech
5 min readAug 30, 2024

--

Photo by Jonas Leupe on Unsplash

In my last article, I developed the idea of how we can manage notifications with Firebase to integrate them into our Flutter application. I provided an overview of what Firebase offers and how we can leverage it to receive notifications in Flutter. If you haven’t read it yet, here’s the link:

Today, I’ll guide you through the process of handling notifications sent by Firebase to your Flutter application.

Through this post we are going to:

  1. Create the Firebase project
  2. Configure our Flutter app to receive messages from the created Firebase project
  3. Create a couple of classes to manage the received messages.

Firebase project

First, let’s create the project in Firebase Console:

  1. Open Firebase Console Web page

2. Create a new project

3. Add your Flutter app to the Firebase project and follow the instructions. The process is well explained and straightforward

If you follow the Firebase instructions, you will see 2 apps in your Firebase console:

And also the flutterfire tool created a configuration class into your Flutter project:

Configure our Flutter app

Add Firebase packages

To integrate Firebase into our Flutter app, we must add two Firebase dependencies: firebase_messaging and firebase_core

flutter pub add firebase_messaging
flutter pub add firebase_core

Integrate the Firebase project

As we saw before, the flutterfire tool created a class into our Flutter project with the firebase configuration. The class is called DefaultFirebaseOptions and contains the settings to connect to our Firebase apps (android & ios).

We are going to use that class to initialize our app to use Firebase. The key will be to have this line into our app:

await Firebase.initializeApp(  options: DefaultFirebaseOptions.currentPlatform);

Manage the received messages

In order to manage the Firebase messages I’ve created 3 classes:

Classes to manage Firebase messages
  1. FirebaseNotificationService: it has the ability to initialize the service, request permisisons to use notifications on the device, register the device (token), subscribe to topics, etc.
  2. FirebaseNotificationHandler: implements the handlers for the firebase messages, what to do when a message is coming into the app.
  3. LocalNotificationService: to push the notifications and show the messages to the user.

FirebaseNotificationService

Into this class we are going to initialize the service in the method “initNotifications” where we use the hander and the local notification clases

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'dart:io' show Platform;

import 'package:funpass/src/config/firebase_options.dart';
import 'firebase_notification_handler.dart';
import 'local_notification_service.dart';


Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {

FirebaseNotificationsHandler handler = FirebaseNotificationsHandler();
handler.processOnBackground(message);

}

class FirebaseNotificationService {

FirebaseNotificationsHandler handler = FirebaseNotificationsHandler();
LocalNotificationService localNotificationService = LocalNotificationService();

final String messagetype_global = "global";

FirebaseNotificationService();

initNotifications() async {

await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform,);

var firebaseInstance = FirebaseMessaging.instance;

var status = await firebaseInstance.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);

await firebaseInstance.setForegroundNotificationPresentationOptions(
alert: false,
badge: false,
sound: false,
);

var token = await firebaseInstance.getToken();

await firebaseInstance.subscribeToTopic( Environment().config.firebaseTopic);

//background message
// Set the background messaging handler early on, as a named top-level function
FirebaseMessaging.onBackgroundMessage( _firebaseMessagingBackgroundHandler );

FirebaseMessaging.onMessageOpenedApp.listen( _onMessageOpenedApp);

//foreground message
FirebaseMessaging.onMessage.listen( _onMessage );

return status.authorizationStatus;
}

Future<void> _onMessageOpenedApp(RemoteMessage message) async{
handler.processOnMessageOpenedApp(message);
}


/**
* this message is executed when the app receive a firebase message
* in foreground.
*/
Future<void> _onMessage(RemoteMessage message) async{
handler.processOnMessage(message);
}

}

FirebaseNotificationHandler

The handler will be responsible to handle the Firebase messages. We are going to define what to do when we receive messages from Firebase

import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'local_notification_service.dart';

/**
* This class handles the Firebase notifications
*/
class FirebaseNotificationHandler {

final String messagetype_global = "global";

LocalNotificationService localNotificationService = LocalNotificationService();

/**
* This is a Foreground message.
*/
Future<void> processOnMessage(RemoteMessage message) async {

var messageType = message.data['messageType'];

if (messageType == messagetype_global) {

_processGlobalNotification(message, inForeground: true);

}

}

/**
* This is when the User clicks on the IOS/Android Notitication
*/
Future<void> processOnMessageOpenedApp(RemoteMessage message) async{
//DO something here.
}

/**
* This is a Background message.
*/
Future<void> processOnBackground(RemoteMessage message) async{
var messageType = message.data['messageType'];
if (messageType == messagetype_global) {
_processGlobalNotification(inBackground:true,message);
}
}



Future<void> _processGlobalNotification(RemoteMessage message, {bool inForeground=false, bool inBackground=false}) async {
RemoteNotification? notification = message.notification;

if( notification != null ){
_saveRemoteNotification( notification, inBackground );
if(!inBackground) {
localNotificationService.show(notification);
}
}
}


void _saveRemoteNotification(RemoteNotification? notification, inBackground) {
if(notification!=null){
//here we can save the notification into the device.
}
}

}

LocalNotificationService

In this class will manage how to show the notifications into our Flutter app.

To use is we have to install this package:

flutter pub add flutter_local_notifications
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

class LocalNotificationService {

//instance of FlutterLocalNotificationsPlugin
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();

final AndroidNotificationChannel channel = AndroidNotificationChannel(
'high_importance_channel', // id
'Importance Notifications', // title
importance: Importance.max,
);

//NotificationDetails? platformChannelSpecifics;
NotificationDetails? platformChannelSpecifics = const NotificationDetails(
android: AndroidNotificationDetails('high_importance_channel', 'MyApp Channel',
channelDescription:
'MyApp Notifications Channel', //Required for Android 8.0 or after
importance: Importance.defaultImportance,
priority: Priority.defaultPriority));

Future<void> init() async {

const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('launcher_icon');

final DarwinInitializationSettings initializationSettingsDarwin =
DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true
);

final InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsDarwin);
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onDidReceiveNotificationResponse: onDidReceiveNotificationResponse);


}

Future<void> showNotificationData(Map<String, dynamic> notificationData) async {
await flutterLocalNotificationsPlugin.show(
12345,
notificationData["title"],
notificationData["body"],
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
icon: 'launcher_icon',
channelDescription: channel.description
// other properties...
),
),
payload: notificationData["hashCode"]);
}

Future<void> show( notification) async {
var androidChannelSpecifics = AndroidNotificationDetails(
channel.id,
channel.name,
icon: '@mipmap/launcher_icon',
channelDescription: channel.description
);
DarwinNotificationDetails iosNotificationDetails =
DarwinNotificationDetails( );

flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
iOS: iosNotificationDetails,
android: androidChannelSpecifics,
),
payload: "${notification.hashCode}"
);
}

void onDidReceiveNotificationResponse(NotificationResponse response) async {
// display a dialog with the notification details, tap ok to go to another page
}

}

I shared my classes as a kind of template, because I removed all the specific implementation of my app. I hope this serves as an example for configuring your application

Conclusion

  1. Create a Firebase project in Firebase Console web
  2. Follow the Firebase instructions to integrate Firebase into your Flutter app.
  3. Create your own classes to manage the Firebase messages.

Thanks for reading, Clap if you like it!

Photo by Wil Stewart on Unsplash

Let me know your comments below.

--

--

Bernardo Iribarne
Nerd For Tech

Passionate about design patterns, frameworks and well practices. Becoming a Flutter expert