evollu / react-native-fcm

react native module for firebase cloud messaging and local notification
MIT License
1.73k stars 681 forks source link

Can't access notification data when the app is in background or killed #623

Open vlaraort opened 6 years ago

vlaraort commented 6 years ago

Hi!

First of all, great work with this library!

react-native@0.48.0
react-native-fcm@10.0.2
OS: Android - Emulator - 7.0.2

When my app is in foreground, its working perfectly, I receive the data in this function

FCM.on(FCMEvent.Notification, async (notif) => {

And I can handle everything

image

But when the app is in background, the notification is received, but when I tap the banner, the app goes foreground, the same function is triggered, but the notif object is different, and don't contains my data.

image

When the app is killed, also the notification is received, but when I tap the banner, the app starts, the FCM.getInitialNotification() is triggered, and my notif object doen't also contain the data, the same behaviour than in background

image

I am testing the format of the messages using node-gcm library, of firebase web interface, but nothing works.

This is a sample of my message:

let message = new gcm.Message({
    priority: 'high',
    content_available: true,
    timeToLive: 3,
    data: {
        key1: 'message1',
        key2: 'message2'
    },
    notification: {
        title: "Hello, World",
        icon: "ic_launcher",
        body: "This is a notification that will be displayed if your app is in the background."
    },
    custom_notification: {
        key1: 'message1',
        key2: 'message2'
    }

});

How should I proceed to send and receive data in those cases? Because is driving me crazy.

If you need more data, ask for it :)

Thanks!!

EDIT:

I have two activities in my native part, as I am handling a splash screen in the native way. can this be causing this effect?

This is my manifest.xml. I don't want to handle local notifications, only remotes

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.myapp"
          android:versionCode="1"
          android:versionName="1.0">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

    <uses-sdk
            android:minSdkVersion="16"
            android:targetSdkVersion="22" />

    <application
            android:name=".MainApplication"
            android:allowBackup="true"
            android:label="@string/app_name"
            android:icon="@mipmap/ic_launcher"
            android:theme="@style/AppTheme">
        <meta-data
                android:name="com.google.firebase.messaging.default_notification_icon"
                android:resource="@drawable/ic_stat_azvase_notification" />
        <service android:name="com.evollu.react.fcm.MessagingService" android:enabled="true" android:exported="true">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>
        <service android:name="com.evollu.react.fcm.InstanceIdService" android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
            </intent-filter>
        </service>
        <activity
                android:name=".SplashActivity"
                android:label="@string/app_name"
                android:theme="@style/SplashTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".MainActivity"
                  android:launchMode="singleTop"
                  android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
                  android:windowSoftInputMode="adjustResize"
                  android:exported="true"

        >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

    </application>

</manifest>
vlaraort commented 6 years ago

Ok, I fixed it, It was caused by the native splash screen, when I removed the SplashActivity and I only handle the main one, everything worked fine!

evollu commented 6 years ago

@vlaraort you mean you can get all data now?

fredbt commented 6 years ago

Hi there, first of all, thanks for this library. Great stuff!

I have to say that I implemented a very different workflow in my app, where the push controller component is NOT inside a React component. Instead, the listeners for notifications are always accessible from the top-most component of my app (but not requestPermissions nor getFCMToken). I did this following the suggestions from react-native-push-configuration, the framework that I used before (but which does not work with FCM for IOS). This means that my app could technically receive notifications when it's killed (which actually works pretty well in Android).

I want to describe my use case since I'm having a problem with IOS now:

        data = {
            "to": token,
            "data": {
                "myMessage": json-of-my-payload
            }
        }

the app knows how to interpret "myMessage".

On Android, things work nicely. I get the notification in basically every scenario and take the actions that should be done. Even when the app is killed, Android brings it up under the hood (in a flow that I think is not the common react lifecycle flow) and I can even do redux store operations.

But in IOS I have the following issues:

1 - To start with, the format is different, otherwise notifications do not get through. This is fine and I can handle it somehow in the app side. But for the record, the format is below:

        data = {
            "to": token,
            "notification": {
              "title": my-title-string,
              "body": my-body-string
            }
            "data": {
                "myMessage": json-of-my-payload
            }
        }

2 - First real issue: I don't want to always show a local notification. As I said, I want the app to take decisions to show the notification or not depending on what's encoded in myMessage.

3 - When the app is killed, my callback code (FCM.on(FCMEvent.Notification, notif => {) is not called in IOS. This means that my app is not taking decisions such as to write stuff in the redux store. Because of that, my app is lacking pretty important data. It is worth mentioning that the notification still shows up because IOS always shows up messages with body/title.

I decided to seek help for these cases since the behavior is not very consistent between the platforms.

Thanks, Fred

evollu commented 6 years ago

issue 2: try remove the notification part and add "content_available": true. See if the notification gets delivered. issue 3: App should wake up after reboot or system kill because of memory shortage. Swiping away in task center will prevent app waking up. System behavior.

I would not rely on notification and sync data with server on launch for both Android and iOS because user can turned off notification.

fredbt commented 6 years ago

Thanks, @evollu ... good suggestions, I will change my backend <-> app behavior a bit based on this idea.

Thank you so much!

imarem commented 6 years ago

Hi @fredbt

I have the same problem, have you fix it?

fredbt commented 6 years ago

hi @imarem, I'm using this format for android:

    ```

data = { "to": token, "data": { "myMessage": json-of-my-payload } }



and it works well for most of the things I want to accomplish with my notifications. I still need to test on IOS, but unable now given that our devices are not here in the company.
imarem commented 6 years ago

Hi @fredbt,

Thannks for your answer, in android I haven't problems, I use the same configuration in the payload. It's in iOS where I don't receive anything in the FCM.on event (FCMEvent.Notification, async (notif) => {...

I have several consoles in this event but when the app is in the background, I don't receive nothing if I don't press on banner.

fredbt commented 6 years ago

@imarem

I don't fully remember if we managed to get the it working completely on IOS last week when I was experimenting --- I will double check later this week.

Did you configure your app in XCode to receive Remote Notifications?

imarem commented 6 years ago

@fredbt

==>Did you configure your app in XCode to receive Remote Notifications? ==> Yes! image

VietDucPhan commented 6 years ago

My data payload also disappear when i tap on banner. any one got any suggestion?

pkhien95 commented 6 years ago

Any solution? I have the same problem. My notification when app is on background or killed is totally different from the one when app is foreground. It only has open_from_tray: true and no data payload. I have only MainActivity in AndroidManifest (no SplashScreen as @vlaraort mentioned).

MaxiSantos commented 6 years ago

@vlaraort thanks, your fix worked for me. I removed splash screen and I also added this `

` in MainActivity

balapkm commented 6 years ago

@evollu still i'm getting below msg only in android if i opened app .How to fix this

{
  "content_available": false,
   "notification": {
       "title": "hello",
       "body": "yo"
   },
   "data": {
       "extra":"juice"
   },
  "to":"cbGVdEcQcl5pXvT8wBqo1e8I_nALw7czQaymhDRa1ol0IZD4KV2GVqmDANy6_oJcphyIizEkF9LLtyf18FnYXvd6buARv60y8MLlGds-jpQUvqOPs7Xiat0DV-HiPwmNSPRmZAbn"
}

{ opened_from_tray: 1, fcm: { action: 'android.intent.action.MAIN' } }