Get a better understanding of Firebase Cloud Message (FCM)

Tram Ho

Introduce

In this article, I will focus more on better understanding Firebase Cloud Message (FCM) instead of configuration steps to integrate FCM into Flutter project.

What is Firebase Cloud Messaging (FCM)?

FCM is a cross-platform messaging and notification service provided by Google. You can send messages to devices registered with FCM, the sent content can be up to 4KB.

Some common use-cases:

  • Show a notification
  • Synchronize data on the device (ex: run in the background to synchronize data stored in shared_preferences)
  • Update the interface (UI) of the application

Application states when receiving notifications

Depending on the state of the application on the device, incoming messages will be handled differently. First we need to understand the state of the application:

Statedescription
ForegroundWhen the app is open and in use
BackgroundWhen the application is running but in the background. For example, when the user presses the “home” button or switches to another application
TerminatedWhen the device is locked from the screen, the application is not launched or is (fully closed) terminated from the background

There are a few prerequisites that are required for your application to receive messages from FCM:

  • Application must have been opened at least once (to register with FCM)
  • For iOS, you must setup the project to integrate APN (Apple Push Notification) and FCM
  • By default, if the application is in the foreground state, the application will not show notifications (heads up).

Request permission

For Android, by default you don’t need to ask for permission. In contrast, with iOS you must request permission from the user before you can send messages from FCM. We can do the following:

There are 4 values ​​for authorizationStatus :

  • authorized : User has granted permission
  • denied : User refuses to grant permission
  • notDetermined : User has not decided to grant permission or not
  • provisional : User grants temporary permission

For Android, the default value of authorizationStatus will be authorized if the user has not disabled the application’s notification.

Handle messages from FCM

After we have permission and understand the state of the application, we can now start handling messages sent from FCM.

Message type

There are 3 types of messages:

  • Notification only message: This type of payload contains only a notification attribute, which will be used to display a message on the user’s machine.
  • Data only message (silent message): payload of this type will have a data attribute, which is key/value pairs. These messages are considered low priority .
  • Notification & Data message: Payload will have both notification and data properties.

Based on the state of the application, messages will need to be handled differently:

ForegroundBackgroundTerminated
NotificationonMessageonBackgroundMessageonBackgroundMessage
DataonMessageonBackgroundMessage (*note)onBackgroundMessage (*note)
Notifications & DataonMessageonBackgroundMessageonBackgroundMessage

Note : Messages of data only type are considered as low priority , so they will be ignored when the application is in the background or terminated . However, you can increase the priority of the message before sending it. Example from Node.js server side:

For Foreground messages

To listen for messages while the application is in the foreground state, the onMesssage function can be used:

Note: As I said earlier, when the application is in the foreground state, it will not display a notification when receiving a message from FCM. I will show you another way to restore the dock below.

For background messages

You can use the onBackgroundMessage function to handle incoming messages while the application is in the background or terminated .

There are 3 things to note about the background message handler function (the _firebaseMessagingBackgroundHandler function in the example above):

  • Cannot be anonymous function
  • Must be a top-level function (not a method of a class)
  • There must be @pragma('vm:entry-point') annotation above the function

When a notification-type message is sent to the user, the Firebase SDK will recognize and display a notification to the user (if the user has been granted permission). Then, the above _firebaseMessagingBackgroundHandler function will be executed.

Low priority messages

As I mentioned above, data only messages are considered low priority . Devices can ignore them if your app is in the background or terminated or in a low power, performance state.

Display message in Foreground (Heads up)

Although the application still receives messages (data/notification) from FCM, it will not display any notifications on the device. For iOS : To show heads up, we just need to call below function when initializing FCM:

For Android : First you need to understand through the mechanism of displaying FCM notifications on Android. FCM will use its default channel (Notification Channel) to determine how notifications are displayed:

  • If the application is in the background or terminated , the device shows a notification when it receives it from the FCM.
  • If the app is in the foreground state, you’re using the app by default, so the notification won’t appear. (The reason Firebase explains is that in this case you should use In-App Message to send to the user instead of the Notification Message that we often use)

But of course our goal here is to show heads up notifications even in the Foreground state.

We need to create a new channel with the importance attribute set to max . Then transmit messages from the FCM to the channel. And use other notification display libraries that support, for example flutter_local_notifications . As the name implies, this package will help you to display notifications on the user’s device.

  1. First add package flutter_local_notifications to your project
  2. Initialize a channel object with the highest importance property (max) and the id “high_importance_channel”:

  1. Create a Notification Channel on the device from the channel object created above:

  1. Configure FCM to use your channel instead of the default. In the file android/app/src/main/AndroidManifest.xml , use the channel with the id “high_importance_channel” that we created above:

  1. Handle displays the message from FCM:

Now the message from FCM has been sent to the device through the channel we just created and is below the level of importance max. However, at this point you will still not see the message displayed. Because Firebase Android SDK will not allow to display any message from FCM no matter what channel it uses. That’s when it comes to use.

Use the OnMessage function to listen for messages from the FCM . From there get the data of the message, then use the flutter_local_notifications package to display the notification.

Mechanism of sending notifications by topic

In addition to sending a message to a specific device by device token, you can send by topics and so any device that has subscribed to those topics will receive them. The mechanism that allows a device to subscribe or unsubscribe to named PubSub channels, all managed by the FCM.

Since it is only interested in topics, this mechanism allows you to simplify sending messages/notifications from the server by not needing to store device tokens. However, there are a few things to keep in mind:

  • Messages sent to the topic should not contain sensitive or private information. So each topic for each user
  • Topic messaging supports unlimited number of subscriptions per topic
  • One app instance can subscribe to 2000 topics
  • A topic is created when it is first subscribed
  • If sending too many subscription requests continuously, FCM may return error 429 RESOURCE_EXHAUSTED
  • The server can send a message to up to 5 topics at a time.

Subscribe topic

To subscribe to a topic, for example the topic “weather”:

Unsubscribe topic

Send a message to a topic

The server can send a message/notification to a topic so that all devices that have subscribed to that topic can receive the message/notification. Ex: On the Node.js server, use firebase-admin to send a message to the “weather” topic.

In addition, we can use a boolean expression to define the conditions for topics that will receive messages/notifications. Ex: The example below will only send messages to devices that have subscribed to topics “weather” and “news” or “weather” and “traffic”.

Reference source:

https://firebase.flutter.dev/docs/messaging/notifications#displaying-notifications

Example project:

https://github.com/firebase/flutterfire/tree/master/packages/firebase_messaging/firebase_messaging/example

Share the news now

Source : Viblo