Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔥 iOS Background Notifications Not Being Displayed #3805

Closed
2 of 10 tasks
dooleyb1 opened this issue Jun 19, 2020 · 42 comments
Closed
2 of 10 tasks

🔥 iOS Background Notifications Not Being Displayed #3805

dooleyb1 opened this issue Jun 19, 2020 · 42 comments
Labels
plugin: messaging FCM only - ( messaging() ) - do not use for Notifications Type: Stale Issue has become stale - automatically added by Stale bot

Comments

@dooleyb1
Copy link

dooleyb1 commented Jun 19, 2020

Issue

I am currently performing a version upgrade from "react-native-firebase": "^5.5.5" to the latest libraries following the migration documentation (https://rnfirebase.io/migrating-to-v6). I have successfully migrated and tested all other Firebase libraries that my application uses however, I am having an issue with background notifications not being displayed on iOS devices using the messaging() library. Foreground notifications work as expected on both Android & iOS and background notifications also work on Android as expected.

Firstly, when my app is initialised, the following code is ran:

// Check if user has Push Notifications enabled
  async checkPushNotificationPermission() {
    crashlytics().log('[Initialising][checkPushNotificationPermission] - Checking users push notification permissions...');

    return new Promise(async (resolve, reject) => {
      try {
        
        let registerResult = await messaging().registerDeviceForRemoteMessages();
        
        const authorizationStatus = await messaging().requestPermission();

        if (authorizationStatus === messaging.AuthorizationStatus.AUTHORIZED) {
          console.log('User has notification permissions enabled.');
        } else if (authorizationStatus === messaging.AuthorizationStatus.PROVISIONAL) {
          console.log('User has provisional notification permissions.');
        } else {
          console.log('User has notification permissions disabled');
        }

        crashlytics().log(`[Initialising][checkPushNotificationPermission] - authorizationStatus == ${authorizationStatus}`);
        resolve();
      } catch (error) {
        console.error(error);
      }
    })
  }

And following this the Firebase messaging listeners are created. In particular the background listener below is not being triggered:

messaging().setBackgroundMessageHandler(async remoteMessage => {
    console.log('Message handled in the background!', remoteMessage);
   //showAlert('Background Notification', 'Background Notification');
});

However, the foreground listener such as below fires as expected when the app is running in the foregroud:

messaging().onMessage((remoteMessage) => {
    console.log(`messaging.onMessage`);
    console.log(remoteMessage);
    //showAlert('messaging.onMessage', 'messaging.onMessage');
});

Happy to provide any more necessary/useful debugging information upon request.

Note: I have read through the following issues and applied many of the suggested possible solutions and have yet to come across one that works for me to fix this issue.


Project Files

Javascript

Click To Expand

package.json:

{
    "name": "bounceapp",
    "version": "31.0.0",
    "private": true,
    "devDependencies": {
        "babel-jest": "24.9.0",
        "babel-plugin-module-resolver": "^3.2.0",
        "fs-extra": "^6.0.1",
        "jest": "^24.9.0",
        "metro-react-native-babel-preset": "0.56.0",
        "react-test-renderer": "16.9.0",
        "replace-in-file": "^3.4.2"
    },
    "scripts": {
        "androidOld": "react-native run-android",
        "android": "npx jetify && npx react-native run-android",
        "ios": "react-native run-ios --simulator=\"iPhone 11\"",
        "ios-7": "react-native run-ios --simulator=\"iPhone 7\"",
        "ios-6s": "react-native run-ios --simulator=\"iPhone 6s\"",
        "ios-5": "react-native run-ios --simulator=\"iPhone 5s\"",
        "ios-X": "react-native run-ios --simulator=\"iPhone X\"",
        "ios-release": "react-native run-ios --configuration Release --simulator=\"iPhone X\"",
        "ios-staging": "react-native run-ios --configuration Staging --simulator=\"iPhone X\"",
        "brandons-phone": "react-native run-ios --configuration Debug --device \"brandons-phone\"",
        "apk": "cd android && ./gradlew assembleRelease",
        "android-build": "cd android && ./gradlew bundleRelease",
        "start": "react-native start",
        "hard-reinstall": "rm -rf node_modules && rm -rf ios/Pods && rm -f ios/Podfile.lock && rm -rf ios/build && npm install && cd ios && pod install && cd .."
    },
    "jest": {
        "preset": "react-native"
    },
    "dependencies": {
        "@freakycoder/react-native-helpers": "^0.1.0",
        "@react-native-community/datetimepicker": "^2.1.0",
        "@react-native-community/netinfo": "^5.3.0",
        "@react-native-firebase/app": "^7.2.1",
        "@react-native-firebase/auth": "^8.0.5",
        "@react-native-firebase/crashlytics": "^7.1.5",
        "@react-native-firebase/messaging": "^7.1.5",
        "@react-native-firebase/remote-config": "^7.1.4",
        "@rimiti/react-native-toastify": "^1.2.0",
        "axios": "^0.18.0",
        "jail-monkey": "^2.3.2",
        "jetifier": "^1.6.3",
        "lodash": "^4.17.11",
        "lottie-ios": "^3.1.3",
        "lottie-react-native": "^3.3.2",
        "moment": "^2.24.0",
        "native-base": "^2.12.1",
        "prop-types": "^15.7.2",
        "react": "^16.9.0",
        "react-native": "^0.61.0",
        "react-native-animatable": "^1.3.3",
        "react-native-app-intro-slider": "^3.0.0",
        "react-native-camera": "^3.16.0",
        "react-native-code-push": "^6.0.0",
        "react-native-collapsible": "^1.5.1",
        "react-native-country-picker-modal": "^1.10.0",
        "react-native-device-info": "^5.4.3",
        "react-native-drag-sort": "^1.3.6",
        "react-native-elements": "^1.2.7",
        "react-native-fs": "^2.16.6",
        "react-native-gesture-handler": "^1.5.3",
        "react-native-gradient-header": "^0.2.0",
        "react-native-image-picker": "^2.3.1",
        "react-native-keyboard-aware-scroll-view": "^0.9.1",
        "react-native-linear-gradient": "^2.5.6",
        "react-native-modal": "^11.5.6",
        "react-native-modal-datetime-picker": "^8.1.1",
        "react-native-navigation": "4.6.0",
        "react-native-permissions": "^2.0.9",
        "react-native-phone-input": "^0.2.4",
        "react-native-picker-select": "^6.3.3",
        "react-native-progress": "git+https://github.com/oblador/react-native-progress.git",
        "react-native-qrcode-scanner": "^1.3.1",
        "react-native-qrcode-svg": "^6.0.3",
        "react-native-segmented-control-tab": "^3.4.1",
        "react-native-snap-carousel": "^3.8.4",
        "react-native-ssl-pinning": "^1.4.1",
        "react-native-svg": "^12.0.3",
        "react-native-swipe-gestures": "git+https://github.com/thegamenicorus/react-native-swipe-gestures.git",
        "react-native-switch-toggle": "^1.1.0",
        "react-native-toast-native": "git+https://github.com/onemolegames/react-native-toast-native",
        "react-native-vector-icons": "^6.6.0",
        "react-native-zoom-image": "^0.1.2",
        "react-redux": "^6.0.0",
        "redux": "^4.0.1",
        "redux-thunk": "^2.3.0"
    }
}

firebase.json for react-native-firebase v6:

{
    "react-native": {

      "crashlytics_ndk_enabled": true,
      "crashlytics_debug_enabled": true,
      "crashlytics_disable_auto_disabler": false,
      "crashlytics_auto_collection_enabled": true,
  
      "messaging_ios_auto_register_for_remote_messages": true
    }
  }

iOS

Click To Expand

ios/Podfile:

  • I'm not using Pods
  • I'm using Pods and my Podfile looks like:
# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

target 'bounceapp' do
  # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
  # use_frameworks!

  # React Native v0.60 pods
  pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
  pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
  pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
  pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
  pod 'React', :path => '../node_modules/react-native/'
  pod 'React-Core', :path => '../node_modules/react-native/'
  pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
  pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
  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-Core/RCTWebSocket', :path => '../node_modules/react-native/'
  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 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon"
  pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
  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'
  
  # Pods for bounceapp
  pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons'
  
  pod 'Fabric', '~> 1.10.2'

  permissions_path = '../node_modules/react-native-permissions/ios'
  pod 'Permission-Camera', :path => "#{permissions_path}/Camera.podspec"
  pod 'Permission-Notifications', :path => "#{permissions_path}/Notifications.podspec"

  use_native_modules!

  pod 'jail-monkey', :path => '../node_modules/jail-monkey'

  pod 'react-native-image-picker', :path => '../node_modules/react-native-image-picker'

  post_install do |installer|
    installer.pods_project.targets.each do |target|

      # The following is needed to ensure the "archive" step works in XCode.
      # It removes React & Yoga from the Pods project, as it is already included in the main project.
      # Without this, you'd see errors when you archive like:
      # "Multiple commands produce ... libReact.a"
      # "Multiple commands produce ... libyoga.a"

      targets_to_ignore = %w(React yoga)
      
      if targets_to_ignore.include? target.name
        target.remove_from_project
      end
    end
  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 <CodePush/CodePush.h>

#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>

#import <ReactNativeNavigation/ReactNativeNavigation.h>

#import <Firebase.h>
#import <FirebaseMessaging.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  
  [FIRApp configure];
  [[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
  
  NSURL *jsCodeLocation;


  #ifdef DEBUG
    jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
  #else
    jsCodeLocation = [CodePush bundleURL];
  #endif



  [ReactNativeNavigation bootstrap:jsCodeLocation launchOptions:launchOptions];
  
  return YES;
}

@end


Android

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 -->


Environment

Click To Expand

react-native info output:

System:
    OS: macOS 10.15.1
    CPU: (8) x64 Intel(R) Core(TM) i7-8557U CPU @ 1.70GHz
    Memory: 51.00 MB / 8.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 12.13.1 - /usr/local/bin/node
    Yarn: 1.19.2 - /usr/local/bin/yarn
    npm: 6.12.1 - /usr/local/bin/npm
  SDKs:
    iOS SDK:
      Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1
    Android SDK:
      API Levels: 23, 26, 28, 29
      Build Tools: 28.0.3, 29.0.2
      System Images: android-29 | Google APIs Intel x86 Atom, android-29 | Google Play Intel x86 Atom
  IDEs:
    Android Studio: 3.5 AI-191.8026.42.35.5791312
    Xcode: 11.3/11C29 - /usr/bin/xcodebuild
  npmPackages:
    react: ^16.9.0 => 16.13.1
    react-native: ^0.61.0 => 0.61.5
  npmGlobalPackages:
    react-native-cli: 2.0.1
  • Platform that you're experiencing the issue on:
    • 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:
    • See package.json for submodule version numbers
  • Firebase module(s) you're using that has the issue:
    • Messaging
  • Are you using TypeScript?
    • No


@dooleyb1 dooleyb1 changed the title (:fire:) iOS Background Notifications Not Being Displayed 🔥 iOS Background Notifications Not Being Displayed Jun 19, 2020
@dooleyb1 dooleyb1 changed the title 🔥 iOS Background Notifications Not Being Displayed :fire iOS Background Notifications Not Being Displayed Jun 19, 2020
@dooleyb1 dooleyb1 changed the title :fire iOS Background Notifications Not Being Displayed 🔥 iOS Background Notifications Not Being Displayed Jun 19, 2020
@russellwheatley russellwheatley added the plugin: messaging FCM only - ( messaging() ) - do not use for Notifications label Jun 19, 2020
@mikehardy
Copy link
Collaborator

background listener needs to be set as early in init as possible, like in index.js or App.js, it must be before you use AppRegistry to add the app view etc - if I understand your provided information correctly, it may not be in the correct place in app init https://rnfirebase.io/messaging/usage#background--quit-state-messages

@petetastic
Copy link

petetastic commented Jun 19, 2020

I'm getting the same exact issue. Foreground notifications work, but background notifications don't do anything (I receive the notification, but clicking on it launches the app without doing anything). I'm working on a real device and have put my handler as early as possible, in index.js like this:

import {AppRegistry} from 'react-native';
import messaging from '@react-native-firebase/messaging';
import App from './App';
import {name as appName} from './app.json';

// Register background handler
messaging().setBackgroundMessageHandler(async remoteMessage => {
  console.log('Message handled in the background!', remoteMessage);
});

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

When I click on the notification, I get this from XCode:

nw_read_request_report [C1] Receive failed with error "Software caused connection abort"
nw_read_request_report [C1] Receive failed with error "Software caused connection abort"
Connection 2: received failure notification
nw_flow_add_write_request [C2 192.168.86.242:8081 failed channel-flow (satisfied (Path is satisfied), interface: en0, ipv4, dns)] cannot accept write requests
nw_write_request_report [C2] Send failed with error "Socket is not connected"

@mikehardy
Copy link
Collaborator

In my experience with messaging, no one has the exact same issue. My eyes glaze over now when I see that. I literally stop reading. Make no assumptions about your issue if you want to fix it, because every issue seems to be some unique failure mode.

Perhaps this is a difference between direct channel and APNs, see my comment here #3530 (comment)

@ferocedev
Copy link

ferocedev commented Jun 22, 2020

Me, too.
It does not work on background only on ios.
It works when you run the app.
스크린샷 2020-06-22 오전 10 18 02

--- package.json
"@react-native-community/push-notification-ios": "1.2.2",
"@react-native-firebase/app": "7.2.1",
"@react-native-firebase/messaging": "7.1.5",
"react": "16.11.0",
"react-native": "0.62.2",
"react-native-push-notification": "3.5.2"

@ErickArciniega
Copy link

any update?

@dooleyb1
Copy link
Author

dooleyb1 commented Jun 29, 2020

Update:

@mikehardy You are correct, I had initialised my background listeners after the AppRegistry of views etc. I have moved this to the earliest point possible in the initialisation of my application and it seems to not have changed much.

I also added the code suggested by @samparmenter here
([FIRMessaging messaging].autoInitEnabled = YES;) to my AppDelegate.m file which didn't seem to help also.

The code I am using to send the message to device is using the Firebase Admin Node.JS SDK and is as follows:

  let fcmToken = userData['fcmToken'];

  console.log(`Sending message to users device...`);

  // See - https://firebase.google.com/docs/reference/admin/node/admin.messaging.Messaging#send
  let messagingConditionResponse = await messaging.sendToDevice(
    // Device registration token (fcmToken)
    fcmToken,
    // MessagingPayload
    {
      data: {
        "Test data key": "Test data value"
      },
      notification: {
        title: "New Rewards Available!",
        body: "Check out the Shop in-app to see our new rewards!"
      }
    },
    // MessagingOptions
    {
      contentAvailable: true,
      dryRun: false,
      mutableContent: false,
      priority: "high"
    }
  );

  console.log(`Finished sending message...`);
  console.log(messagingConditionResponse);

This message is being received in the foreground no problem however nothing is being displayed whilst in the background. When I bring the app to the foreground the onMessage handler then fires picking up the message.

I have been running on device (iPhone 7) and the app does not produce any output to the XCode console whilst running in the background or quit.

@nicoceledon
Copy link

Just to clear something, you mean that that the notification doesn't show on the notification area on iOS?

@dooleyb1
Copy link
Author

dooleyb1 commented Jul 2, 2020

Just to clear something, you mean that that the notification doesn't show on the notification area on iOS?

The notification is not displayed i.e on the top of the mobile screen when any notification is received. This happens in both the background and quit state.

@nicoceledon
Copy link

Do you have an apple developers license?

@Wmeng98
Copy link

Wmeng98 commented Jul 4, 2020

I'm having a similar issue. I can receive foreground notifications via onMessage handler and my background callback handler is also called on background messages via setBackgroundMessageHandler.

However, the notification banner isn't being shown nor does it show up in the notification tray on IOS.
Everything works fine on Android as well :).

If both my foreground/background handlers are called as expected, I must've setup IOS cloud messaging correctly to some extent.

Really loving this module so far though!

@mikehardy
Copy link
Collaborator

@Wmeng98 I believe that is functioning as the upstream SDKs define it should function. For local notification handling on foreground you need a local notification package. Those are related but both enormous sets of functionality largely separate from react-native-firebase so this module doesn't cover them.

@Wmeng98
Copy link

Wmeng98 commented Jul 5, 2020

@Wmeng98 I believe that is functioning as the upstream SDKs define it should function. For local notification handling on foreground you need a local notification package. Those are related but both enormous sets of functionality largely separate from react-native-firebase so this module doesn't cover them.

Thanks for the quick reply @mikehardy!
Yep, I'm aware that local notification handling isn't covered by the module.
My concerning issue is that a notification banner isn't shown when the the app is in the background. However, the setBackgroundMessageHandler is still called as expected. Which is kind of crazy.

I've also tested push notifications via curl to apns push server

curl -v  \
     -d '{"aps":{"alert":"hello", "badge":10}}' \
     -H "apns-topic: <bundle id>"  \
     -H "authorization: bearer  <JWT token>"  \
     --http2 \
https://api.sandbox.push.apple.com/3/device/<APNS device token>

Funny thing is I can see the badge update but no notification banner while in background state of the app.
If the message handler is being called as expected, then the message must've been received by the app from APNS.
Maybe I could add handlers in the AppDelegate.m to log and double check but any tips on debugging notification banner issues?

Thanks!

P.S My device is running iOS 13.5.1.

@mikehardy
Copy link
Collaborator

Maybe it is just a matter of setting the right APNS headers, a priority or critical or similar? I'm not good enough to know it off the top of my head but there are mentions of APNS headers related to notification displaying or not all over - should pop up in a search and might work with experimentation

@Wmeng98
Copy link

Wmeng98 commented Jul 6, 2020

Yea, adding the right APNS headers helped me get the setBackgroundMessageHandler callback working on app background.

After some more googling, It turns out I hadn't requested the right permissions using firebase.messaging().requestPermission(). I never bothered confirming that the proper permission settings were requested since the dialog never showed up and my message handlers were being called.

If you want to check authorization natively on IOS (objective-c), include the following in your AppDelegate.m

// Make sure to import UserNotifications
#import <UserNotifications/UserNotifications.h>

// Include inside didFinishLaunchingWithOptions
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert)
            completionHandler:^(BOOL granted, NSError * _Nullable error) {
                if (!error) {
                    NSLog(@"request succeeded!");
                }
            }];

Though this should be done via the requestPermission() method in firebase messaging. Maybe try to explicitly enable alert, badge, and sound settings? They are true by default.
https://rnfirebase.io/messaging/ios-permissions

Thanks again for the quick feedback @mikehardy 👍

@mikehardy
Copy link
Collaborator

I actually encourage everyone to use react-native-permissions - https://github.com/react-native-community/react-native-permissions/ - it is by far the best way to manage permissions IMHO - glad you got your messages through, I want to pass the credit for idea of the headers right along to @forbesgillikin I got the idea from there (but didn't have the link handy) and now there's even a PR #3882 - this stuff is just plain difficult, but we're getting through it together. Cheers

@Shweta-Porwal
Copy link

I tried the options suggested by Wmeng98 but still no luck. I am able to get notifications in foreground but it is not working in background. One more observation : I kept the app in background, send a notification , now when I open the app onMessage() handler is getting called which is not expected as my app was in background. I tried this with two different version of react-native-firebase/messaging. 6.4.0-rc4 and 7.3.2. With both versions I am getting same behaviour. It would be really helpful if someone let me know what I am missing here to add background notification for iOS ?

@Wmeng98
Copy link

Wmeng98 commented Jul 7, 2020

You added the proper apns headers to your message as suggested above @Shweta-Porwal?
How are you sending push notifications? FCM console? Admin SDK?

@Shweta-Porwal
Copy link

Shweta-Porwal commented Jul 7, 2020 via email

@mikehardy
Copy link
Collaborator

The only way to properly test cloud messaging is to craft the JSON yourself and send it via firebase-admin, it's not that with the console "we don't have to write any header", it's that with the console you don't even get the chance, so you don't stand a chance of getting things exactly right

@Shweta-Porwal
Copy link

{
"to" : "myDeviceFCMToken",
"notification" : {
"body" : "Test Message",
"title" : "React Native Firebase",
"content_available" : true,
"priority" : "high"
},
"data" : {
"body" : "Test Message",
"title" : "React Native Firebase",
"content_available" : true,
"priority" : "high"
},
"aps" : {
"content_available" : true
}
}
This is the message body which I am sending from postman and getting notifications on my app when app is in foreground. But nothing comes when app is in background.

@mikehardy
Copy link
Collaborator

@Shweta-Porwal read the comments above carefully, confirm you have the permission granted per above and follow the link to the PR for the documentation and add the appropriate headers - there is already info in this thread that seems important and is not included in the JSON you posted, which makes me think this will be an inefficient use of my time helping troubleshoot - don't do that or I will not pay attention going forward

@forbesgillikin
Copy link
Contributor

forbesgillikin commented Jul 7, 2020

Your request is malformed and does not include the APNs headers that are necessary to push data-only messages in the background on iOS. Your request should look like

{
"to" : //device fcm token,
"notification" : {
"data" : {
"body" : "Test Message",
"title" : "React Native Firebase",
},
"aps" : {
"content_available" : 1
}
}

With

"apns-push-type": "background",
"apns-priority": "5",
"apns-topic": // your app bundle identifier

As headers in the request.

Using Postman will require a different json block than what is described in the RNFirebase docs. Either use the Node Admin SDK and use the RNFirebase documentation or become familiar with the FCM and APNs documentation

@harrydema
Copy link

I am gettting crazy to make it work on background or quit mode on IOS. The notifications do work on foreground.

Android notifications work perfect.

This is my code:

AppDelegate.m

#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>

#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>

#import <Firebase.h>

static void InitializeFlipper(UIApplication *application) {
  FlipperClient *client = [FlipperClient sharedClient];
  SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
  [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
  [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
  [client addPlugin:[FlipperKitReactPlugin new]];
  [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
  [client start];
}
#endif

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }
  [FIRMessaging messaging].autoInitEnabled = YES;
  #ifdef FB_SONARKIT_ENABLED
    InitializeFlipper(application);
  #endif

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"TestPN"
                                            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;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

@end

index.js

/**
 * @format
 */

import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import messaging from '@react-native-firebase/messaging';
import notifee, { AndroidImportance } from '@notifee/react-native';

async function onMessageReceived(message) {
  await notifee.createChannel({
    id: 'default',
    name: 'Default',
    importance: AndroidImportance.HIGH,
  });

  notifee.displayNotification(JSON.parse(message.data.notifee));

  notifee.incrementBadgeCount();
}

notifee.setBadgeCount(0);

messaging().requestPermission();

if (!messaging().isDeviceRegisteredForRemoteMessages) {
  messaging().registerDeviceForRemoteMessages();
}

messaging().onMessage(onMessageReceived);
messaging().setBackgroundMessageHandler(onMessageReceived);

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

App.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow strict-local
 */

import React, { useEffect } from 'react';
import messaging from '@react-native-firebase/messaging';
import {
  SafeAreaView,
  StyleSheet,
  ScrollView,
  View,
  Text,
  StatusBar,
} from 'react-native';
import Clipboard from '@react-native-community/clipboard'

import {
  Header,
  LearnMoreLinks,
  Colors,
  DebugInstructions,
  ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';

const App: () => React$Node = () => {
  useEffect(() => {
    // Get the device token
    messaging()
      .getToken()
      .then(token => {
        return Clipboard.setString(token);
      });

    // Listen to whether the token changes
    return messaging().onTokenRefresh(token => {
      return Clipboard.setString(token);
    });
  }, []);
  return (
    <>
      <StatusBar barStyle="dark-content" />
      <SafeAreaView>
        <ScrollView
          contentInsetAdjustmentBehavior="automatic"
          style={styles.scrollView}>
          <Header />
          {global.HermesInternal == null ? null : (
            <View style={styles.engine}>
              <Text style={styles.footer}>Engine: Hermes</Text>
            </View>
          )}
          <View style={styles.body}>
            <View style={styles.sectionContainer}>
              <Text style={styles.sectionTitle}>Step One</Text>
              <Text style={styles.sectionDescription}>
                Edit <Text style={styles.highlight}>App.js</Text> to change this
                screen and then come back to see your edits.
              </Text>
            </View>
            <View style={styles.sectionContainer}>
              <Text style={styles.sectionTitle}>See Your Changes</Text>
              <Text style={styles.sectionDescription}>
                <ReloadInstructions />
              </Text>
            </View>
            <View style={styles.sectionContainer}>
              <Text style={styles.sectionTitle}>Debug</Text>
              <Text style={styles.sectionDescription}>
                <DebugInstructions />
              </Text>
            </View>
            <View style={styles.sectionContainer}>
              <Text style={styles.sectionTitle}>Learn More</Text>
              <Text style={styles.sectionDescription}>
                Read the docs to discover what to do next:
              </Text>
            </View>
            <LearnMoreLinks />
          </View>
        </ScrollView>
      </SafeAreaView>
    </>
  );
};

const styles = StyleSheet.create({
  scrollView: {
    backgroundColor: Colors.lighter,
  },
  engine: {
    position: 'absolute',
    right: 0,
  },
  body: {
    backgroundColor: Colors.white,
  },
  sectionContainer: {
    marginTop: 32,
    paddingHorizontal: 24,
  },
  sectionTitle: {
    fontSize: 24,
    fontWeight: '600',
    color: Colors.black,
  },
  sectionDescription: {
    marginTop: 8,
    fontSize: 18,
    fontWeight: '400',
    color: Colors.dark,
  },
  highlight: {
    fontWeight: '700',
  },
  footer: {
    color: Colors.dark,
    fontSize: 12,
    fontWeight: '600',
    padding: 4,
    paddingRight: 12,
    textAlign: 'right',
  },
});

export default App;

Capabilities eanbled
image

Postman request (Added all the content_available possibilities as I was. not sure which one. should I use)

{
	"to" : "dKxdtiyWmUDCqt-0m0GTmF:APA91bFYwxxNrrjOE1MxbCTHcl6hMu7h6eabECZBlSD_DpVufesvsw7BkToRJ_v9rJEmPxklAwOS4sdPujYQGXW92bQ9r8g4t-LrAYm5PbKBjjNLXX6CfT-mA3hRFkKrhcA11UxmMfDh",
	"priority": "high",
	"content_available": true,
	"content-available": true,
	"aps" : {
		"content_available" : 1
	},
	"data": {
	    "notifee": {
	      "title": "Test",
	      "subtitle": "Test",
	      "body": "This message was sent via FCM! 5",
	      "android": {
	        "channelId": "default",
	        "importance": 4,
	        "groupId": "1234"
	      }
	 }
  }
}

Permissions are enabled
image

@harrydema
Copy link

I posted my problem in new ticket:

#3969

@stale
Copy link

stale bot commented Aug 15, 2020

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.

@stale stale bot added the Type: Stale Issue has become stale - automatically added by Stale bot label Aug 15, 2020
@davx1992
Copy link
Contributor

@mikehardy having same issue. Errors are thrown when app is backgrounded. When I send first message, it is not shown and this error is thrown. When next message is sent, previous notification is handled by background handler, so it is one message lag. When I open app latest message is handled. Strangest part here is, that when I enable Background location tracking - Expo Location package, and repeat the same, no error is thrown and each message is handled. Have googled everywhere but no luck to identify what is the problem.

Maybe you can suggest me something, were can I look or troubleshoot this.
As of now receiving these errors: nw_read_request_report [C2] Receive failed with error "Software caused connection abort"
Having these packages:
"@react-native-firebase/app": "^8.4.0",
"@react-native-firebase/iid": "^7.4.1",
"@react-native-firebase/messaging": "^7.8.1",

@stale stale bot removed the Type: Stale Issue has become stale - automatically added by Stale bot label Aug 28, 2020
@forbesgillikin
Copy link
Contributor

forbesgillikin commented Aug 28, 2020

@mikehardy having same issue. Errors are thrown when app is backgrounded. When I send first message, it is not shown and this error is thrown. When next message is sent, previous notification is handled by background handler, so it is one message lag. When I open app latest message is handled. Strangest part here is, that when I enable Background location tracking - Expo Location package, and repeat the same, no error is thrown and each message is handled. Have googled everywhere but no luck to identify what is the problem.

Maybe you can suggest me something, were can I look or troubleshoot this.

As of now receiving these errors: nw_read_request_report [C2] Receive failed with error "Software caused connection abort"

Having these packages:

    "@react-native-firebase/app": "^8.4.0",

    "@react-native-firebase/iid": "^7.4.1",

    "@react-native-firebase/messaging": "^7.8.1",

This error looks related to Xcode not Firebase.

https://stackoverflow.com/questions/43527115/xcode-error-connecting-to-simulator-software-caused-connection-abort

Also, iOS simulators will not handle notifications. They must be tested on a real device.

@davx1992
Copy link
Contributor

@forbesgillikin checked link u provided. As I see I have only one version Xcode, also done mac restart, so no success on this. Were running app on device, not simulator.

@mikehardy
Copy link
Collaborator

Maybe use this pull request for inspiration and add to the constant wait even more? 415dba4

@davx1992
Copy link
Contributor

@mikehardy @compojoom so make some investigation, and understood that issue is with this line:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t) (6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[RNFBRCTEventEmitter shared] sendEventWithName:@"messaging_message_received_background" body:[RNFBMessagingSerializer remoteMessageUserInfoToDict:userInfo]];
});

when I take it out, and leave without dispatch_after it works. Also what I found out, that dispatch_after is not triggered on first message, after it is backgrounded.
I am not skilled with Obj.c. maybe you have any idea, what could cause such behaviour?

@mikehardy
Copy link
Collaborator

I would like to keep information related to that line centralized on the issue I just cross-posted to. It is a specific issue.
Other people seeing problems by just missing content-available etc are much simpler cases and handled already on this thread

@stale
Copy link

stale bot commented Oct 4, 2020

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.

@stale stale bot added the Type: Stale Issue has become stale - automatically added by Stale bot label Oct 4, 2020
@stale
Copy link

stale bot commented Nov 1, 2020

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.

@stale stale bot closed this as completed Nov 1, 2020
@codefreak13
Copy link

I got this working on iOS 13 and 14 by changing the p8 APN auth certificate on firebase console cloud messaging to p12 certificate generated from the Push Notifications feature under the app's provisioning profile in the apple developer account

@furqan-fabtechsol
Copy link

iOS Background Notifications Not Being Displayed in React Native App
Description
I'm currently developing a React Native application and using Firebase Cloud Messaging (FCM) to handle notifications. The notifications work perfectly when the app is in the foreground. However, when the app is in the background, notifications are received, but the data payload is not being delivered to the app.

Environment
React Native Version: 0.73.6
Firebase Version: 20.3.0 (app), 20.3.0 (messaging)
@notifee/react-native Version: 7.8.2
Xcode Version: (specify your version)
iOS Version: (specify the iOS version you are testing on)
Testing on Real Device: Yes
Issue Details
Foreground Notifications: Working as expected, receiving both notification and data payloads.
Background Notifications: Notifications are received, but the data payload is not being delivered or handled by the app.
Steps Taken
AppDelegate Configuration: Configured as per the official documentation for handling notifications.
Permissions and Background Modes: Enabled background modes and configured permissions as required.
Testing: Verified on a real iOS device.
Despite these steps, the data payload is not being delivered in the background. Any guidance or solutions to resolve this issue would be greatly appreciated.

@mohamedshawky982
Copy link

For me when sending data-only notifications and the app is in the background it doesn't work on a simulator but works on Real Devices.

@Satyam-code143
Copy link

Hi @furqan-fabtechsol ,
Have you found the solution?

Hi @mohamedshawky982 ,
Can you please share the data-only object body that you used to send from the backend? Also, the frontend changes that you made in index.js and if some changes made in Appdelegate.mm.

Thank you!

@furqan-fabtechsol
Copy link

furqan-fabtechsol commented Aug 28, 2024

Hi @furqan-fabtechsol , Have you found the solution?

Hi @mohamedshawky982 , Can you please share the data-only object body that you used to send from the backend? Also, the frontend changes that you made in index.js and if some changes made in Appdelegate.mm.

Thank you!

My payload is as given below

def send_multicast_message(data, offline_users):
    tokens = get_tokens(offline_users)
    print(tokens)
    title = data.get("type", "")
    if title not in ["ChatSeen", "ChatDelivered"]:
        content_available = True if title in ["MessageReact", "ChatMessage"] else False
        print(content_available,"--")
        data_str = json.dumps(data)
        message_data = {
            "data": data_str,  # Custom content_type for the message
            "priority": "high"  # Custom priority key
            }  # Convert the data to a JSON string
        apns_config = APNSConfig(
            # headers={
            # "apns-priority": "10",  # '10' for high priority, '5' for normal
            # "apns-expiration": "0"  # Immediate expiration if not delivered
            #     },
            payload=APNSPayload(
                aps=Aps(
                    content_available=content_available,
                    mutable_content=True,  # Allows modification on the device side
                ),
                custom_data=message_data,
            ),
        )
        if tokens:
            multicast_message = MulticastMessage(
                # notification=messaging.Notification(
                #     title="title",
                #     body="body",
                # ),
                tokens=tokens,  # List of device tokens
                data=message_data,
                apns=apns_config,
            )
            response = messaging.send_multicast(multicast_message)
            print(response)
        else:
            print("No tokens found")
    else:
        print("Message type ChatDelivered and ChatSeen does not require a notification")
        
        

Apdelegate.mm file is as given below

#import "AppDelegate.h"

#import <React/RCTBundleURLProvider.h>
#import <React/RCTLinkingManager.h>
#import <Firebase.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
 self.moduleName = @"main";
[FIRApp configure];
 // You can add your custom initial props in the dictionary below.
 // They will be passed down to the ViewController used by React Native.
 self.initialProps = @{};

 return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
 return [self bundleURL];
}

- (NSURL *)bundleURL
{
#if DEBUG
 return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@".expo/.virtual-metro-entry"];
#else
 return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

// Linking API
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
 return [super application:application openURL:url options:options] || [RCTLinkingManager application:application openURL:url options:options];
}

// Universal Links
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
 BOOL result = [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
 return [super application:application continueUserActivity:userActivity restorationHandler:restorationHandler] || result;
}

// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
 return [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
 return [super application:application didFailToRegisterForRemoteNotificationsWithError:error];
}

// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
 return [super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

@end

Index.js File

import registerRootComponent from 'expo/build/launch/registerRootComponent';
import notifee, { EventType } from '@notifee/react-native';
import App from './App';
import { onDisplayNotification } from './app/modules/pushNotificationHelper';
import messaging from '@react-native-firebase/messaging';

// Set up background message handler
messaging().setBackgroundMessageHandler(async (remoteMessage) => {

console.log('Message handled in the background! 1', typeof (remoteMessage.data.data));
});

function HeadlessCheck({ isHeadless }) {
if (isHeadless) {
  // App has been launched in the background by iOS, ignore
  return null;
}

return <App />;
}

registerRootComponent(App);



I still not found solution
stuck on it for a long time
"react-native": "0.74.1",
"@react-native-firebase/app": "^20.3.0",
"@react-native-firebase/messaging": "^20.3.0",

@Satyam-code143
Copy link

Hi @furqan-fabtechsol ,

Thank you for the response!

Even I am in the same state. Without a solution.

Need to check with @mohamedshawky982 once.
Hi @mohamedshawky982 , please help us with the configs.

@DhruvBachani
Copy link

+1

@miladnikad
Copy link

Guys, I found a solution. sendMulticast is deprecated and you should use sendEachForMulticast instead.

@Satyam-code143
Copy link

Hi @miladnikad ,

I have been using the sendEachForMulticast itself. Can you share your message body?
I would really want to know the structure of your data only message body.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plugin: messaging FCM only - ( messaging() ) - do not use for Notifications Type: Stale Issue has become stale - automatically added by Stale bot
Projects
None yet
Development

No branches or pull requests