Android: Handling Push Notifications In App Background or Killed State - oracle/pushiomanager-react-native GitHub Wiki


NOTE: This guide will be helpful if your app uses the @react-native-firebase/messaging plugin. If your app uses a different Firebase Messaging plugin then you can follow the concepts explained below and adapt them for your use-case.



Overview

Due to certain restrictions imposed by the React-Native Firebase Messaging plugin, your app may get the following error in the logs when a push notification is received while the app is not in memory.

E/RNFirebaseMsgReceiver: Background messages only work if the message priority is set to 'high'

In some cases, this leads to the app force-closing.


Following code changes will allow your app to receive push notifications even when the app is in killed-state.


Create New BroadcastReceiver


  • Create a new file - MyRNFirebaseMessagingReceiver.java in android/app/src/main/java/<your-package-name> with the following code,
package com.awesomeproject;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import androidx.core.app.JobIntentService;

import com.google.firebase.messaging.RemoteMessage;
import com.pushio.manager.PIOGCMRegistrationIntentService;
import com.pushio.manager.PushIOConstants;
import com.pushio.manager.PushIOManager;
import com.pushio.manager.rn.RCTPIOFirebaseMessagingService;
import com.pushio.manager.rn.RCTPIONotificationHandlerService;

import io.invertase.firebase.app.ReactNativeFirebaseApp;
import io.invertase.firebase.common.ReactNativeFirebaseEventEmitter;
import io.invertase.firebase.common.SharedUtils;
import io.invertase.firebase.messaging.ReactNativeFirebaseMessagingSerializer;

public class MyRNFirebaseMessagingReceiver extends BroadcastReceiver {
    private static final String TAG = "MyRNFirebaseMsgReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "Push notification broadcast received");

        Bundle extras = intent.getExtras();

        if (extras == null) {
            Log.d(TAG, "empty Intent");
            return;
        }

        RemoteMessage remoteMessage = new RemoteMessage(extras);

        if (PushIOManager.getInstance(context).isResponsysPush(remoteMessage)) {

            Log.d(TAG, "Push message will be handled by Responsys SDK");

            Intent pushHandlerIntent = new Intent(context, RCTPIONotificationHandlerService.class);
            pushHandlerIntent.putExtras(intent);

            JobIntentService.enqueueWork(context, RCTPIONotificationHandlerService.class,
                    1, pushHandlerIntent);

            abortBroadcast();

        } else {

            Log.d(TAG, "Push message forwarded to FCM");

            if (SharedUtils.isAppInForeground(context)) {

                Log.d(TAG, "App is in foreground, passing it to firebase onMessage handler");

                if (ReactNativeFirebaseApp.getApplicationContext() == null) {
                    ReactNativeFirebaseApp.setApplicationContext(context.getApplicationContext());
                }

                ReactNativeFirebaseEventEmitter emitter = ReactNativeFirebaseEventEmitter.getSharedInstance();
                emitter.sendEvent(ReactNativeFirebaseMessagingSerializer.remoteMessageToEvent(remoteMessage, false));
                abortBroadcast();

            }else{
                Log.d(TAG, "App not in foreground");
                Log.d(TAG, "Push message forwarded to FCM");
            }
        }
    }
}

  • Remember to change the package name at the top of the file to your app's package name.

  • Add a reference to this new BroadcastReceiver in AndroidManifest.xml as follows,
<receiver
    android:name=".MyRNFirebaseMessagingReceiver"
    android:exported="true"
    android:permission="com.google.android.c2dm.permission.SEND"
    android:priority="999">
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
    </intent-filter>
</receiver>

Update build.gradle


Open android/app/build.gradle and add the following line in dependencies section,

implementation project(':PushIOManager')
implementation 'androidx.core:core:1.6.0'
implementation 'com.google.firebase:firebase-messaging:17.3.0' 

Add Background Message Handler

  • In index.js, add the following code,
import {AppRegistry} from 'react-native';
import App from './App';
import { name as appName } from './app.json';
import messaging from '@react-native-firebase/messaging';

messaging().setBackgroundMessageHandler(async remoteMessage => {
    console.log('Push message received in background: ', remoteMessage);
    
    // Not a Responsys Push, your app should handle this notification
});

AppRegistry.registerComponent(appName, () => App);
  • This code block is called when the app is in killed-state and push notification is received from any push message provider other than Responsys.

  • Push notifications received from Responsys in this app state are automatically handled by the Responsys SDK.

Add Foreground Message Handler

  • In App.js or your main/home JS file, add the following code,
useEffect(() => {

    const messageHandler = messaging().onMessage(async remoteMessage => {

      console.log('New FCM message received: ', JSON.stringify(remoteMessage));

      PushIOManager.isResponsysPush(remoteMessage, (error, response) => {

        if (response) {
          console.log("Received Push Message from Responsys");

          PushIOManager.handleMessage(remoteMessage);

        } else {
          // Not a Responsys Push, handle it appropriately
        }
      });
    });

    return messageHandler;
}, []);
  • This code block is called when the app is in foreground and a push notification is received from Responsys or any other push message provider.




Copyright (c) 2024 Oracle and/or its affiliates and released under the Universal Permissive License (UPL), Version 1.0.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

⚠️ **GitHub.com Fallback** ⚠️