React Native: Handle silent push notification

Viewed 5016

Im using react-native-firebase for handling push notification for our React Native app (for android and iOS).

I noticed that there is only have 1 callback for a push notification that is received when the app is running (foreground or background) and not when its closed or killed.

firebase
.notifications()
.onNotification(notification => {
    console.log('Notification received');
);

But if the app is closed or killed, it will just put the notification in the tray and will not execute the console.log above.

Then enter silent push notification. So when I just send data part in the payload of the notification and even if app is in foreground, the callback above wont be triggered.

I don't see other callbacks that would help on receiving silent push notifications.

So how do we handle push notification in the javascript part?

1 Answers

You don't need additional packages like suggested in other answers. Use RNFirebase.io, you can handle this easily.

If you receive Notification if App is in Background, you have to handle it by your own to display this Notification. As an example see my init-Method for Push-Notifications.

  import firebase from 'react-native-firebase';
  const notifications = firebase.notifications();
  ....
  notifications.onNotification((notif) => {
    notif.android.setChannelId('app-infos');
    notifications.displayNotification(notif);
  });

You do it with displayNotification. But make sure, that you set the Notification-Channel before calling it, because else it wouldn't work on >= Android 8.0

BTW: Make sure, that you fully setup Firebase and grant all needed Permissions to be able to listen for Notifications if App is closed or in Background. (https://rnfirebase.io/docs/v5.x.x/notifications/android)

Appendix

I add this as example to show how I implemented the firebase-notification-stuff as a tiny library (remove the redux-stuff if you don't need it):

import firebase from 'react-native-firebase';
import { saveNotificationToken } from 'app/actions/firebase';
import reduxStore from './reduxStore';
import NavigationService from './NavigationService';

const messaging = firebase.messaging();
const notifications = firebase.notifications();
const crashlytics = firebase.crashlytics();

function registerNotifChannels() {
  try {
    // Notification-Channels is a must-have for Android >= 8
    const channel = new firebase.notifications.Android.Channel(
      'app-infos',
      'App Infos',
      firebase.notifications.Android.Importance.Max,
    ).setDescription('General Information');

    notifications.android.createChannel(channel);
  } catch (error) {
    crashlytics.log(`Error while creating notification-channel \n ${error}`);
  }
}

// This is the Promise object that we use to initialise the push
// notifications. It will resolve when the token was successfully retrieved. The
// token is returned as the value of the Promise.
const initPushNotifs = new Promise(async (resolve, reject) => {
  try {
    const isPermitted = await messaging.hasPermission();

    if (isPermitted) {
      registerNotifChannels();

      try {
        const token = await messaging.getToken();
        if (token) {
          resolve(token);
        }
      } catch (error) {
        crashlytics.log(`Error: failed to get notification-token \n ${error}`);
      }
    }
  } catch (error) {
    crashlytics.log(`Error while checking notification-permission\n ${error}`);
  }

  // If we get this far then there was no token available (or something went
  // wrong trying to get it)
  reject();
});

function init() {
  // Initialise the push notifications, then save the token when/if it's available
  initPushNotifs.then(token => reduxStore.dispatch(saveNotificationToken(token)));

  // Save the (new) token whenever it changes
  messaging.onTokenRefresh(token => reduxStore.dispatch(saveNotificationToken(token)));

  notifications.onNotification((notif) => {
    notif.android.setChannelId('app-infos');
    notifications.displayNotification(notif);
  });

  notifications.onNotificationOpened((notif) => {
    const { notification: { _data: { chatroom: chatRoomId } } = {} } = notif;

    if (chatRoomId) {
      NavigationService.navigate('ChatRoom', { chatRoomId });
    }
  });
}

export default {
  init,
};

With this, only go to your index.js file (or your root-file for your app, how ever it will be named) and call the init-Metod:

...
import LPFirebase from 'lib/LPFirebase';

LPFirebase.init();
Related