Exploring Push Notifications in React Native

Exploring Push Notifications in React Native

August 10, 2021

react-nativefirebase

Exploring Push Notifications in React Native

What are Push Notifications?

Push notifications are the most cost-efficient way to increase user engagement for an application and keep users updated. Today’s mobile apps extensively use push notifications irrespective of their domains. As per an analysis, opt-in rates for app push notifications on Android ranges from 49% to 95%, with a medium equal to 81%, and on the iOS side, it ranges from 29% to 73%, with a medium equal to 51%.


Push notifications are alerts that the users receive in real-time on their device no matter if the app is running or not. There are 2 major categories of push notifications:

  • Local notification
  • Remote push notification

Further, the remote push notification could be categorized as silent or noisy notification. The former does not show the alert in the notification tray and could be used to trigger some processes in background while the latter displays an alert in the notification tray.


Remote push notifications could be sent using one of the below services:

  • Apple Push Notification Service
  • Expo Push Notification Service
  • Firebase Cloud Messaging

To send push notifications to a react native application, we need to register the app using a token which is a string that uniquely identifies each device. We can store this token in our database and map each token with a user. Since this token is mapped to a device in the frontend, we have to handle the updation and deletion of this token on, token expiry and signing out of the user.


In this blog, we’ll create a sample react-native project (expo bare workflow) and implement push notifications using firebase.


Project setup

1. Initialize a react native project (bare workflow) using expo init.
2. Install firebase core dependencies for push notifications
  • npm i @react-native-firebase/app
  • npm i @react-native-firebase/messaging
  • npx pod-install (for install cocoa-pods in iOS)

3. Create a firebase project
Android
1. Add an android app to your newly created firebase project.

Firebase Android App


The android package name is a unique identifier for your application. You can find the value in the AndroidManifest.xml file.

Android manifiest


2. Download the google-services.json file from the next step and place it inside android/app.

Google services


3. Update the native files for adding dependencies.
  • android/build.gradle
buildscript {
    ext {
        buildToolsVersion = "29.0.3"
        minSdkVersion = 21
        compileSdkVersion = 30
        targetSdkVersion = 30
    }
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:4.1.0")
        classpath 'com.google.gms:google-services:4.3.8'  // New dependency added
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

  • android/app/build.gradle
apply plugin: "com.android.application"
apply plugin: 'com.google.gms.google-services' // New plugin added

import com.android.build.OutputFile

iOS
1. Add an iOS app to your newly created firebase project.

Firebase iOS App


The iOS bundle id is the unique identifier for the application that will be registered with apple.

2. Download the GoogleService-info.plist from the next step and open the iOS project in XCode.
3. Verify that the bundle id is the same as of the firebase app. (If not update the identifier)

iOS Bundle


4. Right click on the project and select Add Files to “project name”

Add files iOS


5. Add the downloaded GoogleService-info.plist

Google services plist


6. In the AppDelegate.m import firebase and initialize firebase app
#import <React/RCTLinkingManager.h>
#import <Firebase.h> // import firebase dependency
@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  // initializing firebase app
  if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }


Getting permissions

iOS
1. In XCode, under Signing & Capabilities, add Push Notifications and Background Modes capability. Under Background Modes, select background fetch and remote notifications options.

Signing Capabilities


2. Head over to the Certificates,Identifiers & Profiles section in the apple developer portal and create a new key. Select the Apple Push Notification Service and then continue and download the key.

Apple Developer Portal


3. Upload the downloaded key in the firebase project settings.

Firebase key upload


Now, since we have completed all the setup, we’ll proceed to the mobile code to fetch the required permissions.
  • In the starting point of your react native project (App.tsx), add the code to request access.
// getting push notification permission
useEffect(() => {
  messaging().requestPermission()
}, [])


Getting push token

useEffect(() => {
  // get the device token on app load
  messaging()
    .getToken()
    .then(token => {
      setToken(token)
    })

  // Setup a listener so that if the token is refreshed while the
  // app is in memory we get the updated token.
  return messaging().onTokenRefresh(token => {
    setToken(token)
  })
}, [])


Backend setup

const payload = {
  notification: {
    title: "Push Notification",
    body: "This is push notification sent dynamically from backend 🤩",
    sound: "default",
  },
}
await admin.messaging().sendToDevice(token, payload, {
  contentAvailable: true,
  priority: "high",
})

Token in the sendToDevice method is the destination token. By default data-only notifications do not show alerts on the device therefore we explicitly make the notification’s priority high and content available as true for android and iOS to show the alert.

Sending and receiving notification

// send the notification
const sendNotification = async () => {
  Alert.alert(
    "Notification sent",
    "The destination will receive the notification"
  )
  try {
    await axios.post(
      "https://9d9gmb4jmd.execute-api.us-east-1.amazonaws.com/dev/",
      { token }
    )
  } catch (error) {
    console.log("Error", error)
  }
}

We’ll send the destination token to our backend endpoint to send the notification.
By default the push notification does not appear when the app is in foreground. To handle the scenario, we need to listen to the incoming notification.

// handling foreground notifications
useEffect(() => {
  const unsubscribe = messaging().onMessage(async (remoteMessage = {}) => {
    const notification = remoteMessage.notification || {}
    const title = notification.title
    const body = notification.body
    if (title) {
      Alert.alert(title, body)
    }
  })

  return unsubscribe
}, [])

This will show an alert once we receive the notification.

App Screenshots

Home Screen


Conclusion

  • To setup push notifications in iOS, you need a developer account
  • iOS simulator does not support push notifications. The flow needs to be tested on a real device.
  • For android emulators, you need to be signed in with a google account for the push notifications to work.
  • For advanced workflows and customizations, you can use react-native-push-notification package

For more information refer to the react native firebase docs.

Source Code

React-native: https://github.com/antstackio/rn-push-notification-demo

Backend: https://github.com/antstackio/push-notification-lambda

Antstack Blog Post
Antstack Blog Post

Are you planning to go to serverless? AntStack is a cloud computing service and consulting company primarily focusing on Serverless Computing. We help companies get up and running with serverless, and we’ll make sure that there are no limits.

Keep track of our socials and connect with us - LinkedIn

event bannerevent bannerevent banner