Notifications are not showing while the app is in foreground - react-native

I am trying to send push notifications using react-native-firebase through firebase console when my app is closed or in the background, the notifications are received and shown as a pop-up but if my app is in the foreground the notifications are not appearing
I have been trying to do some code in on notification method as suggested in the docs but it's not working
please suggest something that my app can show notifications in foreground

Please refer following link.
https://rnfirebase.io/docs/v5.x.x/messaging/android#(Optional)-Background-Messages
If you added, remove following line from your AndroidManifest.xml.
<service android:name="io.invertase.firebase.messaging.RNFirebaseBackgroundMessagingService" />

create a new notifactionHandler.js and import the code below.
import firebase from 'react-native-firebase';
exports.setNotificationListener = () => {
return new Promise((resolve, reject) => {
// triggers when notifiaction received while app on foreground
this.notificationListener = firebase.notifications().onNotification((notification) => {
console.log(notification.data);
setNotification({notification})
});
resolve(true);
})
};
const setNotification = ({notification}) => {
firebase.notifications().displayNotification(notification);
}
then import it on your splash or main page.
then call setNotificationListener function. basicly firebase.notifications().onNotification catches notifications while app on foreground, and displays it with firebase.notifications().displayNotification

in my case:
import firebase from 'firebase';
import * as Notice from "react-native-firebase";
componentDidMount() {
const firebaseConfig = {
apiKey: "**********",
authDomain: "**********",
databaseURL: "**********",
projectId: "**********",
storageBucket: "**********",
messagingSenderId: "**********",
appId: "**********"
};
this.mNotifiConfig()
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
}
mNotifiConfig = async() => {
Notice.messaging().hasPermission()
.then(enabled => {
console.log('HAS PERMISS: ', enabled)
if (enabled) {
Notice.messaging().getToken().then(token => {
console.log("LOG: ", token);
}).catch(err=> console.log(err))
} else {
Notice.messaging().requestPermission()
}
});
const notificationOpen = await Notice
.notifications()
.getInitialNotification();
if (notificationOpen) {
const action = notificationOpen.action;
const notification = notificationOpen.notification;
var seen = [];
// this.onActionWithNotification(notification)
console.log('NOTIFICATION IS OPNE')
}
// config android
const channel = new Notice.notifications.Android.Channel(
"test-channel",
"Test Channel",
Notice.notifications.Android.Importance.Max
).setDescription("My apps test channel");
// Create the channel
Notice.notifications().android.createChannel(channel);
this.notificationDisplayedListener = Notice
.notifications()
.onNotificationDisplayed((notification: Notification) => {
console.log('CREATED CHANNEL')
// 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.
});
this.notificationListener = Notice
.notifications()
.onNotification((notification: Notification) => {
console.log('HAS Notification: ', notification)
// Process your notification as required
// notification.android
// .setChannelId("test-channel")
// .android.setSmallIcon("ic_launcher");
// firebase.notifications().displayNotification(notification).catch(err => console.error(err));
let notification_to_be_displayed = new Notice.notifications.Notification({
data: notification.data,
sound: 'default',
show_in_foreground: true,
title: notification.title,
body: notification.body,
});
if(Platform.OS == "android") {
notification_to_be_displayed
.android.setPriority(Notice.notifications.Android.Priority.High)
.android.setChannelId("test-channel")
.android.setSmallIcon("ic_launcher")
.android.setVibrate(1000);
}
Notice.notifications().displayNotification(notification_to_be_displayed);
});
this.notificationOpenedListener = Notice
.notifications()
.onNotificationOpened((notificationOpen) => {
// Get the action triggered by the notification being opened
const action = notificationOpen.action;
// Get information about the notification that was opened
const notification = notificationOpen.notification;
var seen = [];
console.log('notification Day nay', notification)
Notice
.notifications()
.removeDeliveredNotification(notification.notificationId);
// this.onLinkingtoApp()
});
this.onMessageListener = Notice.messaging().onMessage((message: RemoteMessage) => {
const {data} = message
const showNotif = new Notice.notifications.Notification()
.setNotificationId('notificationId')
.setTitle(data.title || 'Thông báo')
.setBody(data.content || 'Bạn có một thông báo mới')
.setData(data)
.android.setChannelId('test-channel')
.android.setSmallIcon('ic_launcher')
Notice.notifications().displayNotification(showNotif)
})
}

Related

DeviceNotRegistered: "ExponentPushToken[***]" is not a registered push notification recipient

I'm trying to implement expo push notifications on react native app built with expo !
I did everything mentioned on their docs ! i'm getting the token successfully but when i try sending a push notification to that token using their api or the tool they provide i get this error
DeviceNotRegistered: "ExponentPushToken[***]" is not a registered push notification recipient
This is how i'm getting the token !
export const useNotifications = () => {
const registerForPushNotificationsAsync = async () => {
if (Device.isDevice) {
const { status: existingStatus } =
await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== "granted") {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== "granted") {
alert("Failed to get push token for push notification!");
return;
}
const token = (await Notifications.getExpoPushTokenAsync()).data;
console.log("TOKEN------------", token);
alert(token);
} else {
alert("Must use physical device for Push Notifications");
}
if (Platform.OS === "android") {
Notifications.setNotificationChannelAsync("default", {
name: "default",
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: "#FF231F7C",
});
}
};
const handleNotification = (notification = Notifications.Notification) => {
// could be useful if you want to display your own toast message
// could also make a server call to refresh data in other part of the app
};
// This listener is fired whenever a user taps on or interacts with a notification (works when app is foregrounded, backgrounded, or killed)
const handleNotificationResponse = (
response = Notifications.NotificationResponse
) => {
const data = ({ url } = response.notification.request.content.data);
if (data?.url) Linking.openURL(data.url);
};
return {
registerForPushNotificationsAsync,
handleNotification,
handleNotificationResponse,
};
};
useEffect(() => {
registerForPushNotificationsAsync();
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: true,
}),
});
const responseListener =
Notifications.addNotificationResponseReceivedListener(
handleNotificationResponse
);
return () => {
if (responseListener) {
Notifications.removeNotificationSubscription(responseListener);
}
};
}, []);
i run the eas build eas build -p android --profile preview so i can test it on a real device since push notifications works only on real devices and after that i pushed the cloud messaging server key that i got from my firebase project with this command expo push:android:upload --api-key <your-token-here>
As i said i successfully get the token but the i get the error when trying to send the notification!
am i missing a step or something ?
I tried run the build on two devices and both not working !

react native using onesignal the userid generated only after app reload not before

my code is this..so the issue is the userid doesnot generated on first go after reloading the app only userid generates how can i fixed this issue..
//App.js
useEffect(() => {
OneSignal.setLogLevel(6, 0);
OneSignal.setAppId("c35be357-fc37-4423-a162-b63ef396e998");
OneSignal.getDeviceState().then(res => {
AsyncStorage.setItem('push_user_id', res.userId || '');
console.log(res.userId,'res res res onesignal');
});
OneSignal.setNotificationWillShowInForegroundHandler(notificationReceivedEvent => {
console.log("OneSignal: notification will show in foreground:", notificationReceivedEvent);
let notification = notificationReceivedEvent.getNotification();
console.log("notification: ", notification);
const data = notification.additionalData
console.log("additionalData: ", data);
notificationReceivedEvent.complete(notification);
});
OneSignal.setNotificationOpenedHandler(notification => {
console.log("OneSignal: notification opened:", notification);
});
},[]);

react-native-background-actions issue for ios

Iam using react-native-background-actions to run a background task.
but when I exit app, the task just run in 30s and stop
How I can resolve to run forever, atleast untill app terminated
In my code, after 1s, increate 'COUNT' and save to Storage
// BackgroundTaskService.js
import AsyncStorage from '#react-native-community/async-storage';
import BackgroundService from 'react-native-background-actions';
import BackgroundJob from 'react-native-background-actions';
let sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
const increaseCountTask = async taskDataArguments => {
const {delay} = taskDataArguments;
await new Promise(async resolve => {
for (let i = 0; BackgroundJob.isRunning(); i++) {
var value = await AsyncStorage.getItem('COUNT');
if(!value) {
await AsyncStorage.setItem('COUNT', "2");
}
var value = await AsyncStorage.getItem('COUNT');
await AsyncStorage.setItem('COUNT', (parseInt(value) + 1).toString());
value = await AsyncStorage.getItem('COUNT');
console.log('value', value);
await sleep(delay);
}
});
};
const options = {
taskName: 'Demo',
taskTitle: 'Demo Running',
taskDesc: 'Demo',
taskIcon: {
name: 'ic_launcher',
type: 'mipmap',
},
color: '#ff00ff',
parameters: {
delay: 1000,
},
actions: '["Exit"]',
};
const start = () => {
BackgroundService.start(increaseCountTask, options);
};
const stop = () => {
BackgroundService.stop();
};
export default {
start,
stop,
};
// App.js
BackgroundTaskService.start();
Are you testing on a physical device and have enabled Background App Refresh in the Xcode settings, as well as on your physical device? According to documentation in another package, React-native-background-task indicates that that package must be tested on a physical device, or else the iOS simulator version will have to emulate the tasks.
I attempted to rework your code. I am currently getting this to work with BackgroundService instead of BackgroundJob for running in the background of the app. I am also working on testing when the app is closed. Should be able to get back to you soon.
import BackgroundService from 'react-native-background-actions';
import AsyncStorage from "#react-native-async-storage/async-storage";
import BackgroundJob from 'react-native-background-actions';
import {Alert} from "react-native";
const sleep = (time) => new Promise((resolve) => setTimeout(() => resolve(), time));
// You can do anything in your task such as network requests, timers and so on,
// as long as it doesn't touch UI. Once your task completes (i.e. the promise is resolved),
// React Native will go into "paused" mode (unless there are other tasks running,
// or there is a foreground app).
const veryIntensiveTask = async (taskDataArguments) => {
// Example of an infinite loop task
const { delay } = taskDataArguments;
await new Promise( async (resolve) => {
for (let i = 0; BackgroundService.isRunning(); i++) {
console.log(i);
console.log("Running background task");
Alert.alert("Running background task");
await sleep(delay);
}
// for (let i = 0; BackgroundJob.isRunning(); i++) {
//
// var value = await AsyncStorage.getItem('COUNT');
// if(!value) {
// await AsyncStorage.setItem('COUNT', "2");
// }
// var value = await AsyncStorage.getItem('COUNT');
// await AsyncStorage.setItem('COUNT', (parseInt(value) + 1).toString());
// value = await AsyncStorage.getItem('COUNT');
// console.log('value', value);
// await sleep(delay);
//
// }
});
};
const options = {
taskName: 'Example',
taskTitle: 'ExampleTask title',
taskDesc: 'ExampleTask description',
taskIcon: {
name: 'ic_launcher',
type: 'mipmap',
},
color: '#ff00ff',
linkingURI: 'yourSchemeHere://chat/jane', // See Deep Linking for more info
parameters: {
delay: 10000,
},
};
const start = async () => {
return BackgroundService.start(veryIntensiveTask, options);
};
const stop = async () => {
return BackgroundService.stop();
};
export default {
start,
stop,
};
// await BackgroundService.start(veryIntensiveTask, options);
// await BackgroundService.updateNotification({taskDesc: 'New ExampleTask description'}); // Only Android, iOS will ignore this call
// // iOS will also run everything here in the background until .stop() is called
// await BackgroundService.stop();

React native firebase push notification not working for iOS

I have recently upgraded my RN 0.57.1 to RN 0.59.1, Push notification is working properly earlier but now push notification only working when the app installed first time.
package.json:
"react": "16.8.3",
"react-native": "^0.59.1",
"react-native-firebase": "^5.2.0"
I have tried with https://pushtry.com to test the actual issue and it's showing me "NotRegistered". It was working perfect in my old builds but I don't know why it's creating issues.
Here is my code:
info.plist:
<key>FirebaseAppDelegateProxyEnabled</key>
<string>no</string>
<key>FirebaseDataCollectionDefaultEnabled</key>
<string>Yes</string>
<key>LSApplicationQueriesSchemes</key>
app.js:
async componentDidMount() {
this.checkPermission();
this.createNotificationListeners();
}
componentWillUnmount() {
this.notificationListener();
this.notificationOpenedListener();
}
async createNotificationListeners() {
this.notificationListener = firebase.notifications().onNotification((notification) => {
const { title, body} = notification.data;
this.title = title;
this.body = body;
const localNotification = new firebase.notifications.Notification({
sound: 'default',
show_in_foreground: true,
})
.setNotificationId(notification.notificationId)
.setTitle(notification.title)
.setBody(notification.body)
.setData(notification.data)
.android.setAutoCancel(true)
.android.setChannelId('mybeautysquad') // e.g. the id you chose above
.android.setSmallIcon('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));
});
/*
* 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.data;
this.title = title;
this.body = 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.data;
this.title = title;
this.body = body;
}
/*
* Triggered for data only payload in foreground
* */
this.messageListener = firebase.messaging().onMessage((message) => {
//process data message
console.log(JSON.stringify(message));
});
}
async checkPermission() {
const enabled = await firebase.messaging().hasPermission();
if (enabled) {
this.getToken();
} else {
this.requestPermission();
}
}
async getToken() {
let fcmToken = await AsyncStorage.getItem('fcmToken');
console.log(fcmToken);
if (!fcmToken) {
fcmToken = await firebase.messaging().getToken();
if (fcmToken) {
// user has a device token
await AsyncStorage.setItem('fcmToken', fcmToken);
}
}
}
async requestPermission() {
try {
await firebase.messaging().requestPermission();
// User has authorised
this.getToken();
} catch (error) {
// User has rejected permissions
console.log('permission rejected');
}
}
Also, I am saving sane FCM token on the server when login and check if user FCM token not updated in login then I am also updating their FCM device token when they update their profile.
Please let me know if anyone can help me into this...Thanks!

When receiving messages from firebase console, app crashes(<appName> has stopped)

When I send test message from firebase console to my device, the app crashes without any console log.
Installed packages:
"react": "16.6.3"
"react-native": "^0.59.8"
"react-native-device-info": "^1.4.3"
"react-native-firebase": "^5.3.1"
"react-native-paper": "^2.12.0"
"react-native-vector-icons": "^6.3.0"
build.gradle
// Firebase dependencies
implementation "com.google.android.gms:play-services-base:16.1.0"
implementation "com.google.android.gms:play-services-auth:16.0.1"
implementation "com.google.firebase:firebase-core:16.0.9"
implementation "com.google.firebase:firebase-messaging:18.0.0"
Things already tried:
adb logcat - no use
adb logcat *:S ReactNative:V ReactNativeJS:V - no use
//App.js code for receiving remote notification
async componentDidMount() {
this.checkPermission();
this.onTokenRefreshListener = firebase.messaging().onTokenRefresh(fcmToken => {
// Process your token as required
Alert.alert(fcmToken);
});
this.messageListener = firebase.messaging().onMessage((message) => {
console.log("JSON.stringify:", JSON.stringify(message));
Alert.alert(message);
});
this.notificationDisplayedListener = firebase.notifications().onNotificationDisplayed((notification: 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)
});
this.notificationListener = firebase.notifications().onNotification((notification: Notification) => {
console.log("test");
});
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 = await firebase.notifications().getInitialNotification();
if (notificationOpen) {
const { title, body } = notificationOpen.notification;
console.log('getInitialNotification:');
Alert.alert(title, body)
}
}
componentWillUnmount() {
try {
this.onTokenRefreshListener();
this.messageListener();
this.notificationListener();
this.notificationOpenedListener();
} catch (error) {
console.error(error)
}
}
async checkPermission(){
const enabled = await firebase.messaging().hasPermission();
if (enabled) {
this.getToken();
} else {
this.requestPermission();
}
}
async getToken(){
const fcmToken = await firebase.messaging().getToken();
if (fcmToken) {
console.log("FCMToken:"+fcmToken);
this.setState({test:fcmToken})
} else {
// user doesn't have a device token yet
}
}
async requestPermission(){
try {
await firebase.messaging().requestPermission();
// User has authorised
} catch (error) {
// User has rejected permissions
}
}
I missed out the code in AndroidManifest.xml file. If any one facing same issue do check this file.