react-native-firebase icon indicating copy to clipboard operation
react-native-firebase copied to clipboard

[🐛] Bug Report Title - Time Sensitive Notification

Open JakeOrel opened this issue 3 years ago • 2 comments

Issue

Describe your issue here Working on adding time sensitive notifications to my IOS app, I have gone through the process of adding the capabilities and entitlements, The app settings reflect that time sensitive is available. However whenever i send my time sensitive notifications they are not being tagged as such or breaking through focus modes. Example of JSON in push message:

{
   "to": "<insert ID>",
   "priority": "high",
   "content_available": true,
   "notification": {
      "title": "this is test",
      "body": "This should be marked as time sensitive",
      "sound": "default"
   },
   "apns": {
      "payload": {
         "aps": {
            "alert": {
               "title": "this is test",
               "body": "I should be time sesitive",
               "sound": "default"
            },
            "badge": 0,
            "sound": "default",
            "interruption-level": "time-sensitive"
         },
         "headers": {
            "apns-priority": 5
         }
      }
   },
    "data": {
      "command": "time-sensitive",
      "popup": true,
      "sound": true,
      "uid": "ladF5joB",
      "body2": ""
    }
}

What is logged on receive of notificaiton:

 -[RNFBMessagingAppDelegate application:didReceiveRemoteNotification:fetchCompletionHandler:] [Line 133] didReceiveRemoteNotification gcm.message_id was present {
    aps =     {
        alert =         {
            body = "This should be marked as time senstiive";
            title = "this is test";
        };
        "content-available" = 1;
         <----- interruption level not present
        sound = default;
    };
    body2 = "";
    command = "time-sensitive";
    "gcm.message_id" = 1657127464737870;
    "google.c.a.e" = 1;
    "google.c.fid" = "fcWS4x2PlkiUs2lDL0zC-8";
    "google.c.sender.id" = 120375847630;
    popup = true;
    sound = true;
    uid = ladF5joB;
}

Project Files

Javascript

Click To Expand

package.json:

{
  "name": "myApp",
  "version": "2.1.7",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "detox-start-debug": "RN_SRC_EXT=e2e.js react-native start --reset-cache",
    "test": "jest --verbose",
    "test:watch": "jest --watchAll --verbose",
    "lint": "eslint .",
    "storybook": "start-storybook -p 7007",
    "build-storybook": "build-storybook",
    "postinstall": "patch-package"
  },
  "dependencies": {
    "@react-native-async-storage/async-storage": "^1.15.5",
    "@react-native-community/masked-view": "^0.1.11",
    "@react-native-community/netinfo": "^7.1.2",
    "@react-native-community/push-notification-ios": "^1.10.1",
    "@react-native-community/slider": "^3.0.3",
    "@react-native-firebase/app": "14.11.1",
    "@react-native-firebase/messaging": "14.11.1",
    "@react-navigation/drawer": "^5.12.5",
    "@react-navigation/native": "^5.9.4",
    "@react-navigation/stack": "^5.14.5",
    "axios": "^0.21.1",
    "card-validator": "^8.1.1",
    "expo": "^45.0.4",
    "expo-av": "^11.2.3",
    "expo-barcode-scanner": "^11.3.0",
    "js-base64": "^3.6.1",
    "lodash": "^4.17.21",
    "lottie-ios": "^3.1.8",
    "lottie-react-native": "^5.1.3",
    "md5": "^2.3.0",
    "moment": "^2.29.1",
    "moment-timezone": "^0.5.33",
    "patch-package": "^6.4.7",
    "postinstall-postinstall": "^2.1.0",
    "pubnub": "^4.36.0",
    "pubnub-react": "^2.1.0",
    "react": "17.0.2",
    "react-native": "0.68.2",
    "react-native-background-fetch": "^4.0.3",
    "react-native-background-geolocation": "^4.1.1",
    "react-native-bubble-notifications": "^0.1.9",
    "react-native-chart-kit": "^6.12.0",
    "react-native-config": "^1.4.5",
    "react-native-device-info": "^8.1.3",
    "react-native-elements": "^3.4.2",
    "react-native-gesture-handler": "^1.10.3",
    "react-native-keyboard-aware-scroll-view": "^0.9.5",
    "react-native-keychain": "^8.0.0",
    "react-native-linear-gradient": "^2.5.6",
    "react-native-maps": "^0.31.1",
    "react-native-maps-directions": "github:theOaksDev/react-native-maps-directions",
    "react-native-permissions": "^3.0.5",
    "react-native-progress": "^4.1.2",
    "react-native-push-notification": "^8.1.1",
    "react-native-ratings": "^8.0.4",
    "react-native-reanimated": "^2.3.1",
    "react-native-safe-area-context": "^3.2.0",
    "react-native-screens": "^3.3.0",
    "react-native-select-dropdown": "^1.2.0",
    "react-native-svg": "^12.3.0",
    "react-native-switch-selector": "^2.1.4",
    "react-native-timezone": "https://github.com/TheOaksDev/react-native-timezone.git",
    "react-native-toast-message": "^1.6.0",
    "react-native-vector-icons": "^9.1.0",
    "react-native-webview": "^11.6.5",
    "react-redux": "^7.2.4",
    "redux": "^4.1.0",
    "redux-thunk": "^2.3.0",
    "rn-swipe-button": "^1.3.6",
    "sha256": "^0.2.0",
    "yup": "^0.32.9"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@babel/plugin-transform-flow-strip-types": "^7.16.7",
    "@babel/runtime": "^7.12.5",
    "@react-native-community/eslint-config": "^2.0.0",
    "@testing-library/jest-native": "^4.0.4",
    "@testing-library/react-native": "^9.0.0",
    "babel-jest": "^26.6.3",
    "babel-loader": "^8.2.2",
    "detox": "^19.0.0",
    "eslint": "7.14.0",
    "eslint-plugin-detox": "^1.0.0",
    "jest": "^26.6.3",
    "jest-circus": "^27.3.1",
    "jest-expo": "^43.0.1",
    "metro-react-native-babel-preset": "^0.64.0",
    "react-dom": "17.0.1",
    "react-test-renderer": "17.0.1"
  },
  "jest": {
    "preset": "jest-expo",
    "setupFiles": [
      "./node_modules/react-native-gesture-handler/jestSetup.js",
      "./jest/setup.js"
    ],
    "setupFilesAfterEnv": [
      "@testing-library/jest-native/extend-expect"
    ],
    "transformIgnorePatterns": [
      "node_modules/(?!(jest-)?react-native|@react-native-community|@react-navigation|react-native|@react-native|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg)"
    ]
  }
}

firebase.json for react-native-firebase v6:

# N/A

iOS

Click To Expand

ios/Podfile:

  • [ ] I'm not using Pods
  • [x] I'm using Pods and my Podfile looks like:
require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")
require File.join(File.dirname(`node --print "require.resolve('@react-native-community/cli-platform-ios/package.json')"`), "native_modules")

platform :ios, '12.0'

require 'json'
podfile_properties = JSON.parse(File.read('./Podfile.properties.json')) rescue {}

target 'myApp' do


  permissions_path = '../node_modules/react-native-permissions/ios'

  pod 'Permission-Camera', :path => "#{permissions_path}/Camera"
  pod 'Permission-LocationAlways', :path => "#{permissions_path}/LocationAlways"
  pod 'Permission-LocationWhenInUse', :path => "#{permissions_path}/LocationWhenInUse"
  pod 'Permission-Motion', :path => "#{permissions_path}/Motion"
  pod 'Permission-Notifications', :path => "#{permissions_path}/Notifications"
  pod 'Permission-FaceID', :path => "#{permissions_path}/FaceID"
  # pod 'Permission-AppTrackingTransparency', :path => "#{permissions_path}/AppTrackingTransparency"
  # pod 'Permission-BluetoothPeripheral', :path => "#{permissions_path}/BluetoothPeripheral"
  # pod 'Permission-Calendars', :path => "#{permissions_path}/Calendars"
  # pod 'Permission-Contacts', :path => "#{permissions_path}/Contacts"
  # pod 'Permission-LocationAccuracy', :path => "#{permissions_path}/LocationAccuracy"
  # pod 'Permission-MediaLibrary', :path => "#{permissions_path}/MediaLibrary"
  # pod 'Permission-Microphone', :path => "#{permissions_path}/Microphone"
  # pod 'Permission-PhotoLibrary', :path => "#{permissions_path}/PhotoLibrary"
  # pod 'Permission-PhotoLibraryAddOnly', :path => "#{permissions_path}/PhotoLibraryAddOnly"
  # pod 'Permission-Reminders', :path => "#{permissions_path}/Reminders"
  # pod 'Permission-Siri', :path => "#{permissions_path}/Siri"
  # pod 'Permission-SpeechRecognition', :path => "#{permissions_path}/SpeechRecognition"
  # pod 'Permission-StoreKit', :path => "#{permissions_path}/StoreKit"


  # React Native Maps dependencies
  rn_maps_path = '../node_modules/react-native-maps'
  pod 'react-native-google-maps', :path => rn_maps_path

  use_expo_modules!
  config = use_native_modules!
  use_react_native!(
    :path => config[:reactNativePath],
    :hermes_enabled => podfile_properties['expo.jsEngine'] == 'hermes'
  )

  pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons'

  target 'myAppTests' 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!()

  deployment_target="12.0"

  post_install do |installer|
    react_native_post_install(installer)
    `sed -i -e  $'s/__IPHONE_10_0/__IPHONE_14_0/' #{installer.sandbox.root}/RCT-Folly/folly/portability/Time.h`
    
    deployment_target = "12.0"

    # Workaround `Cycle inside FBReactNativeSpec` error for react-native 0.64
    # Reference: https://github.com/software-mansion/react-native-screens/issues/842#issuecomment-812543933
    installer.pods_project.targets.each do |target|
      installer.pods_project.targets.each do |target|
        target.build_configurations.each do |config|
          config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = deployment_target
            if (target.name&.eql?('FBReactNativeSpec'))
              target.build_phases.each do |build_phase|
                if (build_phase.respond_to?(:name) && build_phase.name.eql?('[CP-User] Generate Specs'))
                  target.build_phases.move(build_phase, 0)
              end
            end
          end
        end
      end
    end
  end
end

AppDelegate.m:

#import <Firebase.h>
#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <React/RCTConvert.h>
#import <TSBackgroundFetch/TSBackgroundFetch.h>
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>

#import <GoogleMaps/GoogleMaps.h>

 #if defined(FB_SONARKIT_ENABLED) && __has_include(<FlipperKit/FlipperClient.h>)
 #import <FlipperKit/FlipperClient.h>
 #import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
 #import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
 #import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
 #import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
 #import <FlipperKitReactPlugin/FlipperKitReactPlugin.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

// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
 [RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
  [RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
 [RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}
// Required for localNotification event
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)(void))completionHandler
{
  [RNCPushNotificationIOS didReceiveNotificationResponse:response];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }
[GMSServices provideAPIKey:@"AIzaSyBUzZDi5EMELcRTTlvZBJzBd4ZpEIaf7dM"];
#ifdef FB_SONARKIT_ENABLED
  InitializeFlipper(application);
#endif

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"Wridz" initialProperties:nil];
  id rootViewBackgroundColor = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RCTRootViewBackgroundColor"];
  if (rootViewBackgroundColor != nil) {
    rootView.backgroundColor = [RCTConvert UIColor:rootViewBackgroundColor];
  } else {
    rootView.backgroundColor = [UIColor whiteColor];
  }

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];

  // [REQUIRED] Register BackgroundFetch
  [[TSBackgroundFetch sharedInstance] didFinishLaunching];
  [super application:application didFinishLaunchingWithOptions:launchOptions];

   // Define UNUserNotificationCenter
  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
  center.delegate = self;

  return YES;
}

//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
  completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}

- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge
{
    // If you'd like to export some custom RCTBridgeModules that are not Expo modules, add them here!
    return @[];
}

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

@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 12.3.1
    CPU: (6) x64 Intel(R) Core(TM) i5-8500B CPU @ 3.00GHz
    Memory: 309.84 MB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 14.18.2 - ~/.nvm/versions/node/v14.18.2/bin/node
    Yarn: 1.22.18 - ~/.nvm/versions/node/v14.18.2/bin/yarn
    npm: 6.14.15 - ~/.nvm/versions/node/v14.18.2/bin/npm
    Watchman: 2022.02.21.00 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.11.2 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 21.4, iOS 15.5, macOS 12.3, tvOS 15.4, watchOS 8.5
    Android SDK:
      Android NDK: 22.1.7171670
  IDEs:
    Android Studio: 2021.2 AI-212.5712.43.2112.8512546
    Xcode: 13.4.1/13F100 - /usr/bin/xcodebuild
  Languages:
    Java: 11.0.10 - /usr/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: 17.0.2 => 17.0.2 
    react-native: 0.68.2 => 0.68.2 
    react-native-macos: Not Found
  npmGlobalPackages:
  • Platform that you're experiencing the issue on:
    • [] iOS
    • [ ] Android
    • [x] 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:
    • Only using modules app and messaging
  • Firebase module(s) you're using that has the issue:
    • messaging, app
  • Are you using TypeScript?
    • N

JakeOrel avatar Jul 06 '22 17:07 JakeOrel

Some discussion here already:

https://github.com/invertase/react-native-firebase/discussions/6371#discussioncomment-3089239

Appears to need an addition to the objective-c code to carry the JSON from the message as received in Objective-C to the object that we serialize / send to javascript layer as JSON

PRs welcome :pray: otherwise this will have to sit for a bit while I'm low-availability during some travel

mikehardy avatar Jul 06 '22 17:07 mikehardy

I'm not the most familiar with native IOS coding, just started dipping my toes into it recently. Is there a good place for some documentation I could reference to try and help along trying to hack this one out?

JakeOrel avatar Jul 06 '22 17:07 JakeOrel

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

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

github-actions[bot] avatar Dec 05 '22 19:12 github-actions[bot]

I too am still trying to figure this out. I can see the entitlement listed here: https://docs.expo.dev/build-reference/ios-capabilities/, and I see mentions of people complaining that the interruption-level isn't getting carried through, but I'm trying to do it on a local notification. Does anyone have a clue if this is possible yet?

I also posted here, because it seems like this issue never gets fully solved and the issues get automatically closed: https://github.com/invertase/react-native-firebase/discussions/6371#discussioncomment-3089239

zlanich avatar Aug 18 '23 03:08 zlanich