invertase / react-native-firebase

🔥 A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.7k stars 2.22k forks source link

[🐛]🔥Foreground notifications don't fire any messaging callback in iOS #7409

Closed RRigueira24 closed 1 year ago

RRigueira24 commented 1 year ago

Issue

Similiar to https://github.com/invertase/react-native-firebase/issues/7389. When receving a push notification with the app in background or quit state neither setBackgroundMessageHandler or onNotificationOpenedApp or getInitialNotification seem to work in iOS. This issue started after updating React Native from 0.68 to 0.71.13 and the rnfirebase packages from 14 to 18.4.

ps: app name hidden for security reasons, can be later provided if needed


Project Files

Javascript

Click To Expand

#### `package.json`: ```json "@react-native-firebase/app": "^18.4.0", "@react-native-firebase/crashlytics": "^18.4.0", "@react-native-firebase/dynamic-links": "^18.4.0", "@react-native-firebase/firestore": "^18.4.0", "@react-native-firebase/in-app-messaging": "^18.4.0", "@react-native-firebase/messaging": "^18.4.0", "react": "18.2.0", "react-native": "^0.71.13", ``` #### `firebase.json` for react-native-firebase v6: ```json { "react-native": { "crashlytics_debug_enabled": true, "google_analytics_automatic_screen_reporting_enabled": false } } ``` #### `index.js`: ```js import React from 'react'; import {AppRegistry} from 'react-native'; import messaging from '@react-native-firebase/messaging'; import App from './App'; import {name as appName} from './app.json'; import NotificationsStore from '_mobx/notifications'; import {log} from '_utils/logs'; // register background handler messaging().setBackgroundMessageHandler(async remoteMessage => { const {newNotification} = NotificationsStore; //stores notification on device newNotification(remoteMessage); log('Message handled in the background!' + remoteMessage, 'inapp'); }); function HeadlessCheck({isHeadless}) { if (isHeadless) { console.log('isHeadless ' + isHeadless); // App has been launched in the background by iOS, ignore return null; } return ; } AppRegistry.registerComponent(appName, () => HeadlessCheck); ```

iOS

Click To Expand

#### `ios/Podfile`: - [ ] I'm not using Pods - [x] I'm using Pods and my Podfile looks like: ```ruby require_relative '../node_modules/react-native/scripts/react_native_pods' require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' require_relative '../node_modules/react-native-permissions/scripts/setup' platform :ios, min_ios_version_supported prepare_react_native_project! setup_permissions([ 'AppTrackingTransparency', # 'BluetoothPeripheral', # 'Calendars', 'Camera', # 'Contacts', # 'FaceID', # 'LocationAccuracy', # 'LocationAlways', 'LocationWhenInUse', 'MediaLibrary', # 'Microphone', # 'Motion', 'Notifications', 'PhotoLibrary', 'PhotoLibraryAddOnly' # 'Reminders', # 'SpeechRecognition', # 'StoreKit' ]) # If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. # because `react-native-flipper` depends on (FlipperKit,...) that will be excluded # # To fix this you can also exclude `react-native-flipper` using a `react-native.config.js` # ```js # module.exports = { # dependencies: { # ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), # ``` flipper_config = FlipperConfiguration.disabled linkage = ENV['USE_FRAMEWORKS'] use_frameworks! :linkage => :static if linkage != nil Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green end project 'xxx', 'Dev.Debug' => :debug, 'Dev.Release' => :release, 'Qa.Debug' => :debug, 'Qa.Release' => :release, 'Prod.Debug' => :debug, 'Prod.Release' => :release target 'xxx' do config = use_native_modules! # Flags change depending on the env values. flags = get_default_flags() use_react_native!( :path => config[:reactNativePath], # Hermes is now enabled by default. Disable by setting this flag to false. # Upcoming versions of React Native may rely on get_default_flags(), but # we make it explicit here to aid in the React Native upgrade process. :hermes_enabled => flags[:hermes_enabled], :fabric_enabled => flags[:fabric_enabled], # Enables Flipper. # # Note that if you have use_frameworks! enabled, Flipper will not work and # you should disable the next line. :flipper_configuration => flipper_config, # An absolute path to your application root. :app_path => "#{Pod::Config.instance.installation_root}/.." ) target 'xxx' do inherit! :complete # Pods for testing end # Enables Flipper. # # Note that if you have use_frameworks! enabled, Flipper will not work and # you should disable the next line. #use_flipper!({ 'Flipper-Folly' => '2.6.10' }) #use_flipper!({'Flipper' => '0.75.1', 'Flipper-Folly' => '2.5.3', 'Flipper-RSocket' => '1.3.1'}) post_install do |installer| react_native_post_install( installer, # Set `mac_catalyst_enabled` to `true` in order to apply patches # necessary for Mac Catalyst builds :mac_catalyst_enabled => false ) __apply_Xcode_12_5_M1_post_install_workaround(installer) installer.pods_project.targets.each do |target| if target.respond_to?(:product_type) and target.product_type == "com.apple.product-type.bundle" target.build_configurations.each do |config| config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO' end end end end end ``` #### `AppDelegate.m`: ```objc #import "AppDelegate.h" #import "RNBootSplash.h" #import "RNFBMessagingModule.h" #import #import #import #import #import "RNQuickActionManager.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [FIRApp configure]; self.moduleName = @"xxx"; // 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 = [RNFBMessagingModule addCustomPropsToUserProps:nil withLaunchOptions:launchOptions]; return [super application:application didFinishLaunchingWithOptions:launchOptions]; } - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #if DEBUG return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; #else return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; #endif } /// This method controls whether the `concurrentRoot`feature of React18 is turned on or off. /// /// @see: https://reactjs.org/blog/2022/03/29/react-v18.html /// @note: This requires to be rendering on Fabric (i.e. on the New Architecture). /// @return: `true` if the `concurrentRoot` feture is enabled. Otherwise, it returns `false`. - (BOOL)concurrentRootEnabled { // Switch this bool to turn on and off the concurrent root return false; } - (NSDictionary *)prepareInitialProps { NSMutableDictionary *initProps = [NSMutableDictionary new]; #ifdef RCT_NEW_ARCH_ENABLED initProps[kRNConcurrentRoot] = @([self concurrentRootEnabled]); #endif return initProps; } - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary *)options { if ([[FBSDKApplicationDelegate sharedInstance] application:application openURL:url options:options]) { return YES; } if ([RCTLinkingManager application:application openURL:url options:options]) { return YES; } return NO; } - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray> * _Nullable))restorationHandler { return [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; } - (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL succeeded)) completionHandler { [RNQuickActionManager onQuickActionPress:shortcutItem completionHandler:completionHandler]; } // ⬇️ Add this before file @end - (UIView *)createRootViewWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initProps:(NSDictionary *)initProps { UIView *rootView = [super createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps]; [RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView]; // ⬅️ initialize the splash screen return rootView; } @end ```


Environment

Click To Expand

**`react-native info` output:** ``` System: OS: macOS 13.3 CPU: (8) arm64 Apple M1 Memory: 95.88 MB / 16.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 18.16.1 - /var/folders/ns/_hzr6fpj3rx927knyzwq6bf40000gn/T/yarn--1697639407519-0.11020800598023928/node Yarn: 1.22.5 - /var/folders/ns/_hzr6fpj3rx927knyzwq6bf40000gn/T/yarn--1697639407519-0.11020800598023928/yarn npm: 9.5.1 - ~/.nvm/versions/node/v18.16.1/bin/npm Watchman: Not Found Managers: CocoaPods: 1.13.0 - /Users/ruirigueira/.rvm/gems/ruby-3.0.0/bin/pod SDKs: iOS SDK: Platforms: DriverKit 22.4, iOS 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4 Android SDK: Not Found IDEs: Android Studio: 2022.1 AI-221.6008.13.2211.9477386 Xcode: 14.3/14E222b - /usr/bin/xcodebuild Languages: Java: 11.0.14.1 - /usr/bin/javac npmPackages: @react-native-community/cli: Not Found react: 18.2.0 => 18.2.0 react-native: ^0.71.13 => 0.71.13 react-native-macos: Not Found npmGlobalPackages: *react-native*: Not Found ``` - **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


RRigueira24 commented 1 year ago

Adding FCM payload

{
    "to": "xxx",
    "collapse_key": "xxx",
    "notification": {
        "title": "Test",
        "body": "Test"
    },
    "apns": {
        "payload": {
            "aps": {
                "content-available": 1
            }
        }
    },
    "data": {
        "link": "https://example.com"
    }
}
RRigueira24 commented 1 year ago

Found solution in https://github.com/invertase/react-native-firebase/issues/7055#issuecomment-1515189614