On iOS, after installing the app and launching it for the _first time_, I receive notifications when my app is in background but I can't reach onNotification() and onNotificationOpened() (after clicking on a notification) callbacks.
Then when closing the app (killing it) and upon relaunch, everything works fine.
Click To Expand
#### `package.json`:
{
"name": "xxx",
"version": "2.0.4",
"private": true,
"scripts": {
"postinstall": "npx jetify"
},
"dependencies": {
"@react-native-community/netinfo": "^4.4.0",
"@types/react-native-orientation": "^5.0.1",
"@types/react-native-video": "^3.1.5",
"@types/react-redux": "^7.1.1",
"axios": "^0.19.0",
"intl": "^1.2.5",
"jwt-decode": "^2.2.0",
"native-base": "^2.12.1",
"react": "16.8.6",
"react-native": "0.60.0",
"react-native-config": "^0.12.0",
"react-native-firebase": "^5.5.6",
"react-native-image-picker": "https://github.com/xxx/react-native-image-picker.git",
"react-native-image-zoom-viewer": "^2.2.26",
"react-native-intercom": "https://github.com/xxx/react-native-intercom.git",
"react-native-keyboard-aware-scroll-view": "^0.9.1",
"react-native-launch-navigator": "^1.0.6",
"react-native-modal-datetime-picker": "^7.5.0",
"react-native-orientation": "^3.1.3",
"react-native-pdf": "^5.1.4",
"react-native-sentry": "^0.43.2",
"react-native-simple-device-info": "^0.24.0",
"react-native-swiper": "^1.5.14",
"react-native-video": "^5.0.2",
"react-navigation": "^2.18.3",
"react-redux": "^7.1.0",
"redux": "^4.0.2",
"rn-fetch-blob": "^0.10.16"
},
"devDependencies": {
"@babel/core": "^7.5.0",
"@babel/runtime": "^7.5.2",
"@react-native-community/async-storage": "^1.4.0",
"@react-native-community/eslint-config": "^0.0.5",
"@types/jest": "^24.0.15",
"@types/react": "^16.8.23",
"@types/react-native": "^0.60.0",
"@types/react-navigation": "^3.0.7",
"@types/react-test-renderer": "^16.8.2",
"babel-jest": "^24.8.0",
"detox": "^14.9.2",
"eslint": "^6.0.1",
"jest": "^24.9.0",
"jetifier": "^1.6.4",
"metro-react-native-babel-preset": "^0.55.0",
"react-addons-test-utils": "^15.6.2",
"react-native-typescript-transformer": "^1.2.12",
"react-test-renderer": "16.8.6",
"ts-jest": "^24.0.2",
"typescript": "^3.5.3"
},
"jest": {
"presets": [
"react-native",
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript"
],
"moduleFileExtensions": [
"ts",
"tsx",
"js"
],
"transform": {
"^.+\\.(js)$": "<rootDir>/node_modules/babel-jest",
"\\.(ts|tsx)$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
},
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
"testPathIgnorePatterns": [
"\\.snap$",
"<rootDir>/node_modules/"
],
"cacheDirectory": ".jest/cache"
},
"rnpm": {
"assets": [
"app/assets/fonts/NotoSans",
"app/assets/fonts/TT-Norms"
]
},
"detox": {
"configurations": {
"ios.sim.debug": {
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/xxx.app",
"build": "RN_SRC_EXT=e2e.tsx,e2e.js xcodebuild -workspace ios/xxx.xcworkspace -scheme xxx -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
"type": "ios.simulator",
"device": {
"type": "iPhone X"
}
}
},
"test-runner": "jest"
}
}
#### `firebase.json` for react-native-firebase v6:
# N/A
#### `App.tsx` :
import React from 'react';
import firebase from 'react-native-firebase';
import { Notification, NotificationOpen } from 'react-native-firebase/notifications';
...
const CHANNEL_ID_KEY = 'notifications.channelId';
class App extends React.Component<Props, State> {
async componentDidMount() {
...
this.setupNotifications();
}
componentWillUnmount(): void {
this.unsubscribeFromNotificationsListeners();
}
setupNotifications = async () => {
this.checkForAppOpenedByNotification();
this.requestPermission();
this.createAndroidChannel();
this.createNotificationListeners();
};
async storeFCMToken() {
let fcmToken = await localStorage.getKey(constants.fcmToken);
if (!fcmToken) {
fcmToken = await firebase.messaging().getToken();
if (fcmToken) {
console.log('fcmToken', fcmToken);
await localStorage.saveKey(constants.fcmToken, fcmToken);
}
}
}
async requestPermission() {
try {
await firebase.messaging().requestPermission();
// permission is granted
this.storeFCMToken();
} catch (error) {
console.log('[Firebase] ERROR: Permission rejected.');
}
}
async createAndroidChannel() {
if (Platform.OS === 'android') {
const channel = new firebase.notifications.Android.Channel(
constants.FirebaseChannelId,
constants.FirebaseChannelName,
firebase.notifications.Android.Importance.Max
);
channel.setDescription(constants.FirebaseChannelDescription);
await localStorage.saveKey(CHANNEL_ID_KEY, channel.channelId);
await firebase.notifications().android.createChannel(channel);
}
}
createNotificationListeners() {
this.cancelNotificationListener = firebase.notifications().onNotification(async (notification: Notification) => {
const localNotification = new firebase.notifications.Notification()
.setNotificationId(notification.notificationId)
.setTitle(notification.title)
.setSubtitle(notification.subtitle || '')
.setBody(notification.body)
.setData(notification.data);
// Android only
if (Platform.OS === 'android') {
const channelId = await localStorage.getKey(CHANNEL_ID_KEY);
if (channelId) {
localNotification.android.setChannelId(channelId);
localNotification.android.setAutoCancel(true);
localNotification.android.setSmallIcon('ic_status_bar');
}
}
// iOS only
if (Platform.OS === 'ios') {
localNotification.ios.setLaunchImage('icon-83.5@2x');
}
try {
await firebase.notifications().displayNotification(localNotification);
} catch (e) {
console.log('[Firebase] ERROR: Can not display notification', e);
}
});
this.cancelNotificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen: NotificationOpen) => {
// Get information about the notification that was opened
const notification: Notification = notificationOpen.notification;
this.handleNotificationOpened(notification);
});
}
checkForAppOpenedByNotification = async () => {
const notificationOpen: NotificationOpen = await firebase.notifications().getInitialNotification();
if (notificationOpen) {
const notification: Notification = notificationOpen.notification;
this.handleNotificationOpened(notification);
}
}
handleNotificationOpened = (notification: Notification) => {
const { state, ...payload } = notification.data;
store.dispatch(navigateTo(state, payload));
}
unsubscribeFromNotificationsListeners = () => {
if (this.cancelNotificationListener) this.cancelNotificationListener();
if (this.cancelNotificationOpenedListener) this.cancelNotificationOpenedListener();
}
render() {
...
}
}
Click To Expand
#### `ios/Podfile`: - [ ] I'm not using Pods - [x] I'm using Pods and my Podfile looks like:
platform :ios, '9.0'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
target 'xxx' do
# Pods for xxx
pod 'React', :path => '../node_modules/react-native/'
pod 'React-Core', :path => '../node_modules/react-native/React'
pod 'React-DevSupport', :path => '../node_modules/react-native/React'
pod 'React-fishhook', :path => '../node_modules/react-native/Libraries/fishhook'
pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
pod 'React-RCTWebSocket', :path => '../node_modules/react-native/Libraries/WebSocket'
pod 'Firebase/Core', '~> 5.19.0'
pod 'GoogleIDFASupport', '~> 3.14.0'
pod 'Firebase/Messaging', '~> 5.19.0'
pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
# pod 'react-native-video', :path => '../node_modules/react-native-video'
pod 'react-native-video', :path => '../node_modules/react-native-video/react-native-video.podspec'
pod 'Intercom'
pod 'react-native-intercom', :path => '../node_modules/react-native-intercom'
target 'xxx' do
inherit! :search_paths
# Pods for testing
end
use_native_modules!
end
target 'xxx-tvOS' do
# Pods for xxx-tvOS
target 'xxx-tvOSTests' do
inherit! :search_paths
# Pods for testing
end
end
#### `AppDelegate.m`:
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <Firebase.h>
#import "RNFirebaseNotifications.h"
#import "Orientation.h"
#import "Intercom/intercom.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSString *intercomAppId = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"INTERCOM_APP_ID"];
NSString *intercomApiKey = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"INTERCOM_API_KEY"];
[Intercom setApiKey:intercomApiKey forAppId:intercomAppId];
[FIRApp configure];
[RNFirebaseNotifications configure];
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"xxx"
initialProperties:nil];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[Intercom setDeviceToken:deviceToken];
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
[[RNFirebaseNotifications instance] didReceiveLocalNotification:notification];
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return [Orientation getOrientation];
}
@end
Click To Expand
#### Have you converted to AndroidX? - [ ] my application is an AndroidX application? - [ ] I am using `android/gradle.settings` `jetifier=true` for Android compatibility? - [ ] I am using the NPM package `jetifier` for react-native compatibility? #### `android/build.gradle`:
// N/A
#### `android/app/build.gradle`:
// N/A
#### `android/settings.gradle`:
// N/A
#### `MainApplication.java`:
// N/A
#### `AndroidManifest.xml`:
<!-- N/A -->
Click To Expand
**`react-native info` output:**
System:
OS: macOS Mojave 10.14.6
CPU: (4) x64 Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
Memory: 21.11 MB / 8.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 10.16.3 - ~/.nvm/versions/node/v10.16.3/bin/node
Yarn: 1.15.2 - /usr/local/bin/yarn
npm: 6.9.0 - ~/.nvm/versions/node/v10.16.3/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1
Android SDK:
API Levels: 23, 25, 26, 27, 28
Build Tools: 27.0.3, 28.0.2, 28.0.3
System Images: android-26 | Google Play Intel x86 Atom, android-28 | Google Play Intel x86 Atom
IDEs:
Android Studio: 3.5 AI-191.8026.42.35.5791312
Xcode: 11.2.1/11B500 - /usr/bin/xcodebuild
npmPackages:
react: 16.8.6 => 16.8.6
react-native: 0.60.0 => 0.60.0
npmGlobalPackages:
react-native-cli: 2.0.1
- **Platform that you're experiencing the issue on**:
- [x] iOS
- [ ] Android
- [ ] **iOS** but have not tested behavior on Android
- [ ] **Android** but have not tested behavior on iOS
- [ ] Both
- **`react-native-firebase` version you're using that has this issue:**
- `5.5.6 | 5.6.0 (tried both)`
- **`Firebase` module(s) you're using that has the issue:**
- `notifications`
- **Are you using `TypeScript`?**
- `Y` & `^3.5.3`
Think react-native-firebase is great? Please consider supporting all of the project maintainers and contributors by donating via our Open Collective where all contributors can submit expenses. [Learn More]
React Native Firebase and Invertase on Twitter for updates on the library.notifications does not exist in RNFBv6 (see first pinned issue in the repo) so investing a lot of time troubleshooting it doesn't seem worthwhile - I suggest integrating react-native-push-notifications or similar for access to local notification APIs, use firebase messaging to send the push messages then RNPN to pop notifications and call your handlers
@mikehardy It's not v6 here but v5. I've actually tried two different versions which are 5.5.6 and 5.6.0.
I understand - the purpose of the comment was to think, what API do you want invest time in, making it all work? One with continuity or without?
@mikehardy It's just that it's the only thing that fails in my implementation right now and I hoped there was an easy fix or that someone could tell me about something I did wrong. I guess I'll try switching to react-native-push-notifications if there's no other option.
@mikehardy I've been struggling with similar issues where my iOS app simply does not receive notifications (only data-only messages). I really have reviewed the documentation very closely and have also built/run the swift native firebase messaging example, provisioned certs/setup APNs that way and everything works.
I simply cannot get RNF 5.6.x to receive/trigger onNotification on iOS (RN 0.61.x), no matter what everything simply comes in as a data-only message rather than a notification. It feels like the app is potentially registering a faulty APNs token in conjunction with the FCM token, but it's hard to debug where along the chain the problem occurs.
Thus, if the solution were to integrate both RNFB and RNPN, how could one get this to handle background notifications? If I'm not mistaken, does the app not only receive messages when it is in the foreground?

This functionality appears to be android only, thus I feel like the only solution is to use RNPN until the new notifications tool comes out of alpha?
even for ios there is a functionality hole with FCM and iOS on force-closed apps, they will never be woken up. The only solution there (from what I have read, not direct experience) is to send directly via APNS. The whole thing is tiresome to even think about it, I'd love to see a clean open demo repo with all these things integrated in a way that are tested and working but I'm exhausted with FCM personally (sorry...)
This functionality appears to be android only, thus I feel like the only solution is to use RNPN until the new notifications tool comes out of alpha?
Android allows you to handle background tasks, such as a receive a data payload & do something with it locally (e.g. display a notification).
Part of the reason we've not released an iOS version of Notifee yet is because we're still working on tapping this stuff on the head. iOS allows you to handle a "silent notification" when a content-available property is sent to the device, but the tricky part is executing JavaScript (and handling it well).
After banging my head on a wall for the last week and re-reviewing my code over and over and over and over, I realized my problem when I luckily stumbled over a warning where I realized my capabilities weren't set properly. I had added push capability but not Background Modes > Remote notifications.
I'm not sure why this would affect things since AFAIK it's not needed for push, but it did fix things. Also removing and re-setting the Push capability.
Now, everything is working nicely across both iOS and Android.
@mikehardy, sorry to interrupt, but I have seen your comments on a lot of threads like the one above and I wanted to you to shed some light on some confusion that I have.
You commented on a thread earlier, "_onNotification() is only triggered when a user taps a local notification while the app is in the foreground_."
For developers (possibly like @alancwoo) who want their setBadge to update in real time... would firebase.notifications().onNotification() be the optimal solution thus far? How do we deal with devices not running our app? What if the user is using another app?
Yeah, I've been struggling to understand all the corner cases myself, it's pretty subtle and intricate. Nearly unsupportable, actually, the problem domain is so complex.
my best advice is to not mix notifications and messages, which are different things in firebase-land. If you send FCM with JSON payload that has a notification component, the google firebase SDK will attempt to handle it, in some cases, in some ways, without complete control over appearance etc. Which in my view is confusing and makes everything had to think about.
I would send only "silent push" / "data only" messages. I would make sure they were handled well everywhere in all cases (you can even handle the iOS force-closed case if you send directly to APNs with special headers - https://github.com/invertase/react-native-firebase/issues/3095#issuecomment-581316199 ). So now you get real-time control when the messages is delivered to the device, and you do whatever you want (update badge, pop a notification, process things, etc).
Hello 馃憢, to help manage issues we automatically close stale issues.
This issue has been automatically marked as stale because it has not had activity for quite some time. Has this issue been fixed, or does it still require the community's attention?
This issue will be closed in 15 days if no further activity occurs.
Thank you for your contributions.
Closing this issue after a prolonged period of inactivity. If this is still present in the latest release, please feel free to create a new issue with up-to-date information.
I have the same problem here.
At first i tried to use RNPN , but it couldn't get any notification from firebase cloud messaging test function, was not working on ios.
So i tried to use RNFB 5.6.0. now it gets push notifcation when app is in background.
But can't handle any lisetners.. These are not being called.
How can i solve this problem?
componentDidMount() {
this.checkPermission();
this.createNotificationListeners();
}
componentWillUnmount() {
this.notificationListener;
this.notificationOpenedListener;
}
//Check whether Push Notifications are enabled or not
async checkPermission() {
const enabled = await firebase.messaging().hasPermission();
if (enabled) {
this.getToken();
} else {
this.requestPermission();
}
}
//Get Device Registration Token
async getToken() {
let fcmToken = await AsyncStorage.getItem('fcmToken');
if (!fcmToken) {
fcmToken = await firebase.messaging().getToken();
if (fcmToken) {
console.log('fcmToken:', fcmToken);
await AsyncStorage.setItem('fcmToken', fcmToken);
}
}
}
//Request for Push Notification
async requestPermission() {
try {
await firebase.messaging().requestPermission();
// If user allow Push Notification
this.getToken();
} catch (error) {
// If user do not allow Push Notification
console.log('Rejected');
}
}
async createNotificationListeners() {
console.log('[SPIDER] [APP] Creating Notification Listeners');
// If your app is in Foreground
this.notificationListener = firebase.notifications().onNotification((notification) => {
console.log('[SPIDER][APP][notification][1]');
const localNotification = new firebase.notifications.Notification({
show_in_foreground: true,
})
.setNotificationId(notification.notificationId)
.setTitle(notification.title)
.setBody(notification.body)
firebase.notifications()
.displayNotification(localNotification)
.catch(err => console.error(err));
});
this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen) => {
console.log('[SPIDER][APP][notification][2]');
const { title, body } = notificationOpen.notification;
console.log('onNotificationOpened:');
Alert.alert(title, body)
});
// If your app is closed
const notificationOpen = await firebase.notifications().getInitialNotification();
if (notificationOpen) {
console.log('getInitialNotification:');
}
// For data only payload in foreground
this.messageListener = firebase.messaging().onMessage((message) => {
//process data message
console.log("Message", JSON.stringify(message));
});
}
Just wanted to update everyone, as far as I am aware this issue is still unresolved. I ended up having to abandon this task because I couldn't find a solution. I am researching now for a solution.
Anyone have solution here ?? i can't access data in notification+data payload because listener onNotification and onNotificationOpened never trigger on IOS platform
@fspider how about you ??
I have done PN without using RNFB. Just only using RNPN.
But for IOS platform, send messages without using FB cloud message.
(android) PHP backend -> FB cloud messaging -> Android RNPN
(IOS) PHP backend ->APNS -> IOS RNPN
@fspider Your solotion can handle data on notification+data payload right ??
Most helpful comment
Just wanted to update everyone, as far as I am aware this issue is still unresolved. I ended up having to abandon this task because I couldn't find a solution. I am researching now for a solution.