Push Notifications React Native
Push notifications are great for engage users to your app, almost all apps use them, so it’s an important feature you must know how to implement it.
How push notifications work internally?
What we have to understand first of all is that push notifications work thanks to Firebase and APNs (Apple Push Notification service), which are two services that are able to send push notifications to our devices (Android and iOS).
Each device (iOS and Android) has its own device push token, basically it’s a unique identifier for the device, with this token and using the services mentiones above, we can send a push notification to the device.
Configuring a React Native app for receiving notifications
In this tutorial we are going to configure the React Native app for receiving push notifications in Android. Te code written is going to work for both Android and iOS, but for iOS we need to configure another steps that we will cover in another tutorial.
Let’s start by creating a React Native app with the command:
npx react-native init notificationsApp
Then you have to install the Firebase required libraries (see this link if you want to get more information about Firebase with React Native).
First of all we need the Firebase app module, because it’s required to install any other Firebase service, to do that run the following command:
npm install --save @react-native-firebase/app
Now we have to make some configurations in Firebase console.
Let’s start by configuring the Firebase Console
Go to the firebase console and create a project (you must be logged into your google account)
Select the Create a project button, then enter your project name (this is the name for your firebase project, it’s not related to your mobile app).
You can enable analytics if you want, but for now we are going to disable them.
Finally click on Create project.
Create Android app in Firebase
Now we have the firebase project created, we need to create the app instances for the frontend apps we want to send notifications, we could create one for Android and one for iOS, or even two for Android and one for iOS, it depends on which apps do you want to enable push notifications from this Firebase project.
Let’s create just one Android app. Click the Android icon, then copy your Android package name of the app you want to receive push notifications. You can also add an optional App nickname to identify your app in firebase.
Then click on Register app.
After that, you have to download the google-services.json
file, this file contains the information your app needs to identify the Firebase project you have created.
Then, click on Next, Next again, and then click on Continue to console.
Configure React Native Android firebase module
We have to make some configurations in our Android generated project, in order to make the native Android Firebase library work propertly with the React Native code.
Copy the google-services.json
file to the /android/app folder.
Now we have to link this file with our Android native code, to do that copy the following line of code in the directory /android/build.gradle:
classpath 'com.google.gms:google-services:4.3.15'
Finally we have to execute the Firebase plugin, to do that, copy the following line of code in the directory /android/app/build.gradle
apply plugin: 'com.google.gms.google-services'
Now our Android React Native app is able to receive push notifications, what we need to do next is to handle those notifications.
Handle push notifications
The code we are going to write in this part works for both Android and iOS, because we are not going to modify more native code.
Now, in our React Native project, we need to install the firebase messaging library, to do that run the following command:
npm i @react-native-firebase/messaging
(for installing the iOS libraries you must run also npx pod-install)
Ask the user permission and listen to push notifications
For receiving push notifications the user must give permissions to the app.
There are 3 types of push notifications:
- Foreground: When the app is open and in view.
- Background: When the app is open but not in view (for example, the user is in another app or in the homescreen)
- Quit: When the app is closed or the device is locked.
To handle the different types of push notifications, we are going to create a custom hook: usePushNotification
import React from 'react';
import messaging from '@react-native-firebase/messaging';
import {PermissionsAndroid, Platform} from 'react-native';
const usePushNotification = () => {
const requestUserPermission = async () => {
if (Platform.OS === 'ios') {
//Request iOS permission
const authStatus = await messaging().requestPermission();
const enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (enabled) {
console.log('Authorization status:', authStatus);
}
} else if (Platform.OS === 'android') {
//Request Android permission (For API level 33+, for 32 or below is not required)
const res = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS,
);
}
}
const getFCMToken = async () => {
const fcmToken = await messaging().getToken();
if (fcmToken) {
console.log('Your Firebase Token is:', fcmToken);
} else {
console.log('Failed', 'No token received');
}
};
const listenToForegroundNotifications = async () => {
const unsubscribe = messaging().onMessage(async remoteMessage => {
console.log(
'A new message arrived! (FOREGROUND)',
JSON.stringify(remoteMessage),
);
});
return unsubscribe;
}
const listenToBackgroundNotifications = async () => {
const unsubscribe = messaging().setBackgroundMessageHandler(
async remoteMessage => {
console.log(
'A new message arrived! (BACKGROUND)',
JSON.stringify(remoteMessage),
);
},
);
return unsubscribe;
}
const onNotificationOpenedAppFromBackground = async () => {
const unsubscribe = messaging().onNotificationOpenedApp(
async remoteMessage => {
console.log(
'App opened from BACKGROUND by tapping notification:',
JSON.stringify(remoteMessage),
);
},
);
return unsubscribe;
};
const onNotificationOpenedAppFromQuit = async () => {
const message = await messaging().getInitialNotification();
if(message) {
console.log('App opened from QUIT by tapping notification:', JSON.stringify(message));
}
};
return {
requestUserPermission,
getFCMToken,
listenToForegroundNotifications,
listenToBackgroundNotifications,
onNotificationOpenedAppFromBackground,
onNotificationOpenedAppFromQuit,
};
};
export default usePushNotification;
This hook has 6functions:
- requestUserPermissionHandler: this function basically asks the user for permissions to receive push notifications. In iOS is required you ask them, but on Android API level 32 and below, you do not need to request user permission, you have to ask in API level 33+.
- getFCMToken: with this function we get the device push token of the current device.
- listenToForegroundNotifications: this function listen for notifications, whenever a notifications is received with the app opened and in view (foreground).
- listenToBackgroundNotifications: this function listen for notifications, whenever a notifications is received with the app opened and in background (in homescreen or in other app).
- onNotificationOpenedAppFromBackground: when a notification is arrived and the app is in background, if the user opens the app by tapping the notification, the callback of this function is going to be executed.
- onNotificationOpenedAppFromQuit: when a notification is arrived and the app is in closed (quit), if the user opens the app by tapping the notification, this function receives the notification, and you can do whatever you want with the data.
With the custom hook done, you will need to call these functions in your app.
import React, {useEffect} from 'react';
import {View, Text} from 'react-native';
import usePushNotification from './src/hooks/usePushNotification';
const App = () => {
const {
requestUserPermission,
getFCMToken,
listenToBackgroundNotifications,
listenToForegroundNotifications,
onNotificationOpenedAppFromBackground,
onNotificationOpenedAppFromQuit,
} = usePushNotification();
useEffect(() => {
const listenToNotifications = () => {
try {
getFCMToken();
requestUserPermission();
onNotificationOpenedAppFromQuit();
listenToBackgroundNotifications();
listenToForegroundNotifications();
onNotificationOpenedAppFromBackground();
} catch (error) {
console.log(error);
}
};
listenToNotifications();
}, []);
return (
<View>
<Text>Push Notification APP</Text>
</View>
);
};
export default App;
Another important point is that you might want to execute a callback when a notification is received (like fetching some data or someting else), but the functions we add to our custom hooks are executed when the app is opened, not with the app closed. To execute this callback, we have to execute the following code outside of your application logic as early as possible (in this case, inindex.js
)
Test push notifications
We can test push notifications using a generated server key
that we can find in the firebase project we created earlier, to do that, go to the firebase console, then click on the gear icon, and click on Project settings.
Then go to Cloud Messaging tab and click on the 3 dots, and then in Manage API in Google Cloud Console.
A new browser tab is going to be opened, and then click on ENABLE.
Then go to the previous tab, refresh the page, and you are going to see a Server key, this server key is used to send push notifications to the apps you have created in you firebase project (like the Android one we created earlier).
Now that we have the server key, we must open the app in the Android simulator, and then copy the FCM push token from the console, then go to the FCM Tester page, and try to send push notifications.
Then you will be able to receive notifications.
Here we see how the app is closed, and the notification is received and logged in the console, this is thanks to the listener we add previously in the index.js file.