Implement Push notifications for Android apps with React Native

Published on Nov 19, 2019

9 min read

REACT-NATIVE

Relevant Push notifications are a great way to boost a user's engagement towards an application. According to some analysis, push notifications increase app engagement by 88%. It’s also curious to see that the click-through rate for push notifications in Android (4.06%) is much higher than in iOS (1.7%).

In this tutorial, you are going to learn how to implement push notifications as an app feature using React Native and Firebase. I will be testing out the notification feature on an Android device, but you can go ahead and try it out on iOS yourself.

There are two main ways you can send push notifications to your app users: local and remote. Local notifications are sent from a React Native application, while remote push notifications are sent from the server or a push notification service such as Google's Cloud Messaging Service (GCM). We will explore both approaches.

Requirements

🔗

To follow this tutorial, please make sure you have the following installed on your local development environment and have access to the services mentioned below:

  • Nodejs (>=10.x.x) with npm/yarn installed.
  • react-native-cli
  • Windows/Linux users must be running an Android emulator or a real device via USB
  • Active Firebase project

To know more about how to set up a development environment for React Native using react-native-cli, please refer to the official documentation.

You can find the complete code for this tutorial at this GitHub repository.

Install and Set Up react-native-push-notifications

🔗

The react-native-push-notifications library helps you set up controllers to consume local or remote notifications for iOS and Android devices. To begin, follow the instructions from the terminal window. Create a new React Native project and then install this library.

react-native int RNnotifications
cd RNnotifications
yarn add react-native-push-notification

For iOS devices, this library depends on the manual installation instructions mentioned at PushNotificationIOS - an API that is maintained by react-native-community.

For Android devices, you are going to make the following edits in the appropriate files mentioned below. First, open the file android/build.gradle and add the following:

1buildscript {
2 ext {
3 // add the following two lines
4 googlePlayServicesVersion = "16.1.0" // default: "+"
5 firebaseVersion = "17.3.4" // default: "+"
6 }
7 repositories {
8 google()
9 jcenter()
10 }
11 dependencies {
12 // add the following dependency
13 classpath 'com.google.gms:google-services:4.3.2'
14 }
15}

Next, open android/settings.gradle and add the following before include ':app'.

1include ':react-native-push-notification'
2project(':react-native-push-notification').projectDir = file('../node_modules/react-native-push-notification/android')

Do note that, if you are not looking forward to using remote notifications, you can ignore the above step. However, the following step is important for both types of notifications to work. Open the android/app/src/main/AndroidManifest.xml file. Before the <application> tag, add the following.

1 <uses-permission android:name="android.permission.WAKE_LOCK" />
2 <permission
3 android:name="${applicationId}.permission.C2D_MESSAGE"
4 android:protectionLevel="signature" />
5 <uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
6 <!-- < Only if you're using GCM or localNotificationSchedule() > -->
7
8 <uses-permission android:name="android.permission.VIBRATE" />
9 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

Then, inside the <application> tag (and without deleting any existing tags) add:

1 <meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_name"
2 android:value="YOUR NOTIFICATION CHANNEL NAME"/>
3 <meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_description"
4 android:value="YOUR NOTIFICATION CHANNEL DESCRIPTION"/>
5 <!-- Change the resource name to your App's accent color - or any other color you want -->
6 <meta-data android:name="com.dieam.reactnativepushnotification.notification_color"
7 android:resource="@android:color/white"/>
8
9 <!-- < Only if you're using GCM or localNotificationSchedule() > -->
10 <receiver
11 android:name="com.google.android.gms.gcm.GcmReceiver"
12 android:exported="true"
13 android:permission="com.google.android.c2dm.permission.SEND" >
14 <intent-filter>
15 <action android:name="com.google.android.c2dm.intent.RECEIVE" />
16 <category android:name="${applicationId}" />
17 </intent-filter>
18 </receiver>
19 <!-- < Only if you're using GCM or localNotificationSchedule() > -->
20
21 <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationPublisher" />
22 <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver">
23 <intent-filter>
24 <action android:name="android.intent.action.BOOT_COMPLETED" />
25 </intent-filter>
26 </receiver>
27 <service android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationRegistrationService"/>
28
29 <!-- < Only if you're using GCM or localNotificationSchedule() > -->
30 <service
31 android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerServiceGcm"
32 android:exported="false" >
33 <intent-filter>
34 <action android:name="com.google.android.c2dm.intent.RECEIVE" />
35 </intent-filter>
36 </service>
37 <!-- </ Only if you're using GCM or localNotificationSchedule() > -->
38
39 <!-- < Else > -->
40 <service
41 android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService"
42 android:exported="false" >
43 <intent-filter>
44 <action android:name="com.google.firebase.MESSAGING_EVENT" />
45 </intent-filter>
46 </service>

Lastly, go to android/app/src/res/values/colors.xml. If the file does not exist, create it. This file determines the color of the notification on an Android device. For example, the notification can be white:

1<resources>
2 <color name="white">#FFF</color>
3</resources>

Note: To use this library with Expo, you have to eject the Expo SDK app.

Configure Local Push Notifications

🔗

In this section, you are going to write a configure function such that, when a button is pressed, a local notification is triggered. Create a new file inside src/services/LocalPushController.js. Start by importing PushNotification from the library you initialized in the previous step.

1import PushNotification from 'react-native-push-notification';

Add PushNotification.configure() to the file. This accepts an object with a required method onNotification. This method handles what happens after the notification is opened or received. Since it is a required method, it has to be invoked whether the notification is local or remote. The demo application only invokes a console statement stating the properties of the local notification object used in the current demo app.

1PushNotification.configure({
2 // (required) Called when a remote or local notification is opened or received
3 onNotification: function (notification) {
4 console.log('LOCAL NOTIFICATION ==>', notification);
5 },
6
7 popInitialNotification: true,
8 requestPermissions: true
9});

Next, export LocalNotification in the snippet below which gets invoked when a button pressed by the user or as the value of the onPress attribute.

1export const LocalNotification = () => {
2 PushNotification.localNotification({
3 autoCancel: true,
4 bigText:
5 'This is local notification demo in React Native app. Only shown, when expanded.',
6 subText: 'Local Notification Demo',
7 title: 'Local Notification Title',
8 message: 'Expand me to see more',
9 vibrate: true,
10 vibration: 300,
11 playSound: true,
12 soundName: 'default',
13 actions: '["Yes", "No"]'
14 });
15};

PushNotification.localNotification has plenty of properties for each mobile platform (such as iOS or Android). From the above snippet, properties like vibrate, vibration, bigText, subText are Android only. However, properties like actions, title, message, playSound & soundName are cross-platform.

Import this method in the App.js file. Import LocalNotification from the src/services/LocalPushController.js file. Then, inside the functional App component, add a handler method handleButtonPress to invoke only when the user presses the button.

1import React from 'react';
2import { Text, View, Button, StyleSheet } from 'react-native';
3import { LocalNotification } from './src/services/LocalPushController';
4
5const App = () => {
6 const handleButtonPress = () => {
7 LocalNotification();
8 };
9
10 return (
11 <View style={styles.container}>
12 <Text>Press a button to trigger the notification</Text>
13 <View style={{ marginTop: 20 }}>
14 <Button title={'Local Push Notification'} onPress={handleButtonPress} />
15 </View>
16 </View>
17 );
18};
19
20const styles = StyleSheet.create({
21 container: {
22 flex: 1,
23 justifyContent: 'center',
24 alignItems: 'center'
25 },
26 buttonContainer: {
27 marginTop: 20
28 }
29});
30
31export default App;

Now, from a terminal window, run react-native run-android. Make sure you have a device connected via USB and have USB debugging enabled, or you can test on an Android Emulator.

The output of the above code snippet should look like this:

ss1

When the button is pressed, it displays the notification, vibrates the device, and plays a default notification sound.

ss2

Expanding the notification displays the message from bigText. Pressing the notification results in triggering the console statement from onNotification method.

ss3

You can add scheduled notifications by using the PushNotification.localNotificationSchedule(details: Object) method or you can repeat notifications after a particular time too. Read how to do this or add more customizations in the module's official docs.

Configure Remote Notifications

🔗

To test out how remote notifications work, let us integrate the Cloud Messaging Service using Firebase. To follow the steps below, make sure you have an active Firebase project.

From the main Dashboard page, go to Project Settings. In the Your apps section, click on Add app and set up a new Android app.

Next, it will ask you to register the application.

ss4

Download the file google-services.json and save it at the location android/app/ inside your React Nativ project.

ss5

Then, open the android/app/build.gradle file and add the following.

1dependencies {
2 implementation project(':react-native-push-notification')
3 // ... rest remains same
4}
5
6// at the end of the file, add
7apply plugin: 'com.google.gms.google-services'

Next, create a new service file called RemotePushController.js inside the src/services/ directory. This file contains all the configuration to handle a remote push notification. Inside the mandatory onNotification method, let us again display the result of the remote notification in the console.

It also requires a mandatory Android property called senderID. This can be fetched form Project Settings > Cloud Messaging.

ss7

1import React, { useEffect } from 'react';
2import PushNotification from 'react-native-push-notification';
3
4const RemotePushController = () => {
5 useEffect(() => {
6 PushNotification.configure({
7 // (optional) Called when Token is generated (iOS and Android)
8 onRegister: function (token) {
9 console.log('TOKEN:', token);
10 },
11
12 // (required) Called when a remote or local notification is opened or received
13 onNotification: function (notification) {
14 console.log('REMOTE NOTIFICATION ==>', notification);
15
16 // process the notification here
17 },
18 // Android only: GCM or FCM Sender ID
19 senderID: '256218572662',
20 popInitialNotification: true,
21 requestPermissions: true
22 });
23 }, []);
24
25 return null;
26};
27
28export default RemotePushController;

Also, the Cloud Messaging service works based on using a Token between the app and the notification service. The onRegister method registers the remote server and obtains this token. You can view this by adding a console statement.

ss6

The controller component returns null to avoid having any effects on the final layout. Add this method inside the App.js file as shown below:

1// after other import statements
2import RemotePushController from './src/services/RemotePushController'
3
4// before the ending <View>
5 <RemotePushController />
6</View>

To test it out, go to Cloud Messaging section and compose a notification.

ss8

Click the button Send test message. You will have the following output.

ss9

The Log in the terminal is shown for the same notification.

ss10

You can customize the title, message and another behavior of the Firebase Cloud Messaging service to send notifications at a particular time or date by composing the notification.

Conclusion

🔗

Congratulations! You have successfully implemented both ways to send a push notification in a React Native app. Go ahead and try to implement a scheduled notification as a challenge.

Originally published at Jscrambler


More Posts

Browse all posts

Aman Mittal author

I'm a software developer and a technical writer. On this blog, I write about my learnings in software development and technical writing.

Currently, working maintaining docs at 𝝠 Expo. Read more about me on the About page.


Copyright ©  2019-2024 Aman Mittal · All Rights Reserved.