react-native-sdk icon indicating copy to clipboard operation
react-native-sdk copied to clipboard

Can't properly control Iterable push notifications with Firebase when app is in quit state

Open markgibaud-vtail opened this issue 2 years ago • 1 comments

I have contacted Iterable support about this but we've been unable to come up solution, so I'm posting here in case anybody else can help!

Current state

We've implemented push notifications from Iterable using the usual react-native-firebase. All PNs from all our providers (Iterable, Intercom, and ourselves via firebase-admin from our own backend) in foreground/background/quit state work fine on iOS.

We have customized Iterable to send Android PNs with "Use OS Notifications" off as we'd like as much control as possible when receiving PNs.

Our initial problem was that on Android we were not receiving push notificaitons because Firebase was dropping them, as the priority was not set tohigh by Iterable servers when sending.

When we send a test PN from Iterable: image

We don't have this problem when sending our own notifications from our own backend as the default priority when using firebase-admin is high as you can see here.

After help from Iterable support we noticed an extra piece of config we had to add:

https://support.iterable.com/hc/en-us/articles/115000331943-Setting-up-Android-Push-Notifications-#handling-firebase-push-messages-and-tokens

We'd previously integrated Intercom PNs and so we already had our own firebase MainMessagingService. Support explained that the Iterable SDK receives a firebase message in normal priority and upgrades it to high and displays it, so we ended up with this as our new MainMessagingService:

public class MainMessagingService extends ReactNativeFirebaseMessagingService {
    private static final String TAG = "MainMessagingService";
    private final IntercomPushClient intercomPushClient = new IntercomPushClient();

    @Override public void onNewToken(String refreshedToken) {
        intercomPushClient.sendTokenToIntercom(getApplication(), refreshedToken);
        IterableFirebaseMessagingService.handleTokenRefresh();
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Map message = remoteMessage.getData();

        if (intercomPushClient.isIntercomPush(message)) {
            Log.d(TAG, "Intercom message received");
            intercomPushClient.handlePush(getApplication(), message);
        } else if (message.containsKey("itbl")) {
            Log.d(TAG, "Iterable message received");
            IterableFirebaseMessagingService.handleMessageReceived(this, remoteMessage);
        }
        else {
            super.onMessageReceived(remoteMessage);
        }
    }
}

The Problem

This change now does result in receiving push notifications in quit state. The problem is that it also results in PNs being received for backgrounded and foregrounded app states, because it duplicates the functionality we have at the RN layer hooking up the firebase events:

Backgrounded:

messaging().setBackgroundMessageHandler(async (message) => {
  headlessBackgroundNotificationHandler(message);
});

Foreground:

messaging().onMessage((remoteMessage) => {
        void handleForegroundNotification(remoteMessage);
      });

We don't want to change that functionality as it handles navigation, deeplinking, analytics tracking and a host of other things we want to maintain on the RN side when responding to PNs.

So how to only invoke the Iterable SDK when receiving an Iterable psuh notification when the app is in quit state? Note: even this is not ideal, as I'm not sure how deeplinking etc would be successful (as that is all implemented & maintained at the RN layer using LinkingConfig and not at the native Android layer).

What I've tried

I've tried storing a value of quit=true/false as the app foregrounds and then enters quit state (to use to decide whether to send an incoming iterable PN to the iterable SDK or not), but that only works intermittently as an Activity's onDestroy method is not guaranteed to finish before the OS kills the app.

It seems the easiest fix would just be for Iterable to send the firebase notificaiton with high priority and then we can effortlessly handle it at the RN layer :/

Anyone got any suggestions?

More info:

Not terribly helpful but this comment may be referencing a bit of the trouble I'm encountering re 3rd party CRMs playing well with Firebase. https://github.com/invertase/react-native-firebase/issues/3457#issuecomment-1073907233

markgibaud-vtail avatar Nov 22 '22 09:11 markgibaud-vtail

@Ayyanchira is there a reason why we are using "normal" priority when sending the Android push notifications ? Seems if we set the priority to high this issue can be solved.

devcsomnicg avatar Jul 10 '23 07:07 devcsomnicg