[🐛] (Automated/Scheduled) Push Notifications NOT working in iOS
Issue
Hi @mikehardy,
Addressing the previous old issues i've raised (https://github.com/invertase/react-native-firebase/issues/7784 ,https://github.com/invertase/react-native-firebase/issues/7589 ,https://github.com/invertase/react-native-firebase/issues/7783)
We have now upgraded our react native firebase packages, we've changed our AppDeletegate file according to the doc, and we've also cross checked APNs key and cross checked sending Manual notification to our iOS project from Dashboard and Postman cURL request, this works fine.
Basically, we've tried to skimmed through all the documentation and issues we could find, but still we are failing with our push notifications for our iOS devices which used to send earlier from our backend server whenever any new thing (shows or articles) are published, another thing to note is where our Notification type is message.
Please, could anyone guide us what's happening wrong? Please, let us know, we're in a dead loop of no solutions.
This is our notification block that we're sending from backend,
send_notification.delay({
'device_token': token_detail['device_token'],
'title': notification_info[token_detail['language']]['title'],
'message': notification_info[token_detail['language']]['message'],
'data_message': {
'podcast_id': meta_data['episode_id'],
'event_type': 'new_podcast_published',
'icon_url': meta_data['image']
},
'extra_notification_kwargs': {
'image': meta_data['image']
},
'message_icon': meta_data['image']
})
And, this is the function
def send_notification(params):
"""
Send notification to user device
"""
logger.info(params)
push_notification_service.notify_single_device(registration_id=params['device_token'], message_title=params['title'],
message_body=params['message'], data_message=params['data_message'], low_priority=False, sound='Default', content_available=True, android_channel_id='default-channel-id', extra_notification_kwargs=params['extra_notification_kwargs'], message_icon=params['message_icon'], extra_kwargs={'mutable_content': True})
Thanks.
Project Files
Javascript
Click To Expand
package.json:
"@react-native-firebase/analytics": "^15.3.0",
"@react-native-firebase/app": "^15.3.0",
"@react-native-firebase/crashlytics": "^15.3.0",
"@react-native-firebase/in-app-messaging": "^15.3.0",
"@react-native-firebase/messaging": "^15.3.0",
firebase.json:
{
"react-native": {
"messaging_android_notification_channel_id": "high-priority",
"crashlytics_auto_collection_enabled": true,
"crashlytics_debug_enabled": false
}
}
iOS
Click To Expand
ios/Podfile:
- [ ] I'm not using Pods
- [x] I'm using Pods and my Podfile looks like:
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
$RNFirebaseAsStaticFramework = true
platform :ios, '11.0'
target 'NewsLaundry' do
use_frameworks!
config = use_native_modules!
use_react_native!(
:path => config[:reactNativePath],
# to enable hermes on iOS, change `false` to `true` and then install pods
:hermes_enabled => false,
)
# Permissions
permissions_path = '../node_modules/react-native-permissions/ios'
pod 'Permission-LocationAlways', :path => "#{permissions_path}/LocationAlways/Permission-LocationAlways.podspec"
pod 'Permission-LocationWhenInUse', :path => "#{permissions_path}/LocationWhenInUse/Permission-LocationWhenInUse.podspec"
pod 'Permission-PhotoLibrary', :path => "#{permissions_path}/PhotoLibrary"
pod 'react-native-onesignal', :path => '../node_modules/react-native-onesignal'
# React Native Version Check (for iOS app updates)
pod 'react-native-version-check', :path => '../node_modules/react-native-version-check'
pod 'react-native-segmented-control', :path => '../node_modules/@react-native-segmented-control/segmented-control'
pod 'ReactNativeMoEngage', :path => '../node_modules/react-native-moengage'
pod 'ReactNativeMoEngage', :path => '../node_modules/react-native-moengage'
pod 'react-native-voice', :path => '../node_modules/@react-native-voice/voice'
pod 'GoogleUtilities'
target 'NewsLaundryTests' do
use_frameworks!
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!()
pre_install do |installer|
Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}
installer.pod_targets.each do |pod|
if pod.name.eql?('RNPermissions') || pod.name.start_with?('Permission-')
def pod.build_type;
Pod::BuildType.static_library
end
end
end
end
post_install do |installer|
react_native_post_install(installer)
end
end
target 'ImageNotification' do
use_frameworks!
pod 'Firebase/Messaging', '~> 9.4.0' # Version should match the podfile.lock version Refer https://rnfirebase.io/messaging/ios-notification-images
pod 'GoogleUtilities'
end
target 'OneSignalNotificationServiceExtension' do
use_frameworks!
pod 'OneSignalXCFramework', '>= 3.4.3', '< 4.0'
pod 'GoogleUtilities'
end
AppDelegate.m:
#import "AppDelegate.h"
#import "RNSplashScreen.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <React/RCTLinkingManager.h>
#import <Firebase.h>
#import <RNBackgroundDownloader.h>
#import <RNFBMessagingModule.h>
#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import <CodePush/CodePush.h>
#import <ReactNativeMoEngage/MoEngageInitializer.h>
#import <MoEngageSDK/MoEngageSDK.h>
#import "Orientation.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
// Request authorization for notifications
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
[center requestAuthorizationWithOptions:authOptions
completionHandler:^(BOOL granted, NSError * _Nullable error) {
// ...
}];
// Register for remote notifications
[application registerForRemoteNotifications];
if ([FIRApp defaultApp] == nil) {
[FIRApp configure];
}
// Set FIRMessaging delegate
[FIRMessaging messaging].delegate = self;
[[FIRMessaging messaging] tokenWithCompletion:^(NSString *token, NSError *error) {
if (error != nil) {
NSLog(@"Error getting FCM registration token: %@", error);
} else {
NSLog(@"FCM registration token: %@", token);
// self.fcmRegTokenMessage.text = token;
}
}];
[[FBSDKApplicationDelegate sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions];
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
NSDictionary *appProperties = [RNFBMessagingModule addCustomPropsToUserProps:nil withLaunchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"NewsLaundry"
initialProperties:appProperties];
if (@available(iOS 13.0, *)) {
rootView.backgroundColor = [UIColor systemBackgroundColor];
} else {
rootView.backgroundColor = [UIColor whiteColor];
}
[[MoEngageInitializer sharedInstance] initializeDefaultInstance:launchOptions];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
[FIRMessaging messaging].autoInitEnabled = YES;
// [RNSplashScreen show];
return YES;
}
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
while ([[UIDevice currentDevice] isGeneratingDeviceOrientationNotifications]) {
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
}
return [Orientation getOrientation];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// Pass in UIBackgroundFetchResult based on whether operation was successful or has failed
completionHandler(UIBackgroundFetchResultNewData);
}
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
[FIRMessaging messaging].APNSToken = deviceToken;
[[MoEngageSDKMessaging sharedInstance] setPushToken:deviceToken];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
[[MoEngageSDKMessaging sharedInstance] didFailToRegisterForPush];
}
- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
NSLog(@"FCM registration token: %@", fcmToken);
// Notify about received token.
NSDictionary *dataDict = [NSDictionary dictionaryWithObject:fcmToken forKey:@"token"];
[[NSNotificationCenter defaultCenter] postNotificationName:
@"FCMToken" object:nil userInfo:dataDict];
// TODO: If necessary send token to application server.
// Note: This callback is fired at each app startup and whenever a new token is generated.
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler {
// Call only if MoEngageAppDelegateProxyEnabled is NO
[[MoEngageSDKMessaging sharedInstance] userNotificationCenter:center didReceive:response];
// Custom Handling of notification if Any
completionHandler();
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
// This is to only to display Alert and enable notification sound
completionHandler((UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert));
}
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
BOOL handledFB = [[FBSDKApplicationDelegate sharedInstance] application:app openURL:url options:options];
BOOL handledDeeplinking = [RCTLinkingManager application:app openURL:url options:options];
return handledFB || handledDeeplinking;
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
return [CodePush bundleURL];
#endif
}
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler {
[RNBackgroundDownloader setCompletionHandlerWithIdentifier:identifier completionHandler:completionHandler];
}
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity
restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
return [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
}
- (BOOL)application:(UIApplication *)application shouldSaveSecureApplicationState:(NSCoder *)coder {
return YES;
}
- (BOOL)application:(UIApplication *)application shouldRestoreSecureApplicationState:(NSCoder *)coder {
return YES;
}
@end
Environment
Click To Expand
react-native info output:
System:
OS: macOS 13.3.1
CPU: (8) arm64 Apple M1
Memory: 113.25 MB / 8.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 18.16.0 - /opt/homebrew/opt/node@18/bin/node
Yarn: 1.22.19 - /opt/homebrew/bin/yarn
npm: 9.5.1 - /opt/homebrew/opt/node@18/bin/npm
Watchman: 2023.05.22.00 - /opt/homebrew/bin/watchman
Managers:
CocoaPods: 1.12.1 - /Users/appName/.rvm/gems/ruby-2.7.6/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 22.1, iOS 16.1, macOS 13.0, tvOS 16.1, watchOS 9.1
Android SDK: Not Found
IDEs:
Android Studio: 2022.2 AI-222.4459.24.2221.9971841
Xcode: 14.1/14B47b - /usr/bin/xcodebuild
Languages:
Java: 11.0.19 - /usr/bin/javac
npmPackages:
@react-native-community/cli: Not Found
react: ^17.0.2 => 17.0.2
react-native: ^0.66.5 => 0.66.5
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
"@react-native-firebase/analytics": "^15.3.0"
"@react-native-firebase/app": "^15.3.0"
"@react-native-firebase/crashlytics": "^15.3.0"
"@react-native-firebase/in-app-messaging": "^15.3.0"
"@react-native-firebase/messaging": "^15.3.0"
"react-native": "^0.66.5"
-
Are you using
TypeScript?- `No
- 👉 Check out
React Native FirebaseandInvertaseon Twitter for updates on the library.
It appears there is no "notification" key in the FCM you are sending. Those are unreliable and I would expect they won't be delivered. You're at the mercy of Apple and any changes they make to iOS (which changes in my experience just reduce delivery of data-only message further)
Please test after modifying your send method to include a notification key and report results
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.