invertase / react-native-firebase

🔥 A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.65k stars 2.21k forks source link

Why setBackgroundMessageHandler not working in iOS also not able to get remoteMessage? #6241

Closed ReactNativeDev2296 closed 2 years ago

ReactNativeDev2296 commented 2 years ago

Hello @felixclack , @jeanregisser , @andymatuschak I am using React native free-base version v10. 1 and React native firebase messaging version 14.9.1. I got the notification in the background but was not able to get logs(payload) in iOS. is there any solution for this

below the index.js file in I added the setbackgroundhandler. `import messaging from '@react-native-firebase/messaging'; import { AppRegistry } from 'react-native'; import App from './App'; import { name as appName } from './app.json'; messaging().setBackgroundMessageHandler(async (remoteMessage) => { console.log(remoteMessage); })

AppRegistry.registerComponent(appName, () => App);`

I also enabled modes background fetch, remote notifications, background processing but get the remoteMessage in setbackgroundhandler and FCM also provided below body. -"content_available": true, "priority": "high" so please help me above issues

jagowm commented 2 years ago

Same problem, any update? thanks in advance.

gezichenshan commented 2 years ago

"@react-native-firebase/analytics": "7.6.9", "@react-native-firebase/app": "8.4.7", "@react-native-firebase/database": "7.5.13", "@react-native-firebase/in-app-messaging": "7.5.8", "@react-native-firebase/messaging": "7.9.2",

setBackgroundMessageHandler doesn't get called either.

mikehardy commented 2 years ago

Those old versions do not work correctly on new operating systems! They are years behind. Check the changelog for how to handle the breaking changes over the course of the previous major versions (it's usually small stuff, unless you need to use the new separate admob package) and get current.

jagowm commented 2 years ago

in my app, versions installed:

"@react-native-firebase/app": "^14.5.1", "@react-native-firebase/messaging": "^14.5.1",

and still not working

mikehardy commented 2 years ago

Nit sure what to say. I've got an app that I send three data only FCM a day too. In the test backend version of the app it pops a notification so I can verify it works.

It works

Needs minimum complete reproduction

GuestInCorle commented 2 years ago

@mikehardy @kildip I've got the same. The background message handler is never called. However, I do receive cloud messages in the foreground mode. The messages I send are only processed when I open the app.

iOS 15.5

    "@notifee/react-native": "^5.3.0",
    "@react-native-firebase/analytics": "^14.11.0",
    "@react-native-firebase/app": "^14.11.0",
    "@react-native-firebase/dynamic-links": "^14.11.0",
    "@react-native-firebase/messaging": "^14.11.0",
    "react-native": "0.66.3",

    "expo-yarn-workspaces": "^1.6.0",

I tried to use both Firebase Console and a custom backend to send cloud messages. None of them worked for iOS.

Android works fine with exactly the same code.

UPDATE Notifications from the Firebase Console are processed as expected.

mikehardy commented 2 years ago

iOS mostly ignores data only messages, you can see log messages in console.app as the device received the message and doesn't deliver to app, that is by design from apple

AnuragTiwari1 commented 2 years ago

Hi

I am also facing this issue. for me "onNotificationOpenedApp" gets triggered when I open app from notification (received in background) but same notification is not caught by "setBackgroundMessageHandler".

please help, I am trying to execute some code when notification is received.

P.S. setting content-available: 1 in apns payload is also not working and onMessage also doesn't called when it is 1, but on removing it foreground notifications are being caught at "onMessage".

below is the payload for POST https://fcm.googleapis.com/v1/{parent=projects/*}/messages:send

{
  "message": {
    "apns": {
      "payload": {
        "aps": {
          "content-available": 1
        }
      },
      "headers": {
        "apns-priority": "5"
      }
    },
    "token": <FCM Token>,
    "data": {
      "Nick": "Mario",
      "Room": "PortugalVSDenmark",
      "body": "test message",
      "title": "test title"
    },
    "notification": {
      "title": "Denmark vs Pune",
      "body": "A match to watch this weekend"
    }
  }
AnuragTiwari1 commented 2 years ago

Hi, I tried the following payload and it worked, I had to restart my device though, I think iOS was not delivering the notifications. also using the release config helps :) POST [https://fcm.googleapis.com/v1/{parent=projects/*}/messages:send]

{
  "message": {
    "apns": {
      "payload": {
        "aps": {
          "content-available": 1
        },
        "acme1": "bar",
        "acme2": "42"
      },
      "headers": {
        "apns-priority": "5"
      }
    },
    "token": <FCM Token>,
    "notification": {
      "title": "Mumbai vs Pune finals",
      "body": "Watch the match online now"
    }
  },
}
GuestInCorle commented 2 years ago

This solved my issue.

https://github.com/invertase/react-native-firebase/pull/6259/commits/8f4297659ae34c42b7bf670ca459e964d808570d

One question remains: why can messages from the Firebase Console reach my device, but messages from the backend can't?

mikehardy commented 2 years ago

There is always the assertion that messages don't reach devices but in my experience messages reach the device, and data-only messages are judged by iOS power miser to be not worthy of delivery to your app. So your app is not booted. Typically it's a difference in JSON payload, and the firebase console usually sends a notification block (nearly guaranteed delivery) while people mostly want data-only messages which are low-priority and unreliable by design.

So people need to watch Xcode console on release version of app installed on real device and see what happens in the logs. Additionally any use cases based on data-only should be reconsidered if you need them to be reliable, because they will not be reliable.

If you are including a notification block and it's still not delivered then you may need to check priority key in FCM JSON or similar.

gezichenshan commented 2 years ago

All updated to "@react-native-firebase/analytics": "14.11.0", "@react-native-firebase/app": "14.11.0", "@react-native-firebase/database": "14.11.0", "@react-native-firebase/in-app-messaging": "14.11.0", "@react-native-firebase/messaging": "14.11.0",

and my messeage is like:

const message = {
  notification: {
    title: 'test',
    body: 'test body',
  },
  data: {
    alarm: JSON.stringify({
      workMode: 1,
      type: 'BatteryLevel',
      replayType: 0,
      userRequest: true,
      watch: {
        last_updated: 1598819591,
        date_created: 1586482958,
        active: 1,
      },
      person: {
        last_updated: 1576099570,
        date_created: 1576099570,
      },
      lat: 123.3,
      batteryLevel: 45,
    }),
  },
  token:token
};

with the code to send message:

admin
  .messaging()
  .send(message)
  .then(response => {
    // Response is a message ID string.
    console.log('Successfully sent message:', response);
  })
  .catch(error => {
    console.log('Error sending message:', error);
  });

But still not got setBackgroundMessageHandler fired.

gezichenshan commented 2 years ago

I solved it by this link.

mikehardy commented 2 years ago

Yeah - that's a "mixed" message, has notification and data block. So firebase-ios-sdk posts the notification and our code / your code does not ever get control, so the handler won't be called. If the user interacts with it you'll see the handler for notification opening the app / initial notification called

YAMMOUNII commented 1 year ago

still not working in my project , any idea ? I tried all the solution above

YAMMOUNII commented 1 year ago

@mikehardy

freakk101 commented 1 year ago

+1

Eramirez06 commented 1 year ago

anything about this?

wmonecke commented 1 year ago

iOS mostly ignores data only messages, you can see log messages in console.app as the device received the message and doesn't deliver to app, that is by design from apple

@mikehardy shouldn't this be added to the docs?

Our app needs to have data-only notifications to be delivered reliably. The notifications are shown conditionally depending on other variables stored in the device.

You mention you have an app that has data-only notifications that apparently are being delivered reliably. So what is the verdict here? Are data-only notifs supported? Should apps that need reliable data-only notifs write a swift Notification Service? I am just a bit confused between this thread vs. the docs related to Cloud Messaging here.

Would the solution be a custom notification service written in swift?

We are facing the issue where setBackgroundMessageHandler is only being called when the app is in background mode but not when quit. We do see the notif arriving in the console.app and the app is being spun up with isHeadless being true. However, setBackgroundMessageHandler is never fired.

Mansigupta-Playleap commented 1 year ago

any update?

josurene commented 1 year ago

any update?

VaseaLuca commented 11 months ago

Hello, so I was facing this issue, for the background state of the app, the notification was not playing the sound. Basically this prop 'apns' solved the issue

admin.messaging().send({ token, notification: {title, body: body || title}, data: { exerciseId: String(nextExercise.id), }, apns: { payload: { aps: { contentAvailable: true, }, } } });

sufian1999 commented 9 months ago

Hello.

I was also facing this issue. Then I saw the last comment of @VaseaLuca. I told my backend developer to adjust this parameter contentAvailable: true on his side when sending me remote notifications. He added this line on his side and when I get notifications then messaging().setBackgroundMessageHandler triggers.

Now when I press on notifications received in the background. It stills calls notifee.onForegroundEvent. So, in notifee.displayNotification I put the data object in it. The code looks like this:

index.js file: `messaging().setBackgroundMessageHandler(async remoteMessage => { console.log('Message handled in the background!', remoteMessage);

// Create a channel (required for Android)
const channelId = await notifee.createChannel({
    id: 'important',
    name: 'Important Notifications',
    importance: AndroidImportance.HIGH,
    sound: 'default'
});

// Display a notification
await notifee.displayNotification({
    title: remoteMessage.notification.title,
    body: remoteMessage.notification.body,
    data: remoteMessage?.data, //Here
    android: {
        channelId,
        importance: AndroidImportance.HIGH,
        // smallIcon: 'name-of-a-small-icon', // optional, defaults to 'ic_launcher'.
        // pressAction is needed if you want the notification to open the app when pressed
        pressAction: {
            id: 'default',
        },
        style: { type: AndroidStyle.BIGTEXT, text: remoteMessage.notification.body },
    },
});

BadgeAndroid?.setBadge(JSON.parse(remoteMessage?.data?.notificationCount));

notifee.setBadgeCount(JSON.parse(remoteMessage?.data?.notificationCount)).then(count => 
    console.log('Current badge count: ', remoteMessage?.data?.notificationCount, '===>', count)
);

});`

`messaging().onMessage(async remoteMessage => { console.log('received in foreground', remoteMessage);

// Create a channel (required for Android)
const channelId = await notifee.createChannel({
    id: 'important',
    name: 'Important Notifications',
    importance: AndroidImportance.HIGH,
    sound: 'default',
});

// Display a notification
await notifee.displayNotification({
    title: remoteMessage.notification.title,
    body: remoteMessage.notification.body,
    data: remoteMessage?.data, // Here
    android: {
        channelId,
        importance: AndroidImportance.HIGH,
        pressAction: {
            id: 'default',
        },
        style: { type: AndroidStyle.BIGTEXT, text: remoteMessage.notification.body },
    },

});
BadgeAndroid?.setBadge(JSON.parse(remoteMessage?.data?.notificationCount));
notifee.setBadgeCount(JSON.parse(remoteMessage?.data?.notificationCount)).then(count => 
    console.log('Current badge count: ', remoteMessage?.data?.notificationCount, '===>', count)
);

}) `

With this, when I tap on notifications received in background, the notifee.onForegroundEvent calls and it contains my background notification's data object. The code looks like this:

I called this in useEffect in my Home screen because of my scenario: `const foregroundEventListener = notifee.onForegroundEvent(async ({ type, detail }: any) => {

        console.log('[Home] User notification', detail.notification);

        switch (type) {
            case EventType.DISMISSED:
            console.log('User dismissed notification', detail.notification);
            await notifee.cancelAllNotifications();
            break;

            case EventType.PRESS:

            handleNotificationPress(detail.notification?.data) // In this function, I did some work based on detail.notification?.data

            await notifee.cancelNotification(detail.notification?.id);
            break;
        }
    });`

In this way, I manage the interaction with background notifications + foreground notifications in iOS.

zirho commented 8 months ago

Restarting the device did the trick.

frankA10019 commented 6 months ago

@zirho which device? computer or iPhone device?