Push Notification is one of the features that connect your app with the end-user. However, if you think that Push Notification is just a pop up to display a
simple text message to end-user, think again. The Push Notification mechanism allows your app to perform more than just
displaying a message to the user. To know what else the
Push Notification can do, watch till the end of this tutorial video. Welcome back to JustCode Channel! Please support us by subscribing
to our channel and like our video. If you have any questions in this tutorial, please leave a comment below. Today tutorial, we will continue to modify
the Dictionary app we had created in the past tutorial to illustrate how to use the
Push Notification mechanism. First, we need to know that there
are two main types of notification. They are the local notification
and remote notification. The local notification allows
the app to create a notification and display within the device itself. The remote notification is
created via a remote server and "push" to the registered devices. In this tutorial, we will concentrate on the remote
notification via Firebase Cloud Messaging API. The Firebase provides a variety of services ranging from database storage, machine learning, authentication, cloud messaging, and much more. You can visit firebase.google.com
for more information. Today, we will just concentrate on the
Firebase Cloud Messaging (FCM), which is the remote push notification service. Apple also has its own
Cloud Messaging service, which is the Apple Push Notification
service (APNs) for iOS device. However, it is troublesome and time-consuming if we need to maintain the server application
that uses both APNs and FCM API to push notification to
iOS and Android devices. The main advantage of using FCM is that it allows you to push notification
to both Android and iOS devices with a single API. FCM act as a proxy for APNs. To use Firebase services, you must have a valid Firebase account and set up a Project in the Firebase Console. We had done that in tutorial 5. If you are new to Firebase, please watch our tutorial 5 for detailed steps on Firebase setup. In this tutorial, I assumed that you already have a
project set up in the Firebase console. We need to install a few npm
modules require by the FCM. Let's bring up our terminal screen. Make sure you are in the
JustCodeDict project folder. The modules we are going to install are the @react-native-firebase/app and the @react-native-firebase/messaging module. Key in the command as shown
to perform the installation. Once the modules are installed, we need to issue the pod update
Firebase/CoreOnly command in the ios folder. The reason is we had installed
Firebase/CoreOnly in Tutorial 5 and there is a version update
when we making this tutorial. If you are creating a new project, then you just need to issue the pod
install command instead of the update command. We had completed the installation of the modules. Now, we need to perform some setup
before we can use the Push Notification feature. First, we will set up the
Push Notification for iOS. You are required to have a valid Apple
developer account before you proceed. Open the JustCodeDict workspace
in the ios folder via the Xcode. Click on the JustCodeDict project on the side menu. Select the Targets as JustCodeDict, then click on the Signing & Capabilities
tab on the right of the screen. Make sure you had selected the correct
Team under the Signing section and there is no signing error. You cannot use the same
bundle identifier as this tutorial. You need to change the bundle
identifier to a one that is not being used. Click on the + Capability on the
top left of the tab screen. In the pop-up dialog box, double click on the Background Mode. This will add in the Background
capability into the iOS app. In the Background Modes section, select the Background fetch
and Remote notifications option. Now, click on the + Capability again and select the Push Notifications capability. We have completed the setup in Xcode. Now, login to your Apple Developer
accounts via developer.apple.com. Once login, select Certificates, Identifiers & Profiles item. Then click on the Identifiers
menu item on the left. Scroll down until you see the application
bundle identifier for JustCodeDict and click on it. Scroll down until you see
the Push Notification capability and make sure it is selected. Next, go back to the previous
screen and select Keys. We need to generate a Key for the server app to send
the notification to the iOS device. The server app in this case is the FCM, as the FCM acts as a proxy for APNs. Click on the + icon. Key in the name for the Key
and click on the Continue button. This will bring you to the result page. Click on the Download button
to download the key file. Please take note that you can
download the key file for one time only. Make sure you don't lose the file, else you need to revoke
the key and regenerate it. Next, we need to use the downloaded key file to configure the FCM so that FCM can push notification to
the iOS device on behalf of APNs. Let's login to the Firebase Console via console.firebase.google.com. Once login, click on the JustCodeDict Project
we had created in Tutorial 5. Click on the iOS app in the project and click on the gear icon
to configure the application. In the Setting page,
click on the Cloud Messaging tab. Under the iOS app configuration section, click on the upload link in the
APNs Authentication Key subsection. Select the key file we had just downloaded and key in the Key ID. You can obtain the Key ID from the
downloaded filename or Apple Developer Console. Click on the Upload button to save the changes. Now, we need to generate
the FCM private key. Click on the Service accounts tab. We will be using Node.js
Firebase Admin SDK to perform the notification sending. Make sure Node.js is selected and click on the Generate
new private key button. This will download the FCM private key file. We will need this file
later to code the admin SDK. We had completed the
setup for APNs and FCM. Before we start coding, we need to understand how the Push
Notification is sent via the FCM Admin SDK and its lifecycle in the device. The FCM Admin SDK has multiple ways
to send a notification to the device. However, in this tutorial, we will concentrate on two ways. The first is to send a notification to an individual
device base on the unique device token ID. The second way is by topic
the device had subscribed to. A Push Notification consists of two parts. They are the notification and data parts. A Push Notification can have both
notification and data part or either one. Now, let us understand the
life cycle of the Push Notification when it reached the device. If the app is not running in the device
or it is running in the background when a Push Notification reached the device, the device will fire the App's
setBackgroundMessageHandler to handle the notification in the background. However, if the Push Notification
only contains data without the notification part, then the setBackgroundMessageHandler
will not be fired if the message priority for the
Android device is not set to the high and content-available flag is
not set to 1 for the iOS device. The setBackgroundMessageHandler
is normally used to save the notification in the device so that the app can access it later if required. Please note that setBackgroundMessageHandler cannot update the app UI
or change the app state. The next handler is the onMessage handler. It will be fired if the app is running in the
foreground when the notification arrived. If this happens, the app needs to
display the notification manually as the device OS will not
display the notification for you. From the table you can see that the
device OS will display the notification only if the app is not running
or running in the background. Take note that if the notification
only contains the data part, then the device OS will not
display the notification at all even the app is not running. The next two handlers I am going to
discuss is to handle the user interaction with the Push Notification. They are the getInitialNotification and
onNotificationOpenedApp handler. The getInitialNotification handler will be fired if the app is not running
when the notification arrived and the user had tabbed on the notification. The onNotificationOpenedApp
handler will be fired if the app is running in the background when the notification arrived and the
user had tabbed on the notification. Please take note that
to test Push Notification, you need to have a physical
iOS or Android device. Push Notification will not work in Simulator. Let's bring out the VS Code
with the project folder opened. The first thing we need to do is to
set the background message handler. Please note take that the background message handler
must be outside the main app component. Open the index.js in the JustCodeDict folder. Import the messaging module from Firebase. Then we invoke the
setBackgroundMessageHandler method to define the background message handler. For now, we just perform a console log on the received message in the handler. Next, in the ReduxApp functional component, we will take in a new
parameter called isHeadless. The isHeadless parameter will be true if the app is launch by iOS
when the Push Notification arrived. In Android, the isHeadless will be undefined. On iOS when a message arrives, the device silently starts the
application in a background state so that the
setBackgroundMessageHandler is triggered. However, the root React
component also gets mounted. This can be problematic for some apps. To get around this problem, the messaging module injects a isHeadless prop to your root component which you can conditionally use to render or do "nothing" if your app is
launched in the background. On Android, a Headless JS task is created and runs separately from
the main React component. This allows your background handler code
to run without mounting your root component. In the functional component, we will return null if isHeadless is true. Now, let's open the App.js file. Import the messaging module from Firebase. In the componentDidMount method under the App class component, we will request the messaging permission. This applies to the iOS device only. On Android, we do not need to
request user permission. However, this method can still
be called on Android devices and it will always resolve permission granted. After checking the permission, we need to invoke the getToken method. This method will return
the unique device token for receiving notification. This token is the "address" the FCM uses to send the
notification to the individual device. In normal practice, we will send the
token back to our server app for storage so that the server app can send a
notification to the device when required. For this tutorial, we will just perform a
console log for the device token. The FCM server will receive the device token
automatically without the need for the app to send the token. Next, we will define
the onTokenRefresh handler. Whenever the device token had changed, the onTokenRefresh will be fired. Similar to the getToken method, we should save the latest
token back to the server but for this tutorial, we will just
log the token into the console. Follow by, we will define
the onMessage handler to handle the received notification when the app is running in the foreground. For now, we will just log the
notification into the console. We had completed is basic coding for
the app to receive push notification regardless the app is running or not. Let's compile and run
the app on the device. The app had launched in the device. From the console log, we will see the
getToken returned the device token. With this token, we can send
a notification to the device. We can send a notification to a device via Firebase Console or the Firebase Admin SDK. I will show you both way but I will
concentrate more on the Admin SDK. Let's bring out the Firebase Console again. On the side menu, scroll down until you see the Cloud
Messaging menu item and click on it. Then on the right of the screen click on the Send your first message button. Specify the notification title and text. You also can include an optional image URL. Click on the Next button and select the android app as the app is running on the android device. Click on the Next button again and select the schedule. We will select "Now" for this test. Click on the Next button again. We will skip the Conversion events by click on the Next button. Now, you will see the Custom Data section. This is where you can specify the
data part for the notification. For now, we just leave it blank. Click on the sound dropdown
list and select enable. Click on the Review button and then click on the Publish button to send the notification. From the app console log, we will see the onMessage handler is fired as the notification had pushed to the device. However, you may wonder why there is no notification shown on the UI? The reason is the app is
running in the foreground, therefore, the app should be responsible
for displaying the notification in the UI. Now, we will add an alert dialog to display
the notification in the onMessage handler. Let's trigger another notification
from the Firebase console. Now, you will see the app pop up an
alert dialog to display the notification. Next, we going to test the push notification when the app is running in the background. However, this time we will try to
use the Firebase Admin SDK to perform the sending of the notification. Let's create an admin folder outside
the JustCodeDict project folder. In the new folder, let's issue
the npm init command. Key in justcodedictadmin
as the package name. Accept the default version
by press the enter key. Key in a description for
the server-side admin app. Accept the default entry point. Leave empty for test command,
git repository, keywords, and author. Accept the default license. Press enter to accept the setting. We had created a blank Node JS application. To use the Firebase Admin SDK, we need to install the
firebase-admin npm module. Issue the npm install firebase-admin --save command
to install the module. Remember the FCM private key file we
had download from the Firebase console? We will need the file for the admin app. Copy the file from the download
folder to the admin folder. Now, bring out the VS Code and create an index.js file
under the admin folder. Import the Firebase admin module and the FCM private key file as shown. Please take note that the filename for the FCM
private key file will be difference based on the project you created
in your own Firebase Console. Next, we need to initialize the SDK
by invoking the initializeApp method. Within the method, we will provide the credential and
databaseURL parameter as shown. Please take note that your databaseURL
will difference from this tutorial. The first part of the URL
is your Firebase Project ID which you can get from the Firebase Console, or the filename of the key file. Follow by, we will create the
message payload as shown. First is the notification part, it contains the title, body,
and optional imageUrl. Next, is the data part for the notification. We will leave it blank for now. The next part is the notification option for the android device. We will turn on the notification sound and set it as default. We will do the same thing for the
iOS device under the apns payload. The last part of the message payload is the device token which this
message is targeted to. We will copy the device token from
the console log and paste it into here. We had done for the message payload. Now, we will proceed to send the
notification by invoking the send method from the Admin SDK as shown. Now, let us run the admin app to
send the notification to the device. In the terminal screen, let's issue the node index.js
command and press enter. We will see the alert dialog
pop up on the device screen. In the mobile app console log, we will see the log for the
newly arrived message too. I had demonstrated how
to send push notification from Firebase Console
and via the Admin SDK. We also demonstrated how the mobile app
receives and displays the notification when the app is running in the foreground. Now, let us try to send
a notification to the device when the mobile app is
running in the background. Let's minimized the mobile app in the device. In the admin app terminal screen, let's issue the same command
again to send the notification. We will see the notification bar
display by the device OS. The console log will also display the
message is handled in the background, which is the setBackgroundMessageHandler. So far we had implemented the onMessage
and setBackgroundMessageHandler method. There are two more handlers
we need to implement. They are the onNotificationOpenedApp and getInitialNotification handlers. Let us define the onNotificationOpenedApp
handler just below the onMessage handler. The onNotificationOpenedApp handler takes in an arrow function with the remoteMessage parameter as shown. This handler will be fired when the application is running in the
background when the notification arrives and the user had
tapped on the notification bar. For now, we will just perform a
console log on the received message. Next, we will implement the same logic for getInitialNotification handler. This handler will be fired
when the application is quit when the notification arrives and the
user had tapped on the notification bar. Let's reload the application in the device. We will minimize the app into the background. At the admin terminal screen, let's send the notification again. Tap on the notification on the status bar and you will see the console log
displayed that the notification had caused the app to
open from background state. Let's quit the app in the device and trigger another notification
in the admin terminal. Tap on the notification again. This time you will see
the console log displayed that the notification had caused the
app to open from quit state. I had covered the four main handlers for handling the push notification nd they are the
setBackgroundMessageHandler, onMessage, onNotificationOpenedApp, and getInitialNotification handler. Till now, I had shown you how to send a
notification to a device via the device token. Next, I am going to show you how to send a notification to
multiple devices at once by using the notification topic. This is useful when you want to
broadcast information to your end users instead of sending notification one by one. Before the app in the device can
receive notification by topic, the app needs to subscribe
to the specific topic. Open the App.js file in
the JustCodeDict folder. Just above the onMessage handler, we will add in the topic subscription logic. We will create a topic called "dailyword". Assumed that our admin app
will send a daily notification of a word to our end user. We had completed the topic subscription. Now, let's switch back to the
admin app index.js file. We will change the title and
body of the notification. At the end of the message payload, we will replace the token to the topic.
That's all! Let's run the app on both
Android and iOS devices. The application had
launched on both devices. Let's try to send the topic notification by issuing
the same command in the admin app terminal. You will see that both devices
will receive the notification. Sending notification by topic allows us to
broadcast messages to multiple devices at once. So far we only send notification
without the data part. Notification without the data part is mainly
used for displaying messages to end-user. This limits the capability
of the push notification. Now, I am going to show you how to make use of the
notification data part. We will enhance the dailyword topic
notification we had created just now. Let's open the index.js under
the admin app folder. In the message payload
under the data section, we will add in two fields. The first field is the msgType. This field indicates the type of notification so that the mobile app knows
how to handle the message. For now, we will set the msgType to "Search". This instructs the mobile app to
perform a word definition lookup when the end-user tap
on the received notification. The second field is the word field, it contains the word for the
mobile app to perform the lookup via Oxford dictionary API. That's all for the admin app index.js file. Now, we need to modify the mobile app to respond accordingly to the
received push notification. Let's define the logic first
before we start coding. When the device received
the dailyword notification with the msgType equal to "Search", the mobile app will navigate to the
Search page and perform a word lookup via the Oxford dictionary API based on the word in the data part. Let's open the App.js
in the JustCodeDict folder. We will import the pageActions require
for the mobile app to perform the word lookup. We will also create the
navigation reference as shown. The navigation reference is
used to navigate the app to the search page regardless of
which page the app is currently in. Scroll to the render method and add in the navigation reference in the NavigationContainer ref property. Without the navigation reference, the App class component will not be able to navigate within the app. It is because the App class component is not under any of the
navigator components. Next, we will implement a method
called forwardToSearchPage. This method will take in the word parameter and call the pageSearchSetUserWord
action method to set the word in the Redux state. Then, it will use the navigation reference to navigate the app to the Search page and pass in a route parameter autoSeach to instruct the Search page
to perform a word lookup without the user to press the Search button. Now, let's open the index.js under
the src/screen/search folder. We first import the useRoute
from React Navigation so that we can get the
route parameter autoSeach. Scroll to the bottom of the file and we will use the useRoute hook to get the route and pass it into the
ReduxSearch component as shown. Next, we will implement the
componentDidUpdate method. In it, we will check if the autoSeach
route parameter is defined or not. If it is defined and the value is true, then we will set it to false
and perform a word lookup by invoking the onSearch method. That's all for the search index.js file. Back the App.js file, we will create a new method
called processNotification method. The purpose of creating this method is to
centralize the notification processing logic. Currently, we have four handlers
to handle the notification, if we code the notification
processing logic on each of the handle, it will be difficult for us to
maintain the source code if we have more msgType
notification to process. To be a good programmer, we don't
just write code to get things to work. But also make our code efficient
and easy to maintain. If you agreed with my viewpoint, please click on the Like button
of this tutorial video. The processNotification method takes in the remoteMessage
and fromBackground parameter. The remoteMessage is the received notification and the fromBackground parameter indicate if the notification is handled
by the onNotificationOpenedApp or getInitialNotification handlers. At the beginning of the method, we will define the title, body,
and alertBtns variables. Then we check if the
remoteMessage is defined or not. We further check if remoteMessage
notification part is defined or not. If defined, we will get the
title and body as shown. Next, we will check the data part
of remoteMessage is define or not. If defined, then we will check if the notification is
handled by the background handler. If true, we create a switch statement to handle different msgType. For now, we only have one case
which is the "Search". We will invoke the forwardToSearchPage
method by passing in the word in the data part as the parameter so that the app will navigate to the
Search page and perform a word lookup. Next, we will check if the notification
is to be handled by the foreground app. If true, then we create a switch statement to handle different msgType. For now we also only have one
switch case which is the "Search". In it, we will create two
alert buttons in the array. The first button will invoke
the forwardToSearchPage method similar to the background message. The second button will
close the alert dialog box. The last part of the code is to check if the notification arrived when the app is in the foreground. If that is the case, then we need to display an alert dialog box with the title, body, and
alert buttons defined above. Now, we need to invoke
the processNotification method from the onMessage handler onNotificationOpenedApp handler and getInitialNotification handler. We had completed all the changes. Now, let's reload the
application from all devices. Navigate the app to the Setting page. In the admin app terminal, issue the node index.js command to send the notification with data. We will see the mobile app will pop up an alert dialog box showing the title and body of the notification. When we tap on the View button, the app will navigate to the search page and perform the word lookup automatically. We had seen how a
notification with data work when the mobile app is
running in the foreground. Now, let us reload the app, navigate to the Setting page, and minimize the app on both devices. In the admin app terminal, issue the same command to send
the notification with data again. You will see the device OS
displayed the notification instead of the mobile app. Let's tap on the notification and we will see that the
device will launch the app and navigate to the search page to
perform the word lookup automatically. We had covered push notification with only notification part and with
both notification and data part. However, do you know that we can create
a "Silent" notification with only the data part? Let me show you how to
use a "Silent" notification to inform the app user on the app update. Let's duplicate the index.js
in the admin app folder and rename it as versionUpgrade.js. Open the versionUpgrade.js file, we will remove the entire notification
part from the message payload. We will change the
msgType to "VersionUpgrade". We replaced the word to nextVer with the value of 2. Then we specify the URL to update the app for both iOS and Android as shown. The link specified here will link to another
app that I had developed previously. We will remove the android
notification setting in the message payload and add in the priority setting to
make the notification "Silent" in the Android device. We will also do the same for iOS by removing the sound in the aps payload. However, we need to specify a new setting called content-available
with a value equal to 1 in the aps payload. Without this setting, the iOS device will not fire the setBackgroundMessageHandler and the message will not be processed as it is a Silent notification without UI. Last but not least we need to change the
topic to "version_upgrade" in the message payload. We had completed the admin app portion. Now, we need to modify the mobile app to handle the version upgrade message. We need to install an npm module that allows the app to get
its existing version info. Issue the yarn add
react-native-version-number in the JustCodeDict terminal screen
and press enter. The installation had completed. Let's open the index.js under
the JustCodeDict folder. In the setBackgroundMessageHandler, we will check if the incoming message
is for version upgrade or not. If it is, then we will save it
into the device storage with the key nextVer. This allows the app to access the
notification in the subsequent launch. Now, open the App.js file. We will create a method
called checkVersionUpdate to check is there any version
upgrade message in the device storage. If have, and the next version number is
greater than the existing version number, then it will display an alert dialog box to inform the end-user
about the version upgrade. When the user taps on the Update button, it will invoke the Linking.openURL method to redirect the user to the respective App or Play Store depending on the OS type. We will invoke checkVersionUpdate method in the componentDidMount method as shown. The checkVersionUpdate method is used to handle the
version upgrade notification that reached the device when the app is
not running or running in the background. Now, we also need to handle
the version upgrade notification reached the device when the
app is running in the foreground. To do that, let's scroll to the
processNotification method. Under the switch statement that
handles the foreground message, we will add in the new case "VersionUpgrade". In it, if the next version is greater
than the existing version, then we will prepare the title, body, and action buttons
for the alert dialog box similar to the checkVersionUpdate method. We had completed all the changes. Let's reload the application on both devices. Please take note that in iOS for the setBackgroundMessageHandler
to work properly, we need to compile the app
in the released configuration. The app had reloaded on both devices. We will first test the Silent notification
when the app is running in the foreground. In the admin app terminal screen, let's issue the
node versionUpgrade.js command. We will see the mobile app
display an alert dialog box indicating there is a version upgrade. This dialog box is fired via
the processNotification method. Tap on the Update button and you will see that the
iOS device will launch the App Store and the Android device
will launch the Play store. Now, let's quit the mobile app in both devices to test the Silent notification when the app is not running at all. In the admin app terminal screen, issue the same command
again and press enter. We will wait for a few seconds to ensure the notification
is delivered to the device as there is no notification bar at all. Now, let launch the app
from the devices again and you will see the
version upgrade dialog box. This dialog is fired via the
checkVersionUpdate method instead of the processNotification method. Tap on the Update button and
you will see the same effects. We had come to the end of this tutorial. Today, I had shown you how to enable and handle Push Notification within your app. I also had shown you how Push Notification can instruct the app to perform actions. Besides, I also had shown you how to
send messages via the Firebase Console and the Firebase Admin SDK. For more information on
the Firebase Admin SDK, please visit the firebase.google.com. And for more information on the
React Native Firebase client SDK, please visit the rnfirebase.io. If you have any questions regarding this tutorial, please leave a comment below. You can follow the link to get the source
code for this tutorial on our Github page. If you find our video useful, do support us by like our video, subscribe to our channel, and click on the notification bell! Thanks for watching, bye!