setBackgroundMessageHandler: How to invoke when app is in quit state on iOS

Viewed 1486

I am using the react-native-firebase library.

On iOS, I am able to receive notifications in the foreground, background and also when the app is in quit state. Handlers work in every scenario too, except for one.

My only problem is: setBackgroundMessageHandler is not being invoked when the app is in quit state, even though I am receiving the notification. I also tried to send data-only messages but the result was the same.

I am even able to invoke the app in a headless state using content-available: 1 in the message's apns section.

But still the setBackgroundMessageHandler is not getting invoked. This is my index.js page:

messaging().setBackgroundMessageHandler(async remoteMessage => {
  console.log('HEADLESS BACKGROUND: ' + ' | ' + JSON.stringify(remoteMessage));
});

function HeadlessCheck({ isHeadless }) {
  if (isHeadless) {
    console.log("Headless");
    // App has been launched in the background by iOS, ignore
    return null;
  }

  return <App />;
}

AppRegistry.registerComponent(appName, () => HeadlessCheck);
1 Answers

Instead of returning null from in case of a headless invocation, return a simple component that contains nothing and renders nothing.

Index.js

messaging().setBackgroundMessageHandler(async (remoteMessage) => {
  console.log('HEADLESS BACKGROUND: ' + JSON.stringify(remoteMessage));
});

function HeadlessCheck({ isHeadless }) {
  if (isHeadless) {
    console.log('Headless');
    return <AppFake />;
    /* Notice this component, it is not the App Component but a different one*/
  }

  return <App />;
}

AppRegistry.registerComponent(appName, () => HeadlessCheck);

The AppFake component simply contains this:

import { useEffect } from 'react';
import SplashScreen from 'react-native-splash-screen';

const AppFake = () => {
  useEffect(() => {
    SplashScreen.hide();
  }, []);

  return null;
};

export default AppFake;

I did have to hide the SplashScreen. This was essential in my case.

Here is the payload that I send from the server:

var admin = require('firebase-admin');

const message = {
  notification: {
    title: title,
    body: body,
  },
  data: { campaignId: campaignId, title: title, body: body },
  token: registrationId,
  android: {
    priority: 'high',
    notification: {
      title: title,
      body: body,
      sound: 'default',
    },
  },
  apns: {
    payload: {
      aps: {
        sound: 'default',
        'content-available': 1,
      },
    },
    headers: {
      'apns-priority': '5',
    },
  },
};

let response = admin
  .messaging()
  .send(message)
  .then((res) => {
    console.log(res);
  })
  .catch((err) => {
    console.log(err);
  });

Now the setBackgroundMessageHandler is going to be invoked on every new message even when the app is in the quit state on iOS.

Related