How to Take Action / Move Screen When FCM Notification is Opened? - javascript

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,
);
}
}

Related

Firebase background message handler not triggered in react

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.

Push Notification - I can send message to emulator, but not in real device

Currently, I'm doing push notification using Firebase on Ios and have some problems in my app.
I can receive message from server. I'm using Pushtry to test notification.
However, when I tried to use my real device ( iPhone 6 Plus, ios 12 ), Pushtry returned:
InvalidApnsCredential
So why I didnt receive anything from body ( with emulator ) ? which step am I doing wrong ( with real device ) ? Do I need to check anything related to certification ?
I want to do something like this:
And this is my code:
async createNotificationListeners() {
/*
* Triggered when a particular notification has been received in foreground
* */
this.notificationListener = firebase.notifications().onNotification((notification) => {
const { title, body } = notification;
console.log('onNotification:');
const localNotification = new firebase.notifications.Notification({
show_in_foreground: true,
})
.setNotificationId(notification.notificationId)
.setTitle(notification.title)
.setBody(notification.body)
.android.setChannelId('fcm_FirebaseNotifiction_default_channel') // e.g. the id you chose above
.android.setSmallIcon('#drawable/ic_launcher') // create this icon in Android Studio
.android.setColor('#000000') // you can set a color here
.android.setPriority(firebase.notifications.Android.Priority.High)
firebase.notifications()
.displayNotification(localNotification)
.catch(err => console.error(err));
});
const channel = new firebase.notifications.Android.Channel('fcm_FirebaseNotifiction_default_channel', 'Demo app name', firebase.notifications.Android.Importance.High)
.setDescription('Demo app description')
firebase.notifications().android.createChannel(channel);
/*
* If your app is in background, you can listen for when a notification is clicked / tapped / opened as follows:
* */
this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen) => {
const { title, body } = notificationOpen.notification;
console.log('onNotificationOpened:');
alert(title, body)
});
/*
* If your app is closed, you can check if it was opened by a notification being clicked / tapped / opened as follows:
* */
const notificationOpen = await firebase.notifications().getInitialNotification();
if (notificationOpen) {
const { title, body } = notificationOpen.notification;
console.log('getInitialNotification:');
alert(title, body)
}
/*
* Triggered for data only payload in foreground
* */
this.messageListener = firebase.messaging().onMessage((message) => {
//process data message
console.log("JSON.stringify:", JSON.stringify(message));
});
}
Is there any further step should I follow ?

How should I handle push notifications in react native firebase app if closed or running in background

first if app closed:
this.notificationOpenedListener = firebase.notifications()
.getInitialNotification()
.then((notificationOpen: NotificationOpen) => {
if (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;
}
});
second if app running on background:
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;
});
how to join code first and second.
reference : Here's a link!
or how to whip an application closed or running in the background react native?

How to unsubscribe react-native-firebase getInitialNotification

I am using react-native-firebase for push notifications in a react-native application.
When a notification is received, opens the app by clicking on the notification (this works correctly by triggering the getInitialNotification function). However, when i navigate from one screen to another it will be triggered again. How can this be stopped? is there any alternative to unsubscribe this event after it is triggered?
Or is there any workaround to this issue?
class Header extends Component {
async componentDidMount() {
this.checkPermission();
this.createNotificationListeners();
}
componentWillUnmount() {
this.notificationListener();
this.notificationOpenedListener();
}
async checkPermission() {
const enabled = await firebase.messaging().hasPermission();
if (enabled) {
this.getToken();
}
}
async getToken() {
//token retrieve code
}
async createNotificationListeners() {
firebase.messaging().subscribeToTopic("all")
/*
* If your app is closed, you can check if it was opened by a notification being clicked / tapped / opened as follows:
* */
const notificationOpen = await firebase.notifications().getInitialNotification();
if (notificationOpen) {
alert(title, body);
}
}
render() {
return (
<View></View>
);
}
}

React native with Firebase FCM

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

Categories