I am trying to send data to the my app using firebase messaging. I receive the notification, but the background handler is never triggered on the app.
This is how I send the message
await admin.messaging().sendToDevice(
usersToken,
{
notification: {
title: title,
body: body,
sound : 'default'
},
data:{
test: 'hello',
}
},
{
// Required for background/quit data-only messages on Android
priority: 'high',
},
);
And the react code I tried to implement the handler inside and outside the App function, but none worked.
In App.tsx
/**
* This is the root component of our app.
*/
function App() {
}
// Register background handler
messaging().setBackgroundMessageHandler(async remoteMessage => {
console.log('Message handled in the background!', remoteMessage);
});
AppRegistry.registerComponent('app', () => App);
Second try:
/**
* This is the root component of our app.
*/
function App() {
// Register background handler
messaging().setBackgroundMessageHandler(async remoteMessage => {
console.log('Message handled in the background!', remoteMessage);
});
AppRegistry.registerComponent('app', () => App);
}
I receive the notification on the device, I get no errors, but the background handler is not triggered.
Related
I have built a React progressive web application that makes use of service workers.
The service worker gets registered and is activated:
I have been trying to detect the "activate" event using this:
service-worker.js
navigator.serviceWorker.addEventListener("activate", function (event) {
console.log("service worker activated");
});
I added that at the end of the service-worker file. But, this event never gets triggered and I have no idea why.
I also tried to implement push notifications and trigger the from the backend. For this, I needed a "push" event listener that would listen to these events from the server:
navigator.serviceWorker.addEventListener("push", async function (event) {
const message = await event.data.json();
let { title, description, image } = message;
await event.waitUntil(showPushNotification(title, description, image));
});
This is how showPushNotification is defined:
export function showPushNotification(title, description, image) {
if (!("serviceWorker" in navigator)) {
console.log("Service Worker is not supported in this browser");
return;
}
navigator.serviceWorker.ready.then(function (registration) {
registration.showNotification(title, {
body: description,
icon: image,
actions: [
{
title: "Say hi",
action: "Say hi",
},
],
});
});
}
I tested calling that function manually and it successfully triggerss a push notification.
This is the server code that triggers the push notification:
const sendPushNotification = async (user_id, title, description, image) => {
const search_option = { user: user_id };
const users_subscriptions = await PushNotificationSubscription.find(
search_option
);
const number_of_users_subscriptions = users_subscriptions.length;
const options = {
vapidDetails: {
subject: "mailto:xxxx#xxxx.com",
publicKey: VAPID_PUBLIC_KEY,
privateKey: VAPID_PRIVATE_KEY,
},
};
let push_notif_sending_results = {};
for (let i = 0; i < number_of_users_subscriptions; i++) {
const user_subscription = users_subscriptions[i];
await webPush
.sendNotification(
user_subscription,
JSON.stringify({
title,
description,
image,
}),
options
)
.then((notif_send_result) => {
push_notif_sending_results[i] = { success: notif_send_result };
})
.catch((error) => {
push_notif_sending_results[i] = { error: error };
});
}
return push_notif_sending_results;
};
This is the part responsible for sending the push notification:
webPush
.sendNotification(
user_subscription,
JSON.stringify({
title,
description,
image,
}),
options
)
And it's successfully executed as it returns a 201 HTTP response.
So the "push" event listener is supposed to detect it and trigger a push notification.
I think everything regarding the push notification has been successfully implementing and the problem is how the "push" event listener is added since the "activate" event listener also doesn't work.
So I tried moving the two event listeners here right after the registration of the service worker is successful:
function registerValidSW(swUrl, config) {
navigator.serviceWorker.register(swUrl).then((registration) => {
registration.addEventListener("activate", (event) => {
console.log(
"🚀 ~ file: serviceWorker.js:159 ~ navigator.serviceWorker.register ~ event",
event
);
});
registration.addEventListener("push", async function (event) {
const message = await event.data.json();
let { title, description, image } = message;
await event.waitUntil(
showPushNotification(title, description, image)
);
});
});
}
But, it's still the same result.
Neither the "push" nor the "activate" event listeners get triggered.
Any idea what's going on?
Here's the whole service-worker file:
service-worker.js
import axios from "axios";
const isLocalhost = Boolean(
window.location.hostname === "localhost" ||
// [::1] is the IPv6 localhost address.
window.location.hostname === "[::1]" ||
// 127.0.0.0/8 are considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
export function register(config) {
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets;
return;
}
window.addEventListener("load", () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
} else {
// Is not localhost. Just register service worker
console.log(
"Is not localhost. Just register a service worker, by calling registerValidSW"
);
registerValidSW(swUrl, config);
}
});
}
}
async function subscribeToPushNotifications(serviceWorkerReg) {
let subscription = await serviceWorkerReg.pushManager.getSubscription();
if (subscription === null) {
const dev_public_vapid_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const prod_public_vapid_key =
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const public_vapid_key = isLocalhost
? dev_public_vapid_key
: prod_public_vapid_key;
subscription = await serviceWorkerReg.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: public_vapid_key,
});
axios
.post("/api/push_notif_subscription/subscribe", subscription)
.then((response) => {})
.catch((error) => {});
}
}
export function showPushNotification(title, description, image) {
if (!("serviceWorker" in navigator)) {
console.log("Service Worker is not supported in this browser");
return;
}
navigator.serviceWorker.ready.then(function (registration) {
registration.showNotification(title, {
body: description,
icon: image,
actions: [
{
title: "Say hi",
action: "Say hi",
},
],
});
});
}
function registerValidSW(swUrl, config) {
navigator.serviceWorker.register(swUrl).then((registration) => {
subscribeToPushNotifications(registration);
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (!installingWorker) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === "installed") {
if (navigator.serviceWorker.controller) {
// At this point, the updated precached content has been fetched,
// but the previous service worker will still serve the older
// content until all client tabs are closed.
// Execute callback
if (config && config.onUpdate) {
config.onUpdate(registration);
}
} else {
// At this point, everything has been preached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
// Execute callback
if (config && config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
});
}
function checkValidServiceWorker(swUrl, config) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl, {
headers: { "Service-Worker": "script" },
}).then((response) => {
// Ensure the service worker exists, and that we really are getting a JS file.
const contentType = response.headers.get("content-type");
if (
response.status === 404 ||
(!!contentType && contentType.indexOf("javascript") === -1)
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then((registration) => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
console.log("Service worker found, calling registerValidSW");
registerValidSW(swUrl, config);
}
});
}
export function unregister() {
if ("serviceWorker" in navigator) {
navigator.serviceWorker.ready.then((registration) => {
registration.unregister();
});
}
}
navigator.serviceWorker.addEventListener("activate", function (event) {
console.log("service worker activated");
});
navigator.serviceWorker.addEventListener("push", async function (event) {
const message = await event.data.json();
let { title, description, image } = message;
await event.waitUntil(showPushNotification(title, description, image));
});
The events "push" and "activate" are part of the ServiceWorkerGlobalScope as within the Service Worker API.
Push notifications must be handled within the service worker itself.
Therefore only the service worker can register an "activate" event listener.
The same applies for a "push" listener.
Specially in terms of the "push" listener this makes sense.
The idea of push events is to receive them, even if the main app (in this case the website) has been closed.
The service worker is an exception, as it even runs without the page being loaded.
Therefore move the "push" event into your service worker.
Your code (within the service worker) may look like this:
this.addEventListener("push", async function (event) {
const message = await event.data.json();
let { title, description, image } = message;
await event.waitUntil(showPushNotification(title, description, image));
});
function showPushNotification(title, description, image) {
registration.showNotification(title, {
body: description,
icon: image,
actions: [
{
title: "Say hi",
action: "Say hi",
},
],
});
}
The rest seems fine to me.
Update (Some more explanation)
I took a more careful look at your service-worker.js and it seems it contains general methods for registering the service worker.
As mentioned above the main app and the service worker are two completely separate chunks of code, running in different spaces. So this means everything which is not supposed to run in the service worker itself must be put outside of the service-worker.js. The service worker (in your case) should only contain the code for handling push notifications. It's important that you do not include the "service-worker.js" within your application.
In your case, you may seperate these functions into service-worker-register.js which contain all functions which are for managing the service worker registration but should not be executed within the service worker itself (isLocalhost, register, subscribeToPushNotifications, registerValidSW, checkValidServiceWorker, and unregister). Please note the code snippet from above and make changes accordingly to the code left within the service worker.
MDN has a pretty in depth tutorial on service workers (and there are a lot more) I recommend having a look at:
developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers
I am using the latest react native version 0.62 and latest version of react-native-firebase i.e. v6. I am able to get the notification and it working fine on the background but its not displaying on foreground.
Here is the screenshot:
And here is my code:
checkPermission = async () => {
const enabled = await messaging().hasPermission();
console.log('enabled ******* ',enabled)
if (enabled) {
this.getFcmToken();
} else {
this.requestPermission();
}
};
getFcmToken = async () => {
const fcmToken = await messaging().getToken();
if (fcmToken) {
console.log('Your Firebase Token is:', fcmToken);
// this.showAlert('Your Firebase Token is:', fcmToken);
} else {
console.log('Failed', 'No token received');
}
};
requestPermission = async () => {
try {
await messaging().requestPermission();
// User has authorised
} catch (error) {
// User has rejected permissions
}
};
messageListener = async () => {
console.log('inside message listener ****** ')
messaging().onMessage(async remoteMessage => {
Alert.alert('A new FCM message arrived!', JSON.stringify(remoteMessage));
};
showAlert = (title, message) => {
Alert.alert(
title,
message,
[{ text: 'OK', onPress: () => console.log('OK Pressed') }],
{ cancelable: false },
);
};
componentDidMount() {
this.checkPermission();
this.messageListener();
}
By default rnfirebase not supporting displaying notification popup when app is in foreground state as they mentioned here. So push notification pop up only displayed when app is in background state or closed.
So if you want to display push notification on foreground mode also then you have to use extra library which will be display fired push notification as local notification as mention in their documentation.
If the RemoteMessage payload contains a notification property when sent to the onMessage handler, the device will not show any notification to the user. Instead, you could trigger a local notification or update the in-app UI to signal a new notification.
So as a solution you can use react-native-push-notification to fire push notification when app in foreground.
To do so, just install it by command :
npm i react-native-push-notification
For android you don't need to follow any native installation steps just install library by this command and then you can fire local push notification as below :
Create a file called NotificationController.android.js :
import React, { useEffect } from 'react';
import { Alert } from 'react-native';
import messaging from '#react-native-firebase/messaging';
import PushNotification from 'react-native-push-notification';
const NotificationController = (props) => {
useEffect(() => {
const unsubscribe = messaging().onMessage(async (remoteMessage) => {
PushNotification.localNotification({
message: remoteMessage.notification.body,
title: remoteMessage.notification.title,
bigPictureUrl: remoteMessage.notification.android.imageUrl,
smallIcon: remoteMessage.notification.android.imageUrl,
});
});
return unsubscribe;
}, []);
return null;
};
export default NotificationController;
Now, when app is in foreground state and if onMessage receive any message from firebase then PushNotification will fire local notification.
Update: For iOS
For iOS you have to install #react-native-community/push-notification-ios using this command:
npm i #react-native-community/push-notification-ios
Also follow all the native installation steps as suggested in document.
Then you can create file called NotificationController.ios.js where you can handle notification for iOS.
import { useEffect } from 'react';
import { Alert } from 'react-native';
import messaging from '#react-native-firebase/messaging';
import PushNotification from 'react-native-push-notification';
import PushNotificationIos from '#react-native-community/push-notification-ios';
const NotificationController = (props) => {
const navigation = useNavigation();
// Called when application is open by clicking on notification
// and called when application is already opend and user click on notification
PushNotification.configure({
onNotification: (notification) => {
if (notification) {
console.log(notification);
Alert.alert('Opened push notification', JSON.stringify(notification));
}
},
});
useEffect(() => {
// Usesd to display notification when app is in foreground
const unsubscribe = messaging().onMessage(async (remoteMessage) => {
PushNotificationIos.addNotificationRequest({
id: remoteMessage.messageId,
body: remoteMessage.notification.body,
title: remoteMessage.notification.title,
userInfo: remoteMessage.data,
});
});
return unsubscribe;
}, []);
return null;
};
export default NotificationController;
Now, call <NotificationController /> in you Home screen or App initial routing file.
I agree with all the above solutions...
I just wanted to add that, if you don't have channel id the use
PushNotification.createChannel(
{
channelId: 'fcm_fallback_notification_channel', // (required)
channelName: 'My channel', // (required)
channelDescription: 'A channel to categorise your notifications', // (optional) default: undefined.
soundName: 'default', // (optional) See `soundName` parameter of `localNotification` function
importance: 4, // (optional) default: 4. Int value of the Android notification importance
vibrate: true, // (optional) default: true. Creates the default vibration patten if true.
},
created => console.log(`createChannel returned '${created}'`),
);
and be careful while using
const dat = {
channelId: 'fcm_fallback_notification_channel', // (required)
channelName: 'My channel',
//... You can use all the options from localNotifications
message: notification.body, // (required)
title: notification.title,
};
console.log(dat)
PushNotification.localNotification(dat);
In some case when title: undefined, or title: Object{}, same for message might be happening so console log every thing and put it inside localNotification fuction
Following #Kishan Bharda solution, I had to do something different for IOS foreground notifications (here, I have the code in index.js instead of a different file):
import { AppRegistry, Platform } from 'react-native';
import App from './App';
import { name as appName } from './app.json';
import PushNotificationIOS from "#react-native-community/push-notification-ios";
import PushNotification from "react-native-push-notification";
if (Platform.OS === 'ios') {
// Must be outside of any component LifeCycle (such as `componentDidMount`).
PushNotification.configure({
onNotification: function (notification) {
console.log("NOTIFICATION:", notification);
const { foreground, userInteraction, title, message } = notification;
if (foreground && (title || message) && !userInteraction) PushNotification.localNotification(notification);
notification.finish(PushNotificationIOS.FetchResult.NoData);
}
});
}
AppRegistry.registerComponent(appName, () => App);
I am currently using FCM React Native Firebase, where I want to move the screen or take action when I open the fcm notification, like the image below :
react-native-fcm is now deprecated and no longer maintained. It is better to move to react-native-firebase.
Below shows example for react-native-firebase.
First you need to create a notification listener in your application. Mostly it is better to add it on top level root component.
You can passed relevant data on you notification payload data object. https://firebase.google.com/docs/cloud-messaging/concept-options
import firebase from 'react-native-firebase';
componentDidMount() {
this.createNotificationListeners();
}
componentWillUnmount() {
// Remove all the notification related listeners on unmounting the main dashboard
if (this.notificationOpenedListener) {
this.notificationOpenedListener();
}
}
/**
* Contains all the listeners related to the Firebase notification services.
*/
async createNotificationListeners() {
const handleNotification = notificationOpen => {
// Do what ever do you want, based on your notification payload
};
/*
* If app is in background, listen for when a notification is clicked / tapped / opened as follows:
* */
try {
this.notificationOpenedListener = firebase
.notifications()
.onNotificationOpened(notificationOpen => {
console.log(
'FirebaseDataReceiver remote notification clicked from background :',
notificationOpen,
);
handleNotification(notificationOpen);
});
} catch (e) {
console.log(
'Error while clicking the remote notification from background :',
e,
);
}
/*
* If app is closed, check if it was opened by a notification being clicked / tapped / opened as follows:
* */
try {
const notificationOpen = await firebase
.notifications()
.getInitialNotification();
if (notificationOpen) {
console.log(
'FirebaseDataReceiver remote notification clicked app start up :',
notificationOpen,
);
handleNotification(notificationOpen);
}
} catch (e) {
console.log(
'Error while clicking the app was initiated by a remote notification :',
e,
);
}
}
I've building a React Native app and using redux and have implemented the React-Navigation. I have a couple off issues I'm working through and below is one of them that might be able to tackle both problems.
My screen flow is supposed to look like this:
Login (via Facebook)
Dashboard (via automatic re-direct using React-Navigation)
While this flow works, I'm finding that once I land on the Dashboard, the screen is frozen. If I restart the app, the app does work as intended (i.e. it makes a firebase call to retrieve my credentials, and automatically redirects from the Login screen to the Dashboard). The Dashboard then accepts all touches and the UI works fine.
Any idea what might be going? I feel like the issue is with how I'm setting up my listeners. I've implemented my navigation into redux as well. I've pulled out the relevant code below, but you can find the full code in the github links as well.
.src/actions/actions.js
(github link: actions.js)
// User Stuff
export const watchUserData = () => (
(dispatch) => {
currentUserListener((user) => {
// if (user !== null) {
if (user) {
console.log('from action creator login: ' + user.displayName);
dispatch(loadUser(user));
dispatch(watchReminderData(user.uid)); //listener to pull reminder data
dispatch(watchContactData(user.uid)); //listener to pull contact data
dispatch(watchPermissions(user.uid)); //listener to pull notificationToken
} else {
console.log('from action creator: ' + user);
dispatch(removeUser(user));
dispatch(logOutUser(false));
dispatch(NavigationActions.navigate({ routeName: 'Login' }));
}
});
}
);
export const watchUserDataForLogin = () => (
(dispatch) => {
currentUserListener((user) => {
if (!_.isEmpty(user)) {
dispatch(loadUser(user));
dispatch(setLoggedInUser(true));
dispatch(NavigationActions.navigate({ routeName: 'Dashboard' }));
}
});
}
);
.src/screens/Login.js
github link: Login.js
componentDidMount = () => {
this.unsubscribeCurrentUserListener = currentUserListener((snapshot) => {
try {
this.props.watchUserDataForLogin();
} catch (e) {
this.setState({ error: e, });
}
});
};
componentWillUnmount = () => {
if (this.unsubscribeCurrentUserListener) {
this.unsubscribeCurrentUserListener();
}
};
.src/screens/Dashboard.js
github link: Dashboard.js
componentDidMount = () => {
// Listener that loads the user, reminders, contacts, and notification data
// this.unsubscribeCurrentUserListener = currentUserListener((snapshot) => {
// try {
// this.props.watchUserData();
// } catch (e) {
// this.setState({ error: e, });
// }
// });
this.unsubscribeCurrentUserListener = this.props.watchUserData();
};
Let me know if you need additional information. Was trying to keep it succinct, but can add more details. Thanks!
Okay, I figured out what was going on. I had set up the listener incorrectly and so I couldn't unsubscribe from it once I left the login screen. The code now looks like this:
src/screen/Login.js
componentDidMount = () => {
this.unsubscribeCurrentUserListener = this.props.watchUserDataForLogin();
};
componentWillUnmount = () => {
if (this.unsubscribeCurrentUserListener) {
this.unsubscribeCurrentUserListener();
}
};
I'm trying to implement push notification with React Native and Firebase through this documentation.
I set up the settings I need by the tutorial.
import React, { Component } from 'react'
import { View } from 'react-native'
import { Input, Text, Button } from '../Components'
import type { RemoteMessage } from 'react-native-firebase'
import firebase from 'react-native-firebase'
import type { Notification, NotificationOpen } from 'react-native-firebase';
export default class TestComponent extends Component {
async componentDidMount() {
await this.SetUpAuth();
await this.SetUpMessaging();
this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen: NotificationOpen) => {
// Get the action triggered by the notification being opened
const action = notificationOpen.action;
// Get information about the notification that was opened
const notification: Notification = notificationOpen.notification;
});
const notificationOpen: NotificationOpen = await firebase.notifications().getInitialNotification();
if (notificationOpen) {
console.log(notificationOpen)
// App was opened by a notification
// Get the action triggered by the notification being opened
const action = notificationOpen.action;
// Get information about the notification that was opened
const notification: Notification = notificationOpen.notification;
}
}
componentWillUnmount() {
}
async SetUpAuth() {
const credential = await firebase.auth().signInAnonymouslyAndRetrieveData();
if (credential) {
console.log('default app user ->', credential.user.toJSON());
} else {
console.error('no credential');
}
}
async SetUpMessaging() {
this.notification2 = new firebase.notifications.Notification()
.setNotificationId('notificationId')
.setTitle('My notification title')
.setBody('My notification body')
.android.setChannelId('test')
.android.setClickAction('action')
.setData({
key1: 'value1',
key2: 'value2',
});
this.notification2
.android.setChannelId('channelId')
.android.setSmallIcon('ic_launcher');
console.log('assa')
onTokenRefreshListener = firebase.messaging().onTokenRefresh(fcmToken => {
console.log('token generated ->', fcmToken);
// store.dispatch(DeviceActions.SetFCMToken(fcmToken));
});
const fcmToken = await firebase.messaging().getToken();
if (fcmToken) {
// user has a device token
console.log('has token ->', fcmToken);
console.log(firebase.auth().currentUser._user)
firebase.database().ref(`/users/${firebase.auth().currentUser._user.uid}`).set({ pushToken: fcmToken })
// store.dispatch(DeviceActions.SetFCMToken(fcmToken));
} else {
// user doesn't have a device token yet
console.error('no messaging token');
}
const messagingEnabled = await firebase.messaging().hasPermission();
if (messagingEnabled) {
// user has permissions
console.log('User has FCM permissions');
} else {
// user doesn't have permission
console.log('User does not have FCM permissions');
await this.RequestMessagePermissions();
}
messageListener = firebase.messaging().onMessage((message: RemoteMessage) => {
console.log(`Recieved message - ${JSON.stringify(message)}`);
});
notificationDisplayedListener = firebase
.notifications()
.onNotificationDisplayed(notification => {
// Process your notification as required
// ANDROID: Remote notifications do not contain the channel ID. You will have to specify this manually if you'd like to re-display the notification.
console.log(`Recieved notification 1`);
});
notificationListener = firebase
.notifications()
.onNotification(notification => {
console.log(notification)
firebase.notifications().displayNotification(this.notification2)
// Process your notification as required
console.log(`Recieved notification 2`);
});
}
async RequestMessagePermissions() {
console.log('request')
console.log('Requesting FCM permission');
await firebase
.messaging()
.requestPermission()
.catch(err => console.err(err));
}
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
</View>
)
}
When I try to use it in postman I get success:
{
"success": {
"results": [
{
"messageId": "0:1525013439417985%a0cec506a0cec506"
}
],
"canonicalRegistrationTokenCount": 0,
"failureCount": 0,
"successCount": 1,
"multicastId": 6840884736220792000
}
}
But in my debugger (by console.log) I don't see any new incoming message or something else. I sent a message to my device with the token I added to this post but nothing happened.
it works only when app is in foreground, But I want to make it work also when app in background/closed the app
As mentioned in the docs you need onNotificationOpened listener for android, when the app is in background
Android Background: onNotificationOpened triggered if the notification is tapped.
onNotificationDisplayed is for IOS app in background and triggered if content_available set to true
notificationBackgroundListener = firebase
.notifications()
.onNotificationOpened(notification => {
// Process your notification as required
console.log(`Recieved notification 2`);
});
If your notification is working fine when your app is in foreground then the problem is with your service. There are two possible reasons it's not working.
Either you are sending the payload as
{
time_to_live: 86400,
collapse_key: "xxxxxx",
delay_while_idle: false,
registration_ids: registration_ids,
notification: payload
}
instead of
{
time_to_live: 86400,
collapse_key: "xxxxxx",
delay_while_idle: false,
registration_ids: registration_ids,
data: payload
}
which is because the key in notification is recieved only when app is in foreground.
Another possible reason could be the service worker is getting killed for some reason. ex: I was using a one plus which auto kills the service when I force close the app. So you can try debugging your service in native code by adding log or attaching a debugger
also make sure to add google-service.json file in your android/app folder
Edit:
{
"registration_ids" : ["reg_id"],
"time_to_live": 86400,
"collapse_key": "test_type_b",
"delay_while_idle": false,
"notification": {},
"data": {
"subText":"sub title R",
"title":"Notification Heading R",
"message":"Short big text that will be shown when notification is expanded R",
"color":"red",
"actions": ["hello", "welcome"],
"vibrate": true,
"vibration": 1000,
"ticker": "My Notification Ticker",
"imageUrl": "https://cdn-images-1.medium.com/max/712/1*c3cQvYJrVezv_Az0CoDcbA.jpeg" ,
"bigText": "blalMy big text that will be shown when notification is expanded"
}
}
Here is my headers
Authorization: key=mykey:myKey
Content-Type: application/json
Request:
https://fcm.googleapis.com/fcm/send
which is of post and params are of raw type
you can use Headless JS to run task in background and you should write some native code to handle task , unfortunately is only available in android
https://facebook.github.io/react-native/docs/headless-js-android.html
second way(i don't test it) is to use this library
https://github.com/jamesisaac/react-native-background-task#installation
ps:firebase and other push notification service like onesignal handle push notification easily and you should not be concerned unless you want unique notification for each user