Repository navigation
[🐛] setBackgroundMessageHandler does not get called for sometime after Killing the app #8654
Copy link
Copy link
Open
Labels
Workflow: Needs ReviewPending feedback or review from a maintainer.Pending feedback or review from a maintainer.platform: androidplugin: messagingFCM only - ( messaging() ) - do not use for NotificationsFCM only - ( messaging() ) - do not use for Notificationsresolution: solution-providedtype: bugNew bug reportNew bug report
Description
Issue
setBackgroundMessageHandler is not getting called for sometime after I kill the app background in Android. After some time I get the notification and further notifications are coming fine. But if I kill the app again it will take time again to get notification.
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import messaging from '@react-native-firebase/messaging';
messaging().setBackgroundMessageHandler(async remoteMessage => {
console.log('Message handled in the background!', remoteMessage);
// handleBackgroundNotifcation(remoteMessage);
pushLocalNotification(remoteMessage);
});
if (__DEV__) {
require('./ReactotronConfig');
}
AppRegistry.registerComponent(appName, () => App);Project Files
Javascript
Click To Expand
package.json:
"@react-native-firebase/analytics": "^21.10.1",
"@react-native-firebase/app": "^21.10.1",
"@react-native-firebase/app-check": "^21.10.1",
"@react-native-firebase/crashlytics": "^21.10.1",
"@react-native-firebase/dynamic-links": "^21.10.1",
"@react-native-firebase/messaging": "^21.10.1",
"@react-native-firebase/perf": "^21.10.1",
"@react-native-firebase/remote-config": "^21.10.1",firebase.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:
require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
'require.resolve(
"react-native/scripts/react_native_pods.rb",
{paths: [process.argv[1]]},
)', __dir__]).strip
platform :ios, min_ios_version_supported
prepare_react_native_project!
linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
use_frameworks! :linkage => linkage.to_sym
end
target 'MashreqMobileApp' do
use_expo_modules!
if ENV['EXPO_USE_COMMUNITY_AUTOLINKING'] == '1'
config_command = ['node', '-e', "process.argv=['', '', 'config'];require('@react-native-community/cli').run()"];
else
config_command = [
'node',
'--no-warnings',
'--eval',
'require(require.resolve(\'expo-modules-autolinking\', { paths: [require.resolve(\'expo/package.json\')] }))(process.argv.slice(1))',
'react-native-config',
'--json',
'--platform',
'ios'
]
end
# Read APP_ID from ../.app.build
def read_app_id
env_file = File.expand_path('../.app.build', __dir__)
if File.exist?(env_file)
File.foreach(env_file) do |line|
if line =~ /^APP_ID=(.*)/
return $1.strip
end
end
end
nil
end
config = use_native_modules!(config_command)
pod 'FirebaseCoreInternal', :modular_headers => true
pod 'Firebase', :modular_headers => true
pod 'FirebaseCore', :modular_headers => true
pod 'GoogleUtilities', :modular_headers => true
pod 'FirebaseCoreExtension', :modular_headers => true
pod 'FirebaseCrashlytics', :modular_headers => true
pod 'FirebaseInstallations', :modular_headers => true
pod 'GoogleDataTransport', :modular_headers => true
pod 'nanopb', :modular_headers => true
pod 'Firebase/Crashlytics'
pod 'react-native-google-maps', :path => '../node_modules/react-native-maps'
pod 'FirebaseRemoteConfig', :modular_headers => true
pod 'FirebaseABTesting', :modular_headers => true
pod 'RNSecureStorage', :path => '../node_modules/rn-secure-storage/ios' # After the upgrade to RN 0.76 this is required to link the library correctly
pod 'TrustKit', :modular_headers => true
app_id = read_app_id
if app_id.nil? || app_id.empty? || app_id == 'MASHREQ_PAK'
pod 'mashreq-rn-covalent', :path => '../node_modules/@mashreq/mashreq-rn-covalent'
end
use_react_native!(
:path => config[:reactNativePath],
:hermes_enabled => true,
:fabric_enabled => false,
# An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/.."
)
post_install do |installer|
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false,
:ccache_enabled => ENV['TF_BUILD'] == 'True'
)
installer.pods_project.targets.each do |t|
if t.name.start_with?("AEP")
t.build_configurations.each do |bc|
bc.build_settings['OTHER_SWIFT_FLAGS'] = '$(inherited) -no-verify-emitted-module-interface'
end
end
end
# TODO: Ask KYC team to remove bitcode from the EFR lib and remove the step below
bitcode_strip_path = `xcrun --find bitcode_strip`.chop!
def strip_bitcode_from_framework(bitcode_strip_path, framework_relative_path)
framework_path = File.join(Dir.pwd, framework_relative_path)
command = "#{bitcode_strip_path} #{framework_path} -r -o #{framework_path}"
puts "Stripping bitcode: #{command}"
system(command)
end
framework_paths = [
"../node_modules/@mashreq/mashreq-rn-efr/ios/EFRSDK.xcframework/ios-arm64/EFRSDK.framework/EFRSDK",
]
framework_paths.each do |framework_relative_path|
strip_bitcode_from_framework(bitcode_strip_path, framework_relative_path)
end
# END OF TODO: Ask KYC and NEO EGY Onboarding teams to remove bitcode from the libs they are using and remove the step above
end
end
target 'PushTemplateExtension' do
pod 'AEPNotificationContent'
endAppDelegate.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:21.10.1
Firebasemodule(s) you're using that has the issue:e.g. Instance ID
- Are you using
TypeScript?Y&5.0.4
- 👉 Check out
React Native FirebaseandInvertaseon Twitter for updates on the library.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Workflow: Needs ReviewPending feedback or review from a maintainer.Pending feedback or review from a maintainer.platform: androidplugin: messagingFCM only - ( messaging() ) - do not use for NotificationsFCM only - ( messaging() ) - do not use for Notificationsresolution: solution-providedtype: bugNew bug reportNew bug report
Activity
MichaelVerdon commentedon Aug 15, 2025
When you say 'after some time' how long do you mean?
tomLadder commentedon Aug 17, 2025
Having the same issue, that the delivery is delayed when you kill the app for some seconds
rawatmanoj commentedon Aug 17, 2025
@tomLadder this got fixed for me. This issue is in development only. try installing UAT build or some other build in your device, it will work everytime.
MichaelVerdon commentedon Aug 18, 2025
Hi there, happy to see you found a solution. I will be closing this ticket. Feel free to reopen if the issue persists.
AmsalSugihan commentedon Oct 23, 2025
Hello @MichaelVerdon , i'm facing the same issue here on android. The
setBackgroundMessageHandleris not triggered when the app has just been closed (killed). The first notification never shows, but the second and the following notifications are delivered correctly.Version : 23.4.0
Android version : 15
dbs-tuan commentedon Oct 27, 2025
Hi @MichaelVerdon
I'm facing the same issue
Android: 13
The logs from Logcat:
2 remaining items
venux92 commentedon Jan 23, 2026
2 -> That's exactly what happens.
I'm actually having this error on a release build on my Android device where I check the Logcat.
mikehardy commentedon Jan 23, 2026
Thanks for the extra information @venux92 - without some triage I'm not sure if this is upstream or not, however our test app has a manual test (and related cloud function) that allows us to test background notifications. So triage / reproduction should be possible. This may be New Architecture specific, as a note for reproduction - the logcat certainly indicated it was new arch, and using Expo.
venux92 commentedon Jan 23, 2026
Thanks @mikehardy
Any idea what I could do in the meantime to prevent this?
Is there a way to retry the task or run a separate task beforehand—even if it also fails—that would allow the full React Native initialization to complete?
I've migrated from React Native
0.68.5(Old Architecture) to Expo 54 (react-native:0.81.5, New Architecture).As soon as I remove
setBackgroundMessageHandler, the app works fine.I appreciate your input on this. I’m effectively blocked until I find a more stable solution, especially since my app relies heavily on push notifications.
Have a nice weekend, and thanks!
MichaelVerdon commentedon Jan 26, 2026
Hi there
You could probably try disabling newArch as I believe its on by default on Expo although i am not keen it would work.
mikehardy commentedon Jan 26, 2026
I believe that will work for Expo 54 and lower, so could be good for now
however the upcoming Expo 55 (currently in beta) will not contain legacy architecture support, so using legacy architecture is possibly viable if all your packages still support it, but will only have a lifespan of half a year or so before Expo 54 will start to seem "stale" and likely start causing transitive problems if not up to date https://expo.dev/changelog/sdk-54#sdk-54-is-the-final-release-to-include-legacy-architecture-support
venux92 commentedon Jan 27, 2026
I tried to disable newArch but I have already libraries that require newArch to work and yes expo 55 will enforce that.
Currently based on your feedback @mikehardy
I've created a patch that check if React is ready first otherwise triggers it.
Not sure if this is the best approach as I have little knowledge in
javabut this solved the issue.Maybe this can help?
I've tested 50+ times on different devices.
The log
"Waited " + waitedMs + "ms for React to be readyranged from
450mslow/old device to100msfor recent devices and the SoftException never occurred again.I received all my push notifications (I've sent up to 10 at once).
I've also added a
retryPolicyinHeadlessJsTaskConfigas I saw this was possible.While the current error is a
SoftExceptionand it won't matter but it will catch other errors.Not sure why there wasn't any
retrypolicy yet btw, maybe this was a product decision?I'm putting the patch below just in case.
Might not be PR ready, just did it to unlock me
This is also why I'm logging many things, to make sure it works fine.
Hopefully this help ✌🏽
Keen to hear your feedback.
Falsin commentedon Jan 28, 2026
@venux92 You saved my life.Thank you.
mikehardy commentedon Jan 28, 2026
@venux92 very nice:
If you opened a PR for this, it would be fantastic
Retry Policy is a feature originally added in 2019 / react-native 0.61 which is after this code came to exist. It likely was never considered.
I like the idea of a retry policy.
react-native adding the feature react/react-native@ac7ec46
versus the implementation here in the monorepo, which isn't even the original implementation - that was a couple years prior https://github.com/invertase/react-native-firebase/commits/30df38f6df8750ff753566eb961bb46c10a84fed/packages/messaging/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingHeadlessService.java
mikehardy commentedon Jan 28, 2026
This is the code I've used before, for example, when doing similar on Notifee - not sure why it didn't occur to me we would need it here as well but yes we do
Note that there is extra work done here - lots of extra work - in order for the javascript layer to finalize the headlessJS task which is apparently much more important in new architecture. Also, this shows the reflective access to the ReactHost and Context so it's safe to use for older react-native versions:
https://github.com/transistorsoft/react-native-background-fetch/blob/master/android/src/main/java/com/transistorsoft/rnbackgroundfetch/HeadlessTask.java
Notifee's use of the same https://github.com/invertase/notifee/blob/main/packages/react-native/android/src/main/java/io/invertase/notifee/HeadlessTask.java
Could likely pull the ideas in that code or maybe all of it pretty much verbatim into here and have a trusted solution
venux92 commentedon Jan 29, 2026
@mikehardy thanks for the feedback
I did not think of looking at notifee code ^^ even if I'm using it as well.
Nice and there are even check for new/old arch.
I could create a PR but as you contribute on both
notifeeandreact-native-firebaseI would probably also suggest a trusted solution, that would help if any update need to be made so they can be replicated quickly across both repo. Also I feel in the notifee version, there are extra nice checks with the atomicBoolean to prevent multiple initialisation of the react context.👍
Let me know
mikehardy commentedon Jan 29, 2026
Okay, for most folks seeing this, I recommend at least temporarily the patch posted by @venux92 #8654 (comment)
For most people that will work fine for now
If you are on old architecture, and also in certain corner cases, that patch won't handle everything perfectly.
As a permanent solution, a PR is needed that effectively takes the react-native-background-fetch solution (which was also adopted by notifee) and drops it in here. It handles old and new arch, it handles all the corner cases we are aware of, and it's well-tested in existing app deployments. There won't be a general solution that can be reused across repos, just copying the file contents in here and bending it to match the task we start is sufficient
I hope to get to that myself but it may be some time unfortunately, so any PR from affected parties that dropped that more robust solution here would be most welcome.