React Native, Local, Scheduled, Push Notification With Firebase
Vikrant Negi
Posted on July 4, 2019
With ever going increase in app usage, the app developers try to find new ways to keep their user engaged with their apps. Push notifications are one way to keep your users engaged and informed.
Push notifications are the communications channel used by apps to drive user re-engagement and retention. Push notification technology has come a long way from being a single messages delivery system to a rich and interactive medium.
There are two types of notifications, remote and local notifications.
Remote Notifications
With remote notifications, you use one of your company’s servers to push data to user devices via the Apple Push Notification service or FCM.
Local Notifications
Both Android and IOS support the ability to trigger notifications from your application locally. These can either be displayed immediately, or scheduled to be displayed at a later date.
In this article we will be using local notifications feature to send daily a reminder to the user at a particular time every day.
Prerequisites
This tutorial requires basic knowledge of React Native. To set up your development machine, follow the official guide here.
To implement push notifications in React Native application, we are going to use the react-native-firebase.
React Native Firebase has Notifications module that supports for both remote (FCM) and local notifications.
To make sure we are on the same page, the following are the versions used in this tutorial:
- Node v10.15.0
- npm 6.4.1
- yarn 1.16.0
- react-native 0.59.9
- react-native-firebase 5.2.3
Getting Started
To create a new project using react-native-cli
, type the following in terminal:
$ react-native init localReminders
$ cd localReminders
Install React Native Firebase
Install react-native-firebase
by following installation instructions here.
Make sure you have completed both iOS and Android setup.
Install Modules
React Native Firebase only provides your application with access to Core features.
To user notification in our react native app, we'll need to also install the Cloud Messaging and Notifications modules.
Install Cloud Messaging by following the instructions here.
Install Notifications by following the instructions here.
Again, make sure you followed the steps for both iOS and Android.
Initial code setup
In your App.js
file add these imports:
import React, { Component } from "react";
import { Alert } from "react-native";
import firebase from "react-native-firebase";
import Dashboard from "./src/Dashboard";
Create an empty Dashboard.js
file in your src
folder. We'll fill this with code in later part of the tutorial.
Now create a class
component called App
as follow:
export default class App extends Component {
componentDidMount() {
// Create notification channel required for Android devices
this.createNotificationChannel();
// Ask notification permission and add notification listener
this.checkPermission();
}
createNotificationChannel = () => {};
checkPermission = async () => {};
render() {
return <Dashboard />;
}
}
We've created a few helper methods in this class component that we called on componentDidMount()
lifecycle method. In render, we'll return the Dashboard
component.
Let's review and add code to these methods and see what they do and why do we need them.
Create Android Notification Channel
As of Android 8.0 (API Level 26), notifications must specify a Notification Channel or they will not appear.
To allow React Native Firebase to work seamlessly across all versions of Android, you will need to create a channel before you can display a notification. This block of code can be re-run multiple times, so it is safe to do it each time your application starts.
To create this notification channel we created a custom helper method createNotificationChannel()
. Update it with the following:
createNotificationChannel = () => {
// Build a android notification channel
const channel = new firebase.notifications.Android.Channel(
"reminder", // channelId
"Reminders Channel", // channel name
firebase.notifications.Android.Importance.High // channel importance
).setDescription("Used for getting reminder notification"); // channel description
// Create the android notification channel
firebase.notifications().android.createChannel(channel);
};
Android channel accept three parameters channelId
, name
and importance
.
For full reference documentation, please see AndroidChannel and AndroidNotifications.
Notification Permission and Listener
Before we can send any notification we need to make sure we have the notification permission and then, when we have that permission we can add a notification listener. This notification listener will listen for any notification and return us with the notification
when received.
Update your checkPermission()
method with the following:
checkPermission = async () => {
const enabled = await firebase.messaging().hasPermission();
if (enabled) {
// We've the permission
this.notificationListener = firebase
.notifications()
.onNotification(async notification => {
// Display your notification
await firebase.notifications().displayNotification(notification);
});
} else {
// user doesn't have permission
try {
await firebase.messaging().requestPermission();
} catch (error) {
Alert.alert(
"Unable to access the Notification permission. Please enable the Notification Permission from the settings"
);
}
}
};
When the notification listener receives a notification, we call displayNotification()
method with the notification
received which will display the notification.
We can now receive and show the notification. Now its time to schedule a local notification which will fire at some point in the future.
Dashboard Screen
We are going to create a Dashboard screen which will have a switch to enable and disable notifications and a time picker to set time to receive notifications. It will look something like below.
To make this UI Screen we'll add few third party helper libraries.
- react-native-elements - UI component library
- moment - Handling Date Object
- react-native-modal-datetime-picker - A React-Native datetime-picker for Android and iOS
Let's start with adding the required imports:
import React, { Component } from "react";
import { Platform, StyleSheet, Text, SafeAreaView, View } from "react-native";
import { ListItem } from "react-native-elements";
import firebase from "react-native-firebase";
import DateTimePicker from "react-native-modal-datetime-picker";
import moment from "moment";
Now we'll create and default export Dashboard
class component.
Now, add some local states:
state = {
enableNotification: true,
isDateTimePickerVisible: false,
notificationTime: moment({ hour: 17 })
};
Now we want to set reminder as soon as user lands on the dashboard, so we'll create and call a setReminder()
method on componentDidMount()
lifecycle method:
componentDidMount() {
this.setReminder();
}
setReminder = async () => {
const { notificationTime, enableNotification } = this.state;
if (enableNotification) {
// schedule notification
firebase.notifications().scheduleNotification(this.buildNotification(), {
fireDate: notificationTime.valueOf(),
repeatInterval: 'day',
exact: true,
});
} else {
return false;
}
};
In setReminder()
method first we use notificationTime
and enableNotification
state.
If enableNotification
is true we schedule the notification using scheduleNotification()
method.
The scheduleNotification()
has two parameters, notification
and schedule
.
For notification
we'll call another custom method buildNotification()
which will return notification and, in schedule
we'll pass an object with fireDate
, repeatInterval
and exact
keys.
The fireDate
is the date when the notification should first be shown, in milliseconds. For repeatInterval
we'll use day
, as we want the notification to be shown everyday. The exact
option is Android only and it denotes if the fireDate
should be respected exactly, i.e. for reminders, or if it can deviate slightly to save battery.
In else we'll just return false
.
Now, we'll add buildNotification()
method which will build a notification when a notification is received:
buildNotification = () => {
const title = Platform.OS === "android" ? "Daily Reminder" : "";
const notification = new firebase.notifications.Notification()
.setNotificationId("1") // Any random ID
.setTitle(title) // Title of the notification
.setBody("This is a notification") // body of notification
.android.setPriority(firebase.notifications.Android.Priority.High) // set priority in Android
.android.setChannelId("reminder") // should be the same when creating channel for Android
.android.setAutoCancel(true); // To remove notification when tapped on it
return notification;
};
Let's add some helper method for the notification switch
and time picker. These will be used by their respective components to set local states which will then later be used:
enableNotification = value => {
this.setState({
enableNotification: value
});
};
showDateTimePicker = () => {
this.setState({ isDateTimePickerVisible: true });
};
hideDateTimePicker = () => {
this.setState({ isDateTimePickerVisible: false });
};
handleDatePicked = date => {
this.hideDateTimePicker();
this.setState({
notificationTime: moment(date)
});
};
Finally, the render()
which we'll return the UI of the dashboard:
render() {
const { enableNotification, isDateTimePickerVisible, notificationTime } = this.state;
return (
<SafeAreaView style={styles.container}>
<View style={styles.cardTitleView}>
<Text style={styles.cardTitle}>Add Reminder</Text>
</View>
<ListItem
title="Notification"
bottomDivider
titleStyle={styles.titleStyle}
switch={{ onValueChange: this.enableNotification, value: enableNotification }}
/>
<ListItem
title="Time"
titleStyle={styles.titleStyle}
onPress={this.showDateTimePicker}
rightElement={<Text style={{ opacity: 0.7 }}>{moment(notificationTime).format('LT')}</Text>}
/>
<DateTimePicker
isVisible={isDateTimePickerVisible}
onConfirm={this.handleDatePicked}
onCancel={this.hideDateTimePicker}
mode="time" // show only time picker
is24Hour={false}
date={new Date(notificationTime)}
titleIOS="Pick your Notification time"
/>
</SafeAreaView>
);
}
Time to sprinkle in some styles to make UI more appealing.
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#EEEFF0"
},
cardTitleView: {
paddingHorizontal: 15,
paddingTop: 15,
paddingBottom: 8
},
cardTitle: {
fontSize: 15,
color: "#585858",
fontWeight: "600"
},
titleStyle: {
fontSize: 20,
color: "#585858"
}
});
That's it. We are done with development. In the next section, we'll test it out in an iOS simulator.
Running the app
Test the app by enabling notification and setting time 1 min in the future.
Note: Sometimes the notification may not show at the exact time. Please wait for a whole minute for notification to appear.
Conclusion
We can now schedule daily local push notification in our React Native app for both iOS and Android.
Apart from firebase, there are other libraries you can use to implement local push notification like react-native-push-notification.
Here is the Github repo local-reminders.
Originally published on Medium
PS: Cover image by Jamie Street on Unsplash
Posted on July 4, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.