{"id":78829,"date":"2026-03-23T21:55:28","date_gmt":"2026-03-23T16:25:28","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=78829"},"modified":"2026-06-08T18:41:30","modified_gmt":"2026-06-08T13:11:30","slug":"push-notifications-using-firebase-cloud-messaging-in-react-native-a-step-by-step-guide","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/push-notifications-using-firebase-cloud-messaging-in-react-native-a-step-by-step-guide\/","title":{"rendered":"Push Notifications Using Firebase Cloud Messaging in React Native, A Step-by-Step Guide"},"content":{"rendered":"<div id=\"attachment_78858\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-78858\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78858 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/push_notification_react_native_communication-1024x576.png\" alt=\"Push Notification in React Native with FCM\" width=\"625\" height=\"352\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/push_notification_react_native_communication-1024x576.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/push_notification_react_native_communication-300x169.png 300w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/push_notification_react_native_communication-768x432.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/push_notification_react_native_communication-624x351.png 624w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/push_notification_react_native_communication.png 1200w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-78858\" class=\"wp-caption-text\">Push Notification in React Native with FCM<\/p><\/div>\n<h2><span style=\"text-decoration: underline;\">Introduction<\/span><\/h2>\n<p>Push notifications bridge the gap between your backend and the user&#8217;s device \u2014 essential for real-time alerts, order updates, or user engagement. Setting up FCM in React Native involves the Firebase Console, native Android configuration, runtime permissions, and JavaScript handlers. A misstep in any layer causes silent failures.<\/p>\n<p>While working on a React Native project, setting up push notifications was one of those things that looked simple at first but had a lot of moving parts once you got into it\u2014especially when handling different app states and platform quirks.<\/p>\n<p>In this guide, I\u2019ll walk through how to set up push notifications in a React Native app using Firebase Cloud Messaging (FCM), along with some practical notes from actually implementing it.<\/p>\n<h2><span style=\"text-decoration: underline;\">Why Push Notifications Matter<\/span><\/h2>\n<p>Push notifications give your app a direct line to the user\u2014even when the app isn\u2019t open. Whether it\u2019s a transactional update, a reminder, or something personalised, they help bring users back at the right moment.<\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"text-decoration: underline;\">Real-World Use Cases<br \/>\n<\/span><\/h2>\n<p>Push notifications are used in many real-world applications, not just for promotions or marketing messages. They help apps communicate important updates to users in real time.<\/p>\n<p>Some common use cases are the following:<\/p>\n<ul style=\"list-style-type: circle;\">\n<li>Order &amp; Delivery Updates<\/li>\n<li>Shopping and delivery apps use notifications to share order confirmations, shipment updates, and delivery status.<\/li>\n<li>Chat &amp; Messaging Apps<\/li>\n<li>Messaging apps notify users instantly when they receive new messages, even if the app is closed.<\/li>\n<li>Banking &amp; Security Alerts<\/li>\n<li>Banking apps use notifications for OTPs, transaction updates, and security alerts.<\/li>\n<li>Reminders &amp; Scheduling<\/li>\n<li>Healthcare, education, and productivity apps send reminders for appointments, meetings, tasks, or deadlines.<\/li>\n<li>Personalised Notifications<\/li>\n<\/ul>\n<p>While implementing FCM in React Native, one important learning was that handling notifications becomes more challenging when supporting different app states (foreground, background, and terminated) across multiple Android versions.<\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"text-decoration: underline;\">Setting Up Firebase \u2014 Dependencies &amp; Configuration<\/span><\/h2>\n<p><a href=\"https:\/\/rnfirebase.io\/storage\/usage\">https:\/\/rnfirebase.io\/storage\/usage<\/a><\/p>\n<div id=\"attachment_78859\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-78859\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78859 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.11.00\u202fPM-1024x492.png\" alt=\"rnfirebase.io\" width=\"625\" height=\"300\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.11.00\u202fPM-1024x492.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.11.00\u202fPM-300x144.png 300w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.11.00\u202fPM-768x369.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.11.00\u202fPM-1536x739.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.11.00\u202fPM-2048x985.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.11.00\u202fPM-624x300.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-78859\" class=\"wp-caption-text\">rnfirebase.io<\/p><\/div>\n<p>&nbsp;<\/p>\n<h4><span style=\"text-decoration: underline;\">React Native Code:<\/span><\/h4>\n<p>Install Required Packages:<\/p>\n<p><em>yarn add @react-native-firebase\/app<\/em><br \/>\n<em>yarn add @react-native-firebase\/messaging<\/em><\/p>\n<h3>Implementation \u2014 App.tsx<\/h3>\n<p>Import the following package after installation of the above dependencies:<\/p>\n<pre>import messaging from '@react-native-firebase\/messaging';<\/pre>\n<h4>Requesting Permission in Android:<\/h4>\n<div id=\"attachment_78861\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-78861\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78861 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.09.46\u202fPM-1-1024x219.png\" alt=\"Android Request Permission\" width=\"625\" height=\"134\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.09.46\u202fPM-1-1024x219.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.09.46\u202fPM-1-300x64.png 300w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.09.46\u202fPM-1-768x164.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.09.46\u202fPM-1-624x134.png 624w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.09.46\u202fPM-1.png 1382w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-78861\" class=\"wp-caption-text\">Android Request Permission<\/p><\/div>\n<p>&nbsp;<\/p>\n<h4>Full code snippet of app.tsx<\/h4>\n<div id=\"attachment_78911\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-78911\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78911\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-21-at-6.57.21\u202fPM-1024x926.png\" alt=\"App.tsx\" width=\"625\" height=\"565\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-21-at-6.57.21\u202fPM-1024x926.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-21-at-6.57.21\u202fPM-300x271.png 300w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-21-at-6.57.21\u202fPM-768x695.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-21-at-6.57.21\u202fPM-624x564.png 624w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-21-at-6.57.21\u202fPM.png 1486w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-78911\" class=\"wp-caption-text\">App.tsx<\/p><\/div>\n<p>&nbsp;<\/p>\n<h3>Once you run the app, the log will print the token something like this:<\/h3>\n<pre>Token:  \u00a0dHUmDe-FRnenw6UFw2km5n:APA91bHjDopiNnJ2w8kbdXvIGFPgZT6anTHXTqn2k016ukTRO0j81UJ1DSQ6KisPKi6W5_7Nae7k30v35CJtZhm8mSl2mypI8fgCUrY_odlyEthkugh6wp4\r\n\r\n<\/pre>\n<h3><span style=\"text-decoration: underline;\">\u00a0Handling Notifications Across App States<\/span><\/h3>\n<h4>1. Foreground State<\/h4>\n<pre>Handler: messaging().onMessage()<\/pre>\n<p>FCM delivers the payload to JavaScript but does not show a system notification. You handle the display via a toast or a local notification library.<\/p>\n<h4>2. Background State<\/h4>\n<pre>Handler messaging. setBackgroundMessageHandler()<\/pre>\n<p>The system shows the notification automatically. For custom logic, register a handler in `index.js` &#8216;<\/p>\n<div id=\"attachment_78871\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-78871\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78871 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.26.07\u202fPM-1024x357.png\" alt=\"Custom Notification\" width=\"625\" height=\"218\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.26.07\u202fPM-1024x357.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.26.07\u202fPM-300x105.png 300w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.26.07\u202fPM-768x268.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.26.07\u202fPM-1536x536.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.26.07\u202fPM-624x218.png 624w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.26.07\u202fPM.png 1600w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-78871\" class=\"wp-caption-text\">Custom Notification<\/p><\/div>\n<h2><span style=\"text-decoration: underline;\">Android Native Configuration:<\/span><\/h2>\n<h3>1. android\/build.gradle (Project-level)<\/h3>\n<h4>Add Google Services classpath:<\/h4>\n<pre>buildscript {\r\ndependencies {\r\nclasspath(\"com.google.gms:google-services:4.4.2\")\r\n}\r\n}<\/pre>\n<h3>2. android\/app\/build.gradle` (App-level)<\/h3>\n<h4>Apply the plugin at the top:<\/h4>\n<pre>apply plugin: \"com.android.application\"\r\napply plugin: \"org.jetbrains.kotlin.android\"\r\napply plugin: \"com.facebook.react\"\r\napply plugin: \"com.google.gms.google-services\"<\/pre>\n<h4>3. AndroidManifest.xml<\/h4>\n<h4>Add the `POST_NOTIFICATIONS` permission, the following (required for Android 13+):<\/h4>\n<pre>&lt;uses-permission android:name=\"android.permission.INTERNET\" \/&gt;\r\n&lt;uses-permission android:name=\"android.permission.POST_NOTIFICATIONS\" \/&gt;<\/pre>\n<h2><\/h2>\n<h2><span style=\"text-decoration: underline;\">Create Firebase Project &amp; Download&#8220;<\/span><\/h2>\n<p>1. Go to [Firebase Console](<a href=\"https:\/\/console.firebase.google.com\/\">https:\/\/console.firebase.google.com\/<\/a>) and create a project.<br \/>\n2. Navigate to **Messaging** under your project.<br \/>\n3. **Select Platform \u2014 Android.**<br \/>\n4. **Fill in the package name** \u2014 must match `applicationId &#8221; in `android\/app\/build.gradle &#8221; (e.g., `com.pushnotification &#8221;).<br \/>\n5. Download `google-services.json it and place it in the folder.<\/p>\n<p>&nbsp;<\/p>\n<div id=\"attachment_78874\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-78874\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78874 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.25.33\u202fPM-1-1024x398.png\" alt=\"firebase messaging\" width=\"625\" height=\"243\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.25.33\u202fPM-1-1024x398.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.25.33\u202fPM-1-300x117.png 300w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.25.33\u202fPM-1-768x299.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.25.33\u202fPM-1-1536x598.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.25.33\u202fPM-1-2048x797.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.25.33\u202fPM-1-624x243.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-78874\" class=\"wp-caption-text\">firebase messaging<\/p><\/div>\n<div id=\"attachment_78881\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-78881\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78881 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.27.35\u202fPM-3-1024x671.png\" alt=\"Package Name\" width=\"625\" height=\"410\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.27.35\u202fPM-3-1024x671.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.27.35\u202fPM-3-300x196.png 300w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.27.35\u202fPM-3-768x503.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.27.35\u202fPM-3-1536x1006.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.27.35\u202fPM-3-624x409.png 624w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.27.35\u202fPM-3.png 1878w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-78881\" class=\"wp-caption-text\">Package Name<\/p><\/div>\n<p>&nbsp;<\/p>\n<div id=\"attachment_78882\" style=\"width: 310px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-78882\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78882 size-medium\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.27.51\u202fPM-300x202.png\" alt=\"download google-services.json\" width=\"300\" height=\"202\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.27.51\u202fPM-300x202.png 300w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.27.51\u202fPM-1024x688.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.27.51\u202fPM-768x516.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.27.51\u202fPM-1536x1032.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.27.51\u202fPM-624x419.png 624w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.27.51\u202fPM.png 1992w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><p id=\"caption-attachment-78882\" class=\"wp-caption-text\">download google-services.json<\/p><\/div>\n<p>&nbsp;<\/p>\n<p>and place in the android\/app path like below:<\/p>\n<div id=\"attachment_78908\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-78908\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78908 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.22.39\u202fPM-1024x604.png\" alt=\"google-services.json\" width=\"625\" height=\"369\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.22.39\u202fPM-1024x604.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.22.39\u202fPM-300x177.png 300w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.22.39\u202fPM-768x453.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.22.39\u202fPM-624x368.png 624w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.22.39\u202fPM.png 1064w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-78908\" class=\"wp-caption-text\">google-services.json<\/p><\/div>\n<p>&nbsp;<\/p>\n<h2><span style=\"text-decoration: underline;\">Sending a Test Push Notification from Firebase Console<\/span><\/h2>\n<p>Once your setup is done and you have a device token, the easiest way to verify everything is working is by sending a test notification directly from the Firebase Console.<\/p>\n<p>Here\u2019s how you can do it:<\/p>\n<h5>Step 1: Open Firebase Console<\/h5>\n<p>Go to the Firebase Console:<a href=\"https:\/\/console.firebase.google.com\/\"> https:\/\/console.firebase.google.com\/<\/a> and open your project.<\/p>\n<p>From the left sidebar, navigate to the Engage section and click on Messaging (sometimes labelled as Campaigns).<\/p>\n<div id=\"attachment_78883\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-78883\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78883 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.46.42\u202fPM-1024x484.png\" alt=\"Create your first campaign.\" width=\"625\" height=\"295\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.46.42\u202fPM-1024x484.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.46.42\u202fPM-300x142.png 300w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.46.42\u202fPM-768x363.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.46.42\u202fPM-1536x726.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.46.42\u202fPM-2048x968.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.46.42\u202fPM-624x295.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-78883\" class=\"wp-caption-text\">Create your first campaign.<\/p><\/div>\n<p>&nbsp;<\/p>\n<h5>Step 2: Create a New Campaign<\/h5>\n<p>Click on \u201cCreate your first campaign\u201d (or \u201cNew campaign\u201d if you\u2019ve already created one before).<\/p>\n<p>Choose Firebase Cloud Messaging as the campaign type.<\/p>\n<div id=\"attachment_78884\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-78884\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78884 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.44.27\u202fPM-1024x609.png\" alt=\"Firebase Messaging Onboarding\" width=\"625\" height=\"372\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.44.27\u202fPM-1024x609.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.44.27\u202fPM-300x178.png 300w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.44.27\u202fPM-768x457.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.44.27\u202fPM-1536x914.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.44.27\u202fPM-2048x1218.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.44.27\u202fPM-624x371.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-78884\" class=\"wp-caption-text\">Firebase Messaging Onboarding<\/p><\/div>\n<p>&nbsp;<\/p>\n<h5>Step 3: Configure the Notification<\/h5>\n<p>You\u2019ll be prompted to enter the basic notification details:<\/p>\n<p>Title \u2013 This is what will appear as the notification heading<br \/>\nMessage \u2013 The body content of your push notification<br \/>\nKeep it simple for testing purposes.<\/p>\n<div id=\"attachment_78885\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-78885\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78885 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.17.07\u202fPM-1024x589.png\" alt=\"FCM title with Message\" width=\"625\" height=\"359\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.17.07\u202fPM-1024x589.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.17.07\u202fPM-300x173.png 300w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.17.07\u202fPM-768x442.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.17.07\u202fPM-1536x884.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.17.07\u202fPM-2048x1178.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.17.07\u202fPM-624x359.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-78885\" class=\"wp-caption-text\">FCM title with Message<\/p><\/div>\n<h5>Step 4: Send a Test Notification<\/h5>\n<p>On the right-hand side, you\u2019ll see a \u201cSend test message\u201d button.<\/p>\n<p>Clicking this will open a dialogue where you can enter the device token of the device you want to target.<\/p>\n<div id=\"attachment_78886\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-78886\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78886 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.17.20\u202fPM-1024x606.png\" alt=\"Add Token\" width=\"625\" height=\"370\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.17.20\u202fPM-1024x606.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.17.20\u202fPM-300x177.png 300w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.17.20\u202fPM-768x454.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.17.20\u202fPM-624x369.png 624w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.17.20\u202fPM.png 1522w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-78886\" class=\"wp-caption-text\">Add Token<\/p><\/div>\n<p>&nbsp;<\/p>\n<h5>Step 5: Add Device Token and Send<\/h5>\n<p>Paste your device token into the input field, select it, and click on the Test button.<\/p>\n<p>If everything is set up correctly, you should receive the push notification on your device almost instantly.<\/p>\n<div id=\"attachment_78887\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-78887\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78887 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.55.03\u202fPM-1024x694.png\" alt=\"Test on Device\" width=\"625\" height=\"424\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.55.03\u202fPM-1024x694.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.55.03\u202fPM-300x203.png 300w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.55.03\u202fPM-768x521.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.55.03\u202fPM-1536x1042.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.55.03\u202fPM-624x423.png 624w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-20-at-8.55.03\u202fPM.png 1566w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-78887\" class=\"wp-caption-text\">Test on Device<\/p><\/div>\n<p>&nbsp;<\/p>\n<p>Now the user will receive the notification, &#8216;Congratulations&#8217;.<\/p>\n<div id=\"attachment_78888\" style=\"width: 635px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-78888\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78888 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.19.13\u202fPM-1024x740.png\" alt=\"Background push notification Received\" width=\"625\" height=\"452\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.19.13\u202fPM-1024x740.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.19.13\u202fPM-300x217.png 300w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.19.13\u202fPM-768x555.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.19.13\u202fPM-1536x1111.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.19.13\u202fPM-624x451.png 624w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot-2026-03-19-at-7.19.13\u202fPM.png 1914w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-78888\" class=\"wp-caption-text\">Background push notification received.<\/p><\/div>\n<p>&nbsp;<\/p>\n<div id=\"attachment_78889\" style=\"width: 466px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-78889\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-78889 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot_1773926391-456x1024.png\" alt=\"Foreground push notification received.\" width=\"456\" height=\"1024\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot_1773926391-456x1024.png 456w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot_1773926391-134x300.png 134w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot_1773926391-768x1724.png 768w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot_1773926391-684x1536.png 684w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot_1773926391-912x2048.png 912w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot_1773926391-624x1401.png 624w, \/blog\/wp-ttn-blog\/uploads\/2026\/03\/Screenshot_1773926391.png 1080w\" sizes=\"(max-width: 456px) 100vw, 456px\" \/><p id=\"caption-attachment-78889\" class=\"wp-caption-text\">Foreground push notification received.<\/p><\/div>\n<p>&nbsp;<\/p>\n<p>Full Code:<br \/>\n\ud83d\udcbb GitHub:\u00a0<a href=\"https:\/\/github.com\/ketan7055\/RN-Push-Notification\">Repository<\/a><\/p>\n<h2><span style=\"text-decoration: underline;\">Challenges Faced During Implementation<\/span><\/h2>\n<p>Although Firebase Cloud Messaging (FCM) is easy to set up, implementing notifications in a real React Native app comes with a few challenges.<\/p>\n<h4>1. Different Behaviour Across App States<br \/>\nNotifications behave differently depending on whether the app is<\/h4>\n<ul>\n<li>In the foreground<\/li>\n<li>Running in the background<\/li>\n<li>Completely closed (terminated)<\/li>\n<\/ul>\n<p>For example:<\/p>\n<ul>\n<li>In the foreground, Android does not show notifications automatically.<\/li>\n<li>In the background, notifications are handled by the system.<\/li>\n<li>In the terminated state, the payload structure becomes very important.<br \/>\nBecause of this, separate handling and testing were needed for each app state.<\/li>\n<\/ul>\n<h4>2. Android Version Compatibility<br \/>\nStarting from Android 13 (API 33+), notification permission must be requested at runtime using POST_NOTIFICATIONS.<\/h4>\n<p>Without this permission:<\/p>\n<ul>\n<li>FCM tokens are still generated<\/li>\n<li>Firebase shows successful delivery<\/li>\n<li>But notifications do not appear on the device<br \/>\nThis can make debugging confusing.<\/li>\n<\/ul>\n<h4>3. Token Refresh Handling<br \/>\nFCM tokens can change after the following:<\/h4>\n<ul>\n<li>Reinstalling the app<\/li>\n<li>Clearing app data<\/li>\n<li>Device restoration<br \/>\nTo avoid notification failures, the updated token should always be synced with the backend server.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h2><span style=\"text-decoration: underline;\">Performance &amp; Reliability Considerations<\/span><\/h2>\n<p>In production environments, push notifications require more than just successful delivery. Reliability, battery optimisation, and user experience also become important factors.<\/p>\n<p>Battery Optimisation Restrictions<\/p>\n<p>Modern Android devices aggressively optimise background processes to improve battery life.<\/p>\n<p>On some devices (especially Xiaomi, Vivo, Oppo, and OnePlus), notifications may be delayed because the operating system restricts background services.<\/p>\n<p>During testing, notifications worked perfectly on some devices while appearing delayed on others due to manufacturer-specific battery optimisation policies.<\/p>\n<p>Notification Priority<\/p>\n<h4>Backend Retry Strategy<\/h4>\n<p>Push delivery is not guaranteed in unstable network conditions.<\/p>\n<p>To improve reliability, backend systems should:<\/p>\n<ul>\n<li>Store notification delivery status<\/li>\n<li>Retry failed notifications<\/li>\n<li>Handle invalid or expired FCM tokens<\/li>\n<\/ul>\n<p>This becomes especially important in transactional systems such as banking or delivery applications.<\/p>\n<h2><span style=\"text-decoration: underline;\">Common Issues &amp; Debugging<\/span><\/h2>\n<ul>\n<li>\n<table style=\"border-collapse: collapse; width: 100%; height: 240px;\">\n<tbody>\n<tr style=\"height: 24px;\">\n<td style=\"width: 33.3333%; text-align: center; height: 24px;\"><strong>Issue<\/strong><\/td>\n<td style=\"width: 33.3333%; text-align: center; height: 24px;\"><strong>Possible Cause<\/strong><\/td>\n<td style=\"width: 33.3333%; text-align: center; height: 24px;\"><strong>Solution<\/strong><\/td>\n<\/tr>\n<tr style=\"height: 24px;\">\n<td style=\"width: 33.3333%; height: 24px;\">Notifications not received<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Incorrect Firebase setup<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Verify google-services.json, package name, and Gradle plugin configuration<\/td>\n<\/tr>\n<tr style=\"height: 24px;\">\n<td style=\"width: 33.3333%; height: 24px;\">Token generation fails<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Firebase not initialised properly<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Check @react-native-firebase\/app installation<\/td>\n<\/tr>\n<tr style=\"height: 24px;\">\n<td style=\"width: 33.3333%; height: 24px;\">Foreground notifications not visible<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Expected FCM behaviour<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Use onMessage() and display local notification manually<\/td>\n<\/tr>\n<tr style=\"height: 24px;\">\n<td style=\"width: 33.3333%; height: 24px;\">Notifications delayed<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Battery optimisation restrictions<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Disable battery optimisation for testing<\/td>\n<\/tr>\n<tr style=\"height: 24px;\">\n<td style=\"width: 33.3333%; height: 24px;\">Android 13 notifications missing<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Runtime permission not requested<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Request POST_NOTIFICATIONS permission dynamically<\/td>\n<\/tr>\n<tr style=\"height: 24px;\">\n<td style=\"width: 33.3333%; height: 24px;\">Background handler not triggered<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Incorrect payload structure<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Use proper data payload configuration<\/td>\n<\/tr>\n<tr style=\"height: 24px;\">\n<td style=\"width: 33.3333%; height: 24px;\">Duplicate notifications<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Mixed local + remote notification handling<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Ensure notifications are not displayed twice<\/td>\n<\/tr>\n<tr style=\"height: 24px;\">\n<td style=\"width: 33.3333%; height: 24px;\">Build failures<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">SDK version mismatch<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Use compileSdkVersion 33+ and clean Gradle build<\/td>\n<\/tr>\n<tr style=\"height: 24px;\">\n<td style=\"width: 33.3333%; height: 24px;\">Token becomes invalid<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">App reinstall or token refresh<\/td>\n<td style=\"width: 33.3333%; height: 24px;\">Implement token refresh listener and backend sync<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/li>\n<\/ul>\n<h2><span style=\"text-decoration: underline;\">Conclusion<\/span><\/h2>\n<p>Implementing push notifications in React Native using Firebase Cloud Messaging is not just about integrating an SDK\u2014it requires careful handling of permissions, app lifecycle states, payload structures, and Android platform behaviours.<\/p>\n<p>The actual notification code is relatively small, but achieving reliable delivery across foreground, background, and terminated states requires thorough testing and proper native configuration.<\/p>\n<p>Some key learnings from this implementation were the following:<\/p>\n<ul>\n<li>Android notification behaviour varies significantly across OS versions<\/li>\n<li>Runtime permissions are critical for Android 13+<\/li>\n<li>Foreground notifications require manual handling<\/li>\n<li>Token management is essential for long-term reliability<\/li>\n<li>Device-specific battery optimisation can impact delivery consistency<\/li>\n<li>Once these areas are properly addressed, FCM becomes a reliable solution for building scalable real-time communication systems in React Native applications.<\/li>\n<\/ul>\n<p>At TO THE NEW, we help businesses build scalable mobile applications with production-ready notification systems and seamless user engagement experiences.<\/p>\n<p>We at\u00a0<a href=\"https:\/\/www.tothenew.com\/\">TO THE NEW<\/a> help\u00a0your business build web and hybrid applications for Android\/iOS mobile devices with native UI\/UX experience and performance. <a href=\"https:\/\/www.tothenew.com\/contact-us\">Contact us<\/a>\u00a0for more.<\/p>\n<p>&nbsp;<\/p>\n<h5><\/h5>\n<p>&nbsp;<\/p>\n<h3><\/h3>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Push notifications bridge the gap between your backend and the user&#8217;s device \u2014 essential for real-time alerts, order updates, or user engagement. Setting up FCM in React Native involves the Firebase Console, native Android configuration, runtime permissions, and JavaScript handlers. A misstep in any layer causes silent failures. While working on a React Native [&hellip;]<\/p>\n","protected":false},"author":1918,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":2},"categories":[5881],"tags":[721,4064,5853],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/78829"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1918"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=78829"}],"version-history":[{"count":29,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/78829\/revisions"}],"predecessor-version":[{"id":80026,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/78829\/revisions\/80026"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=78829"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=78829"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=78829"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}