-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Description
Issue
When implementing custom foreground notification presentation logic in AppDelegate, the completionHandler is already consumed by RNFBMessagingUNUserNotificationCenter before the original delegate can handle it. This prevents custom logic from controlling notification display behavior.
In RNFBMessaging+UNUserNotificationCenter.m, when a notification with gcm.message_id is received in the foreground, the code calls completionHandler before forwarding to the original delegate:
if (notification.request.content.userInfo[@"gcm.message_id"]) {
// ... event handling
completionHandler(presentationOptions); // Called first
}
if (_originalDelegate != nil && originalDelegateRespondsTo.willPresentNotification) {
[_originalDelegate userNotificationCenter:center
willPresentNotification:notification
withCompletionHandler:completionHandler]; // Already consumed
}Since completionHandler can only be called once, any custom presentation logic in the original delegate is ignored.
The original delegate should be called first to allow custom notification presentation logic, then fallback to the library's default behavior if no delegate is set.
Example
// AppDelegate.m
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
// Custom logic to determine whether to show notification
if (shouldShowNotification) {
if (@available(iOS 14.0, *)) {
completionHandler(UNNotificationPresentationOptionList |
UNNotificationPresentationOptionBanner |
UNNotificationPresentationOptionBadge);
} else {
completionHandler(UNNotificationPresentationOptionAlert);
}
} else {
completionHandler(UNNotificationPresentationOptionNone);
}
}This code has no effect because RNFBMessaging already called completionHandler.
Proposed Solution (SUDO)
Reverse the order: call the original delegate first, and only use the default behavior if no delegate is set:
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
// Calculate default presentation options
NSArray *presentationOptionsConfig = [[RNFBJSON shared] getArrayValue:@"messaging_ios_foreground_presentation_options" defaultValue:@[]];
UNNotificationPresentationOptions presentationOptions = UNNotificationPresentationOptionNone;
// ... existing presentation options logic
// Send messaging event if FCM message
if (notification.request.content.userInfo[@"gcm.message_id"]) {
NSDictionary *notificationDict = [RNFBMessagingSerializer notificationToDict:notification];
if (!notificationDict[@"contentAvailable"]) {
[[RNFBRCTEventEmitter shared] sendEventWithName:@"messaging_message_received"
body:notificationDict];
}
}
// Let original delegate handle presentation first
if (_originalDelegate != nil && originalDelegateRespondsTo.willPresentNotification) {
[_originalDelegate userNotificationCenter:center
willPresentNotification:notification
withCompletionHandler:completionHandler];
} else {
// Use default behavior if no delegate
completionHandler(presentationOptions);
}
}This allows developers to implement custom foreground notification logic while maintaining backward compatibility.
Project Files
Javascript
Click To Expand
package.json:
# N/Afirebase.json for react-native-firebase v6:
# N/AiOS
Click To Expand
ios/Podfile:
- I'm not using Pods
- I'm using Pods and my Podfile looks like:
# N/AAppDelegate.m:
// N/AAndroid
Click To Expand
Have you converted to AndroidX?
- my application is an AndroidX application?
- I am using
android/gradle.settingsjetifier=truefor Android compatibility? - I am using the NPM package
jetifierfor react-native compatibility?
android/build.gradle:
// N/Aandroid/app/build.gradle:
// N/Aandroid/settings.gradle:
// N/AMainApplication.java:
// N/AAndroidManifest.xml:
<!-- N/A -->Environment
Click To Expand
react-native info output:
OUTPUT GOES HERE
- 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-firebaseversion you're using that has this issue:e.g. 5.4.3
Firebasemodule(s) you're using that has the issue:e.g. Instance ID
- Are you using
TypeScript?Y/N&VERSION
- 👉 Check out
React Native FirebaseandInvertaseon Twitter for updates on the library.