Notifications on React Native using Firebase Cloud Messaging with Notifee.
Notifications on React Native using Firebase Cloud Messaging with Notifee.
Firebase Cloud Messaging
Firebase Cloud Messaging is a notification service which can be used to send push notifications and in-app messages in iOS and Android applications.It supports web as well.
Key capabilities of Firebase Cloud Messaging
- Send notification messages or data messages:
Send notification messages that are displayed to your user or send data messages and determine completely what happens in your application code. See Message types.
- Versatile message targeting:
Distribute messages to your client app in any of 3 ways — to single devices, to groups of devices or to devices subscribed to topics.
- Send messages from client apps:
Send acknowledgments, chats and other messages from devices back to your server over FCM’s reliable and battery-efficient connection channel.
How does FCM work?
An FCM implementation includes two main components for sending and receiving:
- A trusted environment such as Cloud Functions for Firebase or an app server on which to build, target and send messages.
You can send messages via the Firebase Admin SDK or the FCM server protocols. For testing or for sending marketing or engagement messages with powerful built-in targeting and analytics, you can also use the Notifications composer.
Here is a brief illustrative overview of the FCM Architecture:
See the architectural overview for more detail and important information about the components of FCM.
Installation with React Native
To use FCM with React Native, first you need to add react-native-firebase to your project.
Installation with NPM:
Install the React Native Firebase 'app' module to the root of your React Native project with NPM or Yarn:
# Install & setup the app module yarn add @react-native-firebase/app # Install the messaging module yarn add @react-native-firebase/messaging # If you're developing your app using iOS, run this command cd ios/ && pod install
iOS - Requesting Permissions
iOS prevents messages containing notification (or ‘alert’) payloads from being displayed unless you have received explicit permission from the user.
To learn more about local notifications, view the Notifications documentation.
@react-native-firebase/messaging module provides a
requestPermission method which triggers a native permission dialog requesting the user's permission:
The permissions API for iOS provides much more fine-grain control over permissions and how they’re handled within your application. To learn more, view the advanced iOS Permissions documentation.
On Android, you do not need to request user permission. This method can still be called on Android devices; however, iand will always resolve successfully.
FCM messages are sent to the registered devices, I would recommend testing on real device however messages can be sent to Android simulators.
To understand how the FCM messages are received, we would first have to know the application states in which application receives the message and behave accordingly.
The app can either be in Foreground state or in Background when the app is minimized, or it can be in quit state when the user has killed the app.
The app must have to be opened once before notifications can be received. Also instead of closing the app, if user force quits the app then the user must reopen the app to start receiving notifications again.
When the message is fired from the Firebase admin SDK or from console, it is received in one of the following handlers depending on the app state.
OnMessage: when the app is in foreground state.
SetBackgroundMessageHandler: When the app is in background or quit state.
An FCM message consists of two payloads:
Notification: A push notification will be displayed by the app if this field is included (does not display a notification when the app is active in the foreground).
onMessage handler will catch the events if this field is included and the app is active in the foreground.
To learn more about how to send these options in your message payload, view the Firebase documentation for your FCM API implementation.
Foreground State Messages
To listen to messages on foreground, we will use the
Background/Quit State Messages
To receive notifications when the app is not active we would have to configure a background handler to receive messages.
If notification property was sent to the
remoteMessage, the notification would have already been shown by the FCM SDK.
Data Only Messages:
When a notification only has data in the payload and does not have the notification property, it can be referred to as 'data only' messages or 'silent' messages.
These silent notifications can be useful when you want to update the local store of the user in the background or show the notifications yourself (using third party notification handlers in React Native such as Notifee).
When an incoming message is 'data-only' (contains no
notification option), both Android & iOS regard it as low priority and will prevent the application from waking (ignoring the message). To allow data-only messages to trigger the background handler, you must set the 'priority' to 'high' on Android and enable the
content-available flag on iOS. For example, if using the Node.js
firebase-admin package to send a message:
For iOS specific 'data-only' messages, the message must include the appropriate APNs headers as well as the
content-available flag in order to trigger the background handler. For example, if using the Node.js
firebase-admin package to send a "data-only" message to an iOS device:
Background Application State
The background notification handler is implemented slightly differently on both Android and iOS. On Android a headless JS task is created to listen to the messages which runs the handler separately from the React component.
On iOS however, when a message is received the device silently starts your application in a background state. Unlike Android, here the
backgroundHandler is called along with the root of your application, which might and most probably will be a problem for you if you are relying on any kind of side effects (`useEffects` etc.). To get along with this problem, you can inject a
isHeadless prop into your app and use this to conditionally render
null instead of the root of your app.
You have to manually insert
isHeadless prop into your app, you can do this by update your
On Android, the root component does not get rendered when the app is in headless state hence the
isHeadless prop will not exist.
The basic installation of FCM can be nice enough for just showing the notifications in the background, probably losing the ability of showing pop up notifications in the background. As soon you want any kind of control over you notifications it starts to get messier and if you are coming from earlier versions of FCM, you are in fact losing a significant amount of API support. FCM however recommends using third party libraries control your notifications and let FCM act as a messaging delivery service for you.
Notifee is a popular third party app which is recommended by invertase and is also a fork of earlier version.
Notifee : Advanced Notifications
FCM provides support for displaying basic notifications to users with minimal integration required. However, if you require more advanced notifications, you need to integrate a 3rd party local notifications package, such as Notifee with your app.
- Advanced channel and group management.
- Custom appearance with HTML text styling, custom icons, badge support, colors and more.
- Behavior management such as custom sounds, vibration patterns, device notification light management and more.
- Displaying on-going Foreground Service Notifications for dealing with long-running background tasks.
- Advanced interaction handling with action buttons, quick reply features and more.
- Support for built in styling; Big Picture Style, Big Text Style, Inbox Style & Messaging Style notifications.
- Adding Progress Indicators & Timers to your notification.
# Using npm npm install --save @notifee/react-native # Using Yarn yarn add @notifee/react-native # For iOS cd ios/ && pod install --repo-update npx react-native run-ios # For Android npx react-native run-android
Displaying a Notification
When the button is pressed, we perform two tasks: creating a channel & displaying a notification.
Channels are an Android only concept used to categorize and allow users to control how notifications are handled on their devices. Channels are created with sensible default settings and are created or updated each time a call to
createChannel is performed, so it is safe to keep calling this method.
Once the channel has been created, the
displayNotification method is called passing in a
body. The required
channelId is also passed inside of the
android property object to assign the notification to the channel.
On iOS platform, the call to
createChannel resolves instantly & gracefully (iOS has no concept of a channel), then calls
Please go to https://notifee.app for detailed documentations on various customization with your notifications.
Alternatives to Notifee:
With Notifee requiring a paid license for release builds, we appreciate this model may not be viable for everyone. Other Open Source alternatives are also available if required:
- invertase/react-native-firebase (version 5 only) (works without the customization).
Thank you for reading! I hope that this article has given you the insight you need to try FCM and Notifee to implement better and more targeted notifications in your apps.