Versions:
rn - 0.34.1
fcm - 2.3.2
I have an android app. When I click on home button to move the app to background and then sending a notification, the notification goes to notification area, but when I click on the notification, the app goes to foreground directly (it's not re-launching) and the notification data is not passed to the app.
Is this related to the hybrid notification problems? I thought that the hybrid problem is just when not clicking on the notification, but when clicking it should pass the data to the app somehow.
notification payload:
{
priority: 'normal',
contentAvailable: true, //for ios
delayWhileIdle: true,
timeToLive: fcmConfig.timeToLive,
restrictedPackageName: 'my app id',
dryRun: fcmConfig.isDryRun,
data: {
myData: {
id: '123456',
}
},
notification: {
title: 'Hello world title',
icon: "ic_launcher",
body: 'Hello world body',
sound: 'default',
},
}
javascript:
///When app started:
FCM.getInitialNotification()
.then(notification => {
if (notification && notification.myData) {
alert(notification.myData);
}
});
FCM.on('notification', (notif) => {
alert("on: " + notif.myData);
});
I have this same issue, and it's driving me nuts. This project's documentation isn't helpful. It just says, "it's tricky!" and links to a really old GCM issue: https://github.com/google/gcm/issues/63
Looks like if you want a hybrid notification to work properly when the app is in the background, you need to pass a click_action in your notification payload. Then in AndroidManifest.xml set MainActivity to respond to an intent with that click_action.
Feels like this behavior should be better documented. It's taken a lot of trial and error to understand what's really going on.
So u figure it out? I tried using click_action but still couldn't get it to work..
Make sure you did this part correctly: https://github.com/evollu/react-native-fcm#config-for-notification-and-click_action-in-android. That's something that tripped me up for a bit.
Are you sure we're talking about the same scenario?
In my scenario, the app is in the background, still live and kicking..When I click the notification, the app doesn't load from scratch, it just reappears, just like pressing the home button and then pressing the app again..
I'm not talking about when the app is in the background for few mins which then it gets killed or whatever..
I did everything as u said but nothing works..
{
priority: 'normal',
contentAvailable: true, //for ios
delayWhileIdle: true,
timeToLive: fcmConfig.timeToLive,
restrictedPackageName: 'my app id',
dryRun: fcmConfig.isDryRun,
data: {
myData: {
id: '123456',
}
},
notification: {
title: 'Hello world title',
icon: "ic_launcher",
body: 'Hello world body',
sound: 'default',
click_action: 'myAction',
},
}
AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myPackage"
android:versionCode="5"
android:versionName="0.1.5">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<permission
android:name="${applicationId}.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="22" />
<application
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:theme="@style/AppTheme"
android:name=".MainApplication">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:screenOrientation="nosensor"
android:windowSoftInputMode="adjustResize"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="myAction" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<service android:name="com.evollu.react.fcm.MessagingService">
<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="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
Even tried MainActivity.java:
@Override
public void onNewIntent (Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
Nothing seems to get the notification data to the app.
Just to be clear..when the app is closed, and I get the notification, the data is passed to the app through FCM.getInitialNotification.
After checking a little bit I can identify two problems:
Apparently when the app is in the background or even in foreground, when clicking a notification, then:
FCM.getInitialNotification() is populated with the correct notification.
So the following code does seem to work (at least on android):
handleChange(change) {
if (change !== 'active') {
return;
}
// Closing screen and opening again does run this again and will get the same notification..so you might want to add code to check if you already got this notification..
FCM.getInitialNotification().then(notification => {
if (notification.myData) {
alert(`init: ${notification.myData}`);
}
});
}
componentWillMount() {
AppState.addEventListener('change', this.handleChange);
}
componentWillUnmount() {
AppState.removeEventListener('change', this.handleChange);
}
Is this the way to go?
U just need to call getInitialNotification on componentDidMount, no need to call it every time the appstate changes
I didn't need to add an AppState listener whatsoever. To summarize, this is how I'm handling notifications in my app, there's 3 scenarios:
_App isn't Running:_
getInitialNotification() will fire. This is a promise that seems to always fire (with an empty notification if there isn't an initial notification), so you can show a loading screen and wait until this promise resolves to show a screen based on the notification_App is in Foreground:_
data payload will get passed through FCM.on('notification' event. If you want to show a system notification, here you need to trigger a manual, local notification. Be careful with this, since the local notification will fire FCM.on('notification' itself, and you could have a loop creating infinite notifications._App is in Background:_
click_action. The activity needs to be specified as singleTop and be able to handle that intent. The Activity will show and because it's already running, FCM.on('notification' event will fire.Hopefully that's helpful. That's been my experience with this package, and I'm running Android Marshmallow. It might be different on other phones.
To be honest with you, I think the right thing todo is to write my own Firebase listening service, use just data notifications, and fire local notifications when those are received. That's what I'm going to do eventually. Getting all this to work was a big pain, and it's mostly because of Firebase.
More notes....
MainActivity.java"react-native": "0.33.0", "react-native-fcm": "2.3.0",Sample payload:
{
"to" : "token-goes-here",
"notification" : {
"title" : "Story title",
"body" : "location name",
"icon" : "ic_stat_notify",
"sound": "default",
"click_action": "geosocial.story"
},
"data" : {
"title" : "Story title",
"body" : "location name",
"icon" : "ic_stat_notify",
"story_id" : "10279"
},
}
Relevant parts of AndroidManifest (notice geosocial.story intent)
<application
android:name=".MainApplication"
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher_geosocial"
android:theme="@style/AppTheme">
<!-- For displaying local notifications -->
<receiver android:name="com.evollu.react.fcm.FIRLocalMessagingPublisher"/>
<!-- For listening to firebase messages -->
<service android:name="com.evollu.react.fcm.MessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<!-- For handling rotating firebase ids -->
<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=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="geosocial.story" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_api_key"/>
</application>
I've been struggling with this all day. The FCM API seems to have some issues...
Regarding the docs for react-native-fcm, it says that if the app is running in the background, the following applies:
Android will receive notificaton from FCMNotificationReceived event
This, however, is not true. The FCM.on('notification' callback isn't called if I pass both notification and data payloads. It's only called if I pass data only.
Given this constraint, how do I create a hybrid notification, i.e. one that both invokes a callback in the application and displays a system notification?
Using "react-native": "^0.34.0", "react-native-fcm": "^2.2.2",
@dslounge
Ok, I think I've got it now. Thanks for explaining this thoroughly.
Still, I'm totally mystified as to why data is handled in OnMessageReceived when it's passed on its own, but if it's passed with notification it gets handled in the extras of the intent.
This really goes against the principle of least astonishment, and sort of screws up what would otherwise be an intuitive API.

@kylebebak I'm glad you figured it out. It was really confusing for me as well, and I had to do a lot of trial and error. FCM is confusing, and this package's documentation is confusing as well. I'm also using this for iOS and it works on iOS 10 but it doesn't work on iOS 9 for some reason.
I think the main error is _wanting_ the firebase SDK to display the notification for you. It's really tempting to use the notification field on the payload. But the way they handle it is weird and doesn't have all the features you'd want. For my use case, I just want to display a banner in _all_ cases, I don't care if the app is in the foreground, background, killed. Firebase doesn't do that. :/
@kylebebak @dslounge please help me out with App is in Background state not in killed state..i have generated a presentLocalNotification in FCM.on('notification') event so when i receive notification when app is in background state, and when i click on notification FCM.on('notification') gets fired and i have 1 more notification triggered. how do i stop one more triggering.. pls help.
I don't think u can..You do however have two useful properties on the notification:
local_notification - tells u if the notification is local or remote.
opened_from_tray - if the notification is triggered because it was opened from tray or because u triggered it (locally or remotely)
Use these in the handler to ignore the events u don't need
@atlanteh can we close this?
Yes.
i got a solution for that.
just put below code in oncreate method of launcher activity.
if (bundle != null) {
String value = bundle.getString("key");
if (value != null) {
startActivity(new Intent(MainActivity.this, secActivity.class));
}
}
when app is in background or killed,FCM will not call onmessagerecieved method,but it will send data to system tray to display notification.so datapayload(sent from fcm console) will not be handled by onmessagerecieved method.when user click on notification,it will launch default activity of app and datapayload will be passed by intent .so making change in oncreate method of launcher activity(as above)we can get datapayload even when app is in background or killed.(ex key is sent by fcm console).when app is in foreground datapayload and will be handled by onmessagerecieved method of fcm service.
@atlanteh @dslounge @kylebebak Do any of you still use this library? I'm completely mystified. Despite specifying click_action and having the matching intent, no combination of notification and data currently fires off the main callback _at all_ on android, and I have no idea how to even go about debugging it. My app is receiving notifications in the background, but opening it from tray never, ever gets recognized.
@dslounge, Followed steps given by you but having same issue. Can you please help to figure out this issue?
Did anyone of you manage to fix it @jayneshshah @foggy1 ?
@foggy1 Same here. It works in one app, but not the other, and can't figure out why. The intent is registered and the background notification displays but clicking on it doesn't fire an event in Android. Works fine on iOS.
The strange thing is, if chrome developer console is open, then it works perfectly.
Most helpful comment
I didn't need to add an AppState listener whatsoever. To summarize, this is how I'm handling notifications in my app, there's 3 scenarios:
_App isn't Running:_
getInitialNotification()will fire. This is a promise that seems to always fire (with an empty notification if there isn't an initial notification), so you can show a loading screen and wait until this promise resolves to show a screen based on the notification_App is in Foreground:_
datapayload will get passed throughFCM.on('notification'event. If you want to show a system notification, here you need to trigger a manual, local notification. Be careful with this, since the local notification will fireFCM.on('notification'itself, and you could have a loop creating infinite notifications._App is in Background:_
click_action. The activity needs to be specified assingleTopand be able to handle that intent. The Activity will show and because it's already running,FCM.on('notification'event will fire.Hopefully that's helpful. That's been my experience with this package, and I'm running Android Marshmallow. It might be different on other phones.
To be honest with you, I think the right thing todo is to write my own Firebase listening service, use just
datanotifications, and fire local notifications when those are received. That's what I'm going to do eventually. Getting all this to work was a big pain, and it's mostly because of Firebase.More notes....
MainActivity.java"react-native": "0.33.0", "react-native-fcm": "2.3.0",Sample payload:
Relevant parts of
AndroidManifest(noticegeosocial.storyintent)