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

Not getting notification via FCM.on or FCM.getInitialNotification

Open bhosle-git opened this issue 7 years ago • 40 comments

Hi,

I'm seeing similar issue reported in https://github.com/evollu/react-native-fcm/issues/569, but not sure if it is exactly the same.. In some cases, when i click on the notification toast, i get the notification properly in my app in the FCM.on callback that i have as follows:

FCM.on(FCMEvent.Notification, async (notif) => {
    logger.log("received notification: " + JSON.stringify(notif))
    handleNotification(notif)  // my code to handle the notification
}

However, in one particular case, the above code doesn't get invoked. This is when I wait for a long time (say, 15+ minutes) before I click/tap on the notification toast. I think Android puts the app to sleep after that much time?

I am also already checking for FCM.getInitialNotification as follows.. (the code below is invoked from one of my componentDidMount methods)..

FCM.getInitialNotification().then(notif => {
    if(notif){
        logger.log('Got initial notificaton: ' + JSON.stringify(notif))
        NotificationUtil.handleNotification(notif)
    }
}

I do get something in the above block (initial notification), but its kind of empty. the log statement above is:

Got initial notificaton: {"opened_from_tray":1,"fcm":{"action":null}}

And this happens only when I wait for a while before i click/tap on the notification toast (not sure if some folks here are calling that a 'banner' - which is available when you swipe/pull down from the top of the phone screen)..

If the app is just minimized, and i tap on the notification toast in a couple of minutes, everything works fine - my FCM.on callback gets invoked, and i get the complete notification data as expected.. here's one log for the success case:

received notification: {"fcm":{"action":"my_test_action"},"show_in_foreground":true,"data.foo":"bar","sound":"default","opened_from_tray":1,"click_action":"my_test_action","priority":"high","id":"my_notif_id","body":"test notif body","title":"test notif title","icon":"ic_launcher","local_notification":true}

@evollu - do you know what could be causing this?

Thanks Amit

When openning an issue, please include following information for better support

  1. What version of RN and react-native-fcm are you running? "react": "^16.2.0", "react-native": "^0.51.0", "react-native-fcm": "^11.3.1",

  2. What device are you using? (e.g iOS9 emulator, Android 6 device)? Android 7.1.1 emulator (same behavior on many other versions, as well as my Samsung s8+ running 7.1.1)..

  3. Is your app running in foreground, background or not running? not running

Before openning an issue

  1. Reproduce it with the example project in this repo.
  2. If you can't receive iOS notification, make sure you can receive notification using quickstart-ios project provided by Firebase team

bhosle-git avatar Feb 02 '18 19:02 bhosle-git

quick update here..

i realized that we had upgraded the react-native-fcm version recently (11.3.1).. but when i rolled back to an earlier one (10.0.3), things work as expected!(double checked a few times rolling back/forward on these two versions, and that's what it looks like - regression in some version after 10.0.3)

bhosle-git avatar Feb 02 '18 19:02 bhosle-git

one big change I've made is the local broadcasting. If you have chance can you test the latest version if this line is triggered? https://github.com/evollu/react-native-fcm/compare/v10.0.3...v11.3.1#diff-c04acb3238c7458755defae08932ece4R218

v10 has a big issue: if you have multiple app using this notif repo, both apps will get notifications

evollu avatar Feb 05 '18 15:02 evollu

can u double check the diff link? i can't see anything when i click on it.. (see attached screenshot) rn-fcm-diff

bhosle-git avatar Feb 05 '18 18:02 bhosle-git

btw, @evollu - I'm seeing another weird issue..

like already mentioned, i have registered the callbacks for FCM.on.. but i also check for FCM.getInitialNotification(..) from one of the componentDidMount methods (when my app loads)..

sometimes, the FCM.getInitialNotification(..) gets a pretty old (several hours) instance of a notification..

do you know what could cause that? when is the FCM.getInitialNotification(..) supposed to clear out? (or is there a way that I can clear that out from my app?)

is there any recommended pattern / best-practices so that I can know whether I should ignore the FCM.getInitialNotification(..) response or not?

Thanks..

bhosle-git avatar Feb 06 '18 06:02 bhosle-git

I was dealing with a similar issue last week but everything seems to be working fine for me now. I was using wix react native navigation and that was causing problems that I didn't have with this library previously.

Now I get the initial notification before doing anything else on my application and store it to use once the user logs in to the app.

Also if the app starts by running react-native-run-android I'm not able to get the initial notification. If I kill the app and start it again after that everything is fine. This isn't a problem when it goes to a production release on the play store. It's just caused by the terminal starting my Main Intent it seems.

RuairiOliver avatar Feb 06 '18 09:02 RuairiOliver

@bhosle-git the right url is https://github.com/evollu/react-native-fcm/compare/v10.0.3...v11.3.1

FCM.getInitialNotification(..) doesn't get updated until the app is killed. putting app in background for long time doesn't seems to kill the app. Usually you put some custom property in notification like type, then you just check if that thing is present in FCM.getInitialNotification. FCM.getInitialNotification should only be call on app bootstrap. like DidMount in our root component or outside of component lifecycle

evollu avatar Feb 06 '18 14:02 evollu

@evollu - we do have something to identify that its our app's notification.. the issue is that its a very old notif instance that had been processed earlier.. but let me try moving that outside the component lifecycle and see how it behaves..

@RuairiOliver - we recently moved to react-navigation from an earlier one that was deprecated.. not sure if its the same issue.. but yeah - I'll try getting the initial notification before anything else (from index.js) and update here..

thanks both..

bhosle-git avatar Feb 06 '18 15:02 bhosle-git

SO: Android 7.0 - Physical Device

I have the same problem. When opening the app for the first time through the notification, getInitialNotification() runs perfectly. After leaving the app idle for a while (I open other apps to force inactivity) and reopen it, getInitialNotification() is bringing exactly the same data as before. This is a problem.

I also did the test by opening the app after inactivity through another notification in the tray. The result was the same, instead of getInitialNotification () returning the last open notification data, it shows the notification data that opened the app.

Another similar situation is that if I open the app normally by the icon, I let it be inactive, so when I receive a notification and try to open it, getInitialNotification() returns only the data of the app initialization:

{
  "opened_from_tray":1,
  "fcm":{
    "action":"android.intent.action.MAIN"
  },
  "profile":0
}

When the app is in the background, but not sleeping / inactive, and I open the notification via the tray, everything works fine.

Is not there really a way to reset / delete the notification after getInitialNotification() is called?

I think it's the first time I write here. I would like to thank you for the excellent work, @evollu.

dougmbarcellos avatar Feb 26 '18 01:02 dougmbarcellos

I'm facing the same issue as @dowgsss .

Is not there really a way to reset / delete the notification after getInitialNotification() is called?

sfm2222 avatar Feb 26 '18 15:02 sfm2222

Facing the same issue. In addition, my app's notification listener does not show an alert when I tap the alert in the notification center.

christianversloot avatar Feb 26 '18 18:02 christianversloot

@bhosle-git is your issue solved?

Is not there really a way to reset / delete the notification after getInitialNotification() is called? not as far as I know. It is reading from a native property, which doesn't cleared.

evollu avatar Feb 26 '18 21:02 evollu

In recent days I've been trying to solve this problem by researching, modifying, and debugging the native code. Even though my background has been based on Java, I find it difficult on Android. Unfortunately I did not find any solution.

Not unlike what @evollu has already said...

From what I saw, the firebase uses an Intent, which is "attached" to our MainActivity. In this case, the data we send is in the Intent extras. This data can be easily deleted or modified, but by the time Android kills the app and then the user opens it, we get back to the Intent data that was opened along with the app the first time. From what I've read, this data is in a "process" of Android, so whenever the app is restored, the data from that Intent comes back. It seems that some people who use firebase messaging with native java code also have the same problem.

"Solution" in my case...

For the time being, when handling the initial notification I will save the notification code within AsyncStorage and will only take some action on the notification if it is different from the last notification saved in AsyncStorage.

dougmbarcellos avatar Mar 03 '18 01:03 dougmbarcellos

@dowgsss 👍

evollu avatar Mar 03 '18 01:03 evollu

I have not given up yet. Yesterday, while I was in the barber shop waiting for my turn, I still insisted on how to solve the problem, cleanly. I did some research and at some point I came across an issue that I had seen several times in stackoverflow, but had not paid attention to the answer less voted:

https://stackoverflow.com/a/18307360/9070081

Code
@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);

    /*
    * This overrides the original intent.
    */      
    setIntent(intent);
}

I added this excerpt in my MainActivity and YES, the problem has been solved!

In short, there are now two situations that can happen considering that you opened the app and after some downtime the system killed the app:

  • If you open the app through a new notification, the extra data from this last notification will be passed in getInitialNotification. Yeah!
  • If you open the app directly from the list of recent tasks, the first notification executed at the initialization of the app that is received in getInitialNotification. Here you still need to be careful:

At this second point, if you want to prevent the same action / notification from being run multiple times, you need to do an implementation using AsyncStorage or something, as I said in my last comment.

dougmbarcellos avatar Mar 05 '18 02:03 dougmbarcellos

@dowgsss

are you saying that by calling setIntent it will override the response of getInitialNotification to be the newer intent?

But I have 2 questions

  1. Is there a way for iOS to do the same?
  2. This new intent will be broadcasted through notification callback to JS. so what is the benefit of changing the intent?

evollu avatar Mar 05 '18 15:03 evollu

  1. Is there a way for iOS to do the same?

Since I do not program for iOS I really do not know how to answer that. In fact, are there any reports of this same problem in iOS?

  1. This new intent will be broadcasted through notification callback to JS. so what is the benefit of changing the intent?

I'll always have the extra data updated in that specific situation where android kills the app and then I open the app via a notification. I will be able to see the data from this last notification.

dougmbarcellos avatar Mar 05 '18 16:03 dougmbarcellos

  1. so far iOS shares the same behavior as Android, I'd prefer to keep them in sync to avoid surprises.
  2. if android kills the app and you open it through notification, getInitNotification should give your the new notification. @dowgsss

evollu avatar Mar 05 '18 19:03 evollu

@evollu I think there may be a misunderstanding about point 2. The problem is precisely because on Android, when the app is killed by the system (not by the user) when you reopen it through a notification, we are not receiving data from that last notification .

I think I can describe it through the following steps (without the change I suggested in MainActivity):

  • My recent apps list is empty.
  • A notification from my app is received.
  • I touch that notification.
  • Now the app opened for the first time, and via a notification. In getInitialNotification() I get something like:
{
  opened_from_tray: 1,
  fcm: { action: 'android.intent.action.MAIN' },
  collapse_key: 'xxxxxxxxxxx',
  'google.message_id': 'xxxxxxxxxxxxxxxxxxxx',
  from: 'xxxxxxxxxxxxxx',
  'google.ttl': 1111111,
  my_data_key: 'abc123',
  'google.sent_time': 0000000000000
}
  • With each notification I pass a unique my_data_key inside the data node.
  • Ok. Through getInitialNotification() I received the notification data and checked that my_data_key is valid, so I triggered an action.
  • Now I minimize my app and go to other apps. After a while android kills my app because of inactivity, however it continues in the list of recent apps. This is an important point.
  • Now I get another notification.
  • I touch this notification and the app opens one more time, but now it was on the list of recent apps.
  • At this point I expect the new notification data to be passed to getInitialNotification(), but what I get is the same data as the first notification:

Expectation:

{
  opened_from_tray: 1,
  fcm: { action: 'android.intent.action.MAIN' },
  collapse_key: 'xxxxxxxxxxx',
  'google.message_id': 'yyyyyyyyyyyyyyyyyyyyyyy',
  from: 'xxxxxxxxxxxxxx',
  'google.ttl': 1111111,
  my_data_key: 'otherDataKey',
  'google.sent_time': 0000000000000
}

Reality(same data as the first notification):

{
  opened_from_tray: 1,
  fcm: { action: 'android.intent.action.MAIN' },
  collapse_key: 'xxxxxxxxxxx',
  'google.message_id': 'xxxxxxxxxxxxxxxxxxxx',
  from: 'xxxxxxxxxxxxxx',
  'google.ttl': 1111111,
  my_data_key: 'abc123',
  'google.sent_time': 0000000000000
}

Note:

When my app is only in backgroud and not dead, I can handle the notifications without any problem.

dougmbarcellos avatar Mar 05 '18 22:03 dougmbarcellos

i will look into that

evollu avatar Mar 06 '18 00:03 evollu

sorry - had to be away for a couple of weeks. The issue is not resolved on my side either (I tried the change mentioned earlier - doing it outside the component lifecycle).

will try the change that dowgsss has mentioned as working for him.

bhosle-git avatar Mar 06 '18 19:03 bhosle-git

@dowgsss A bit confused here.

  1. When app is running in background do you get notification callback when you tap on notification?
  2. When app is inactive (I don't know if android persist the state of app or not), do you get notification callback when you tap on notification?

evollu avatar Mar 06 '18 19:03 evollu

@evollu

  1. Yes, through the listener FCM.on(FCMEvent.Notification, fn).
  2. In this case, through the getInitialNotification().

dougmbarcellos avatar Mar 06 '18 20:03 dougmbarcellos

case 2: You don't get any notification callback? Can I reproduce it in emulator? I follows steps here https://stackoverflow.com/questions/3417308/force-an-android-phone-to-sleep-in-order-to-test and wake up the device, tap the notification, still get JS callback.

evollu avatar Mar 06 '18 21:03 evollu

case 2: You don't get any notification callback?

No, I'm getting the callback data

dougmbarcellos avatar Mar 06 '18 21:03 dougmbarcellos

@dowgsss then why not just act on the callback data?

evollu avatar Mar 06 '18 21:03 evollu

then why not just act on the callback data?

Because, following those steps I've explained, the data is not arriving correctly. It's coming up with the old notification data. Remembering that I only have problems in getInitialNotification().

I opened another app and turned off the screen, waited for couple minutes, come back and tap the notification. I will get a notification callback triggered

Through the getInitialNotification()?

dougmbarcellos avatar Mar 06 '18 21:03 dougmbarcellos

getInitialNotification() should not be updated because the app is just suspended, not killed. The app status is persisted. Are you still on the same page when you resume the app?

evollu avatar Mar 06 '18 22:03 evollu

getInitialNotification() should not be updated because the app is just suspended, not killed. The app status is persisted. Are you still on the same page when you resume the app?

No, it's like the app starts again.

dougmbarcellos avatar Mar 06 '18 22:03 dougmbarcellos

I tested the emulator by following the suggested steps, but although the device was idle, the app was not killed by the system. So in this case yes, when I opened the notification / app I came across the same screen, the app was not loaded again.

dougmbarcellos avatar Mar 06 '18 22:03 dougmbarcellos

To see the problem the app must be killed by the system (not by the user).

dougmbarcellos avatar Mar 06 '18 22:03 dougmbarcellos