Push notification is not receiving when the app is installed for first time - firebase-cloud-messaging

When I installed the app for first time the push notification is not receiving, if I kill the app and open again the push notifications is working fine.
When I console the code and trigger the push notification manually through FCM , I found that the notification data is not receiving on the onMessage function and on getInitialNotification() the result shows as undefined.
Please check the below code for getting push notifications and also the packages and versions which I have used.
Packages :
"#react-native-firebase/messaging": "^7.5.0",
"#react-native-community/push-notification-ios": "^1.10.1",
"react-native-push-notification": "^8.1.1",
Code :
componentWillUnmount() {
if (Platform.OS === "ios" && this.messageListener1 && this.messageListener2) {
this.messageListener1();
this.messageListener2();
}
}
async requestUserPermission() {
const { navigate } = { ...this.props }
const authStatus = await messaging().requestPermission();
const enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (enabled) {
this.messageListener1 = messaging().onMessage(async remoteMessage => {
PushNotification.localNotification({
/* Android Only Properties */
id: remoteMessage.data.id, // (optional) Valid unique 32 bit integer specified as string. default: Autogenerated Unique ID
autoCancel: true, // (optional) default: true
vibrate: true, // (optional) default: true
vibration: 300, // vibration length in milliseconds, ignored if vibrate=false, default: 1000
group: remoteMessage.data,
userInfo: {
data: remoteMessage.data,
},
title: remoteMessage.notification.title,
message: remoteMessage.notification.body,
});
});
messaging()
.getInitialNotification()
.then(async remoteMessage => {
if (remoteMessage) {
if (await GlobalStorage.handleInitialNotification(remoteMessage)) {
navigate(remoteMessage);
PushNotification.cancelLocalNotifications({ id: remoteMessage.data.id });
}
}
});
this.messageListener2 = messaging().onNotificationOpenedApp(remoteMessage => {
GlobalStorage.handleInitialNotification(remoteMessage)
navigate(remoteMessage);
PushNotification.cancelLocalNotifications({ id: remoteMessage.data.id });
});
Note : There is no issues in getting the FCM token.

I faced the same problem.
I tried all the packages and the result is the same in all of them.
Here's the situation:
*Everything is fine with the Notification integration.
*When you install the application for the first time, there is no notification.
*When you open the application for the first time and kill it in the background and open it again and throw it into the background, everything works fine. You start receiving notifications.
It's really interesting. Has anyone experienced this and know what exactly is causing the issue?

The issue is only facing mainly on android device and here is solution I used to solve the issue
const { navigate,
} = { ...this.props }
PushNotification.configure({
onRegister: function (token) {
},
onNotification: function (notification) {
const clicked = notification.userInteraction ? notification.userInteraction : "";
notification.finish(PushNotificationIOS.FetchResult.NoData);
if (clicked) {
navigate(notification);s
PushNotification.cancelLocalNotifications({ id: notification.id });
} else if (!notification.foreground) {
navigate(notification);
PushNotification.cancelLocalNotifications({ id: notification.id });
}
else {
PushNotification.localNotification({
/* Android Only Properties */
channelId: "app_name", // (required)
channelName: "app_name", // (required)
id: notification.id, // (optional) Valid unique 32 bit integer specified as string. default: Autogenerated Unique ID
// autoCancel: true, // (optional) default: true
vibrate: true, // (optional) default: true
vibration: 300, // vibration length in milliseconds, ignored if vibrate=false, default: 1000
group: notification.data, // (optional) add group to message
priority: "high", // (optional) set notification priority, default: high
visibility: "private", // (optional) set notification visibility, default: private
importance: "high",
userInfo: {
id: notification.id,
name: "name",
title: notification.title,
message: notification.message,
data: notification.data
},
title: notification.title,
message: notification.message,
});
}
notification.finish(PushNotificationIOS.FetchResult.NoData);
},
senderID: "",
permissions: {
alert: true,
badge: true,
sound: true
},
popInitialNotification: true,
requestPermissions: true
});

Related

Invoke an app from the lock screen in react native

I added webRTC feature to make in app call using firebase and react native push notification. The problem is that the company wants the app to start and show the incoming call screen if the app is locked.
Is there any way to make this happen? And,Which resources I can use?
I am handling the background state using the setBackground handler provided from react-native-firebase, and the call is initialized by a push notification, which contains only data payload.
The handler is:
messaging().setBackgroundMessageHandler(async notification => {
let id = 1893950948;
console.log('#INITIAL ROUTE: ', notification);
if (notification.data.channelName === __config.BRAND_PSN_CHANNELS.RTC_CALL) {
if (notification.data.title === 'Incoming call') {
InCallManager.startRingtone('_BUNDLE_');
const {offer, name, sendingAgent} = notification.data;
PushNotification.localNotification({
id,
title: 'Incoming call',
message: `${name} is calling you`,
data: {...notification.data},
channelId: '2',
messageId: notification.messageId,
importance: 'max',
smallIcon: 'app_icon',
largeIcon: 'app_icon',
ongoing: true,
tag: 'call-user',
visibility: 'public',
actions: ['Answer', 'Decline'],
invokeApp: false,
priority: 'high',
});
// send the ringing event
axios.post(
`${API_BASE_URL}/${WEBRTC_URLS.ringingURI}/?token=${WEBRTC_URLS.webhookToken}`,
{
to: sendingAgent,
},
);
// set the data to the local storage
const storedCall = {
offer,
name,
sendingAgent,
};
// PushNotification.getDeliveredNotifications(notifications =>
// console.log(notifications),
// );
// set the data to the local storage
await AsyncStorage.setItem('storedCall', JSON.stringify(storedCall));
}
}
if (notification.data.title === 'Missed Call') {
PushNotification.removeAllDeliveredNotifications();
InCallManager.stopRingtone('_BUNDLE_');
await AsyncStorage.removeItem('storedCall');
await AsyncStorage.removeItem('notification');
}
return Promise.resolve();
});

FCM Push notifications arrive twice (Nuxt with firebase)

So I searched here about this problem and I saw many experienced it but still didn't find solution.
FCM Push notifications arrive twice if the browser is in background
Ty for your help.
My nuxt config firebase serviced:
services: {
auth: true, // Just as example. Can be any other service.,
messaging: {
createServiceWorker: true,
fcmPublicVapidKey: "###", // OPTIONAL : Sets vapid key for FCM after initialization
inject: fs.readFileSync("./serviceWorker.js")
}
}
my service worker:
messaging.setBackgroundMessageHandler(function(payload) {
console.log("[firebase-messaging-sw.js] Received background message ");
self.registration.hideNotification();
return null;
});
self.addEventListener("push", function(e) {
data = e.data.json();
const options = {
tag: "notification-1",
body: data.notification.body,
vibrate: [100, 50, 100],
data: {
dateOfArrival: Date.now(),
primaryKey: "1"
}
};
self.registration.showNotification(data.notification.title, options);
});
self.addEventListener(
"notificationclick",
function(event) {
console.log("test", event);
event.notification.close();
const url = "home";
event.waitUntil(
self.clients.matchAll({ type: "window" }).then(windowClients => {
// Check if there is already a window/tab open with the target URL
for (let i = 0; i < windowClients.length; i++) {
const client = windowClients[i];
// If so, just focus it.
if (client.url === url && "focus" in client) {
return client.focus();
}
}
if (self.clients.openWindow) {
console.log("open window");
}
})
);
},
false
);
Add
self.registration.hideNotification();
On top of line
self.registration.showNotification(
This allows your app to hide the default notification in which case you will only have one notification.

React Native screen navigation on API calls

So, I've been reacting for quite some time. I am facing a problem handling API and making it interact with small widgets in mobile app.
What I am trying to do ?
I am on a Screen(A) and on click of a button I go to Screen(B). Simple. Now in Screen(B) I fill up a form and submit it. While the form is submitting I have to show a Loading component. Finally the API responds if the request was "Success" or a "Failure".
If it was Success - Navigate back to Screen(A) and show a toast message(Boom..boom..) on screen(A).
If it Failed - Be in Screen(B) and show a toast message(yes, with a failure message).
My Approach
Let's start with reducers. I have following reducer state -
{
forSubmitRequest: false, // false - API has been trigerred to submit form
formSubmitRequestOver: true, // true - request is over
formSubmitRequestStatus: true // true - success
}
Now my actions are as follows -
case FORM_SUBMIT_REQUEST:
return {
...state,
formSubmitRequest: true,
formSubmitRequestOver: false,
formSubmitRequestStatus: false,
};
case FORM_SUBMIT_REQUEST_SUCCESS:
return {
...state,
formSubmitRequestOver: true,
formSubmitRequestStatus: true
};
case FORM_SUBMIT_REQUEST_FAILED:
return {
...state,
formSubmitRequestOver: true,
formSubmitRequestStatus: false,
};
case FORM_SUBMIT_REQUEST_DOWN:
return {
...state,
formSubmitRequest: false,
formSubmitRequestOver: true
};
Here's my coding logic in Screen(B)
const [formSubmitReq, setFormSubmitReq] = useState(false);
const [showErrorFormSubmitToast, setShowErrorFormSubmitToast] = useState(false);
useEffect(() => {
if (showErrorFormSubmitToast) {
Toast.show({
type: 'error',
text1: 'Error',
text2: 'Could not submit.',
topOffset: ResponsiveSize(0),
onHide: () => {
setShowErrorFormSubmitToast(false);
},
});
}
}, [showErrorFormSubmitToast]);
if (
formSubmitReq &&
props.teacher.formSubmitRequest &&
!props.teacher.formSubmitRequestOver
) {
return <Loading msg="Submitting form..." />;
}
if (
formSubmitReq &&
props.teacher.formSubmitRequest &&
props.teacher.formSubmitRequestOver
) {
if (props.teacher.formSubmitRequestStatus) {
props.navigation.goBack();
return <></>;
} else {
setFormSubmitReq(false);
setShowErrorFormSubmitToast(true);
props.handleCreateFormSubmitDown();
}
}
Logic in Screen(A)
const [showSuccessFormSubmitToast, setShowSuccessFormSubmitToast] =
useState(false);
useEffect(() => {
if (showSuccessFormSubmitToast) {
Toast.show({
type: 'success',
text1: 'Success',
text2: 'Successfully submitted.',
onHide: () => {
setShowSuccessFormSubmitToast(false);
},
});
}
}, [showSuccessFormSubmitToast]);
if (
!showSuccessFormSubmitToast &&
props.teacher.formSubmitRequest &&
props.teacher.formSubmitRequestOver &&
props.teacher.formSubmitRequestStatus
) {
console.log('Prep show toast');
setShowSuccessFormSubmitToast(true);
props.handleCreateFormSubmitDown();
}
Lastly this function - handleCreateFormSubmitDown just fires action - FORM_SUBMIT_REQUEST_DOWN
Gist of the code ->
I am trying to show Toast on Screen(A) only when request was success and request was actually fired. Not it may happen that request was success and I came back to Screen(A) now I simply navigate to Screen(B) so I have to make sure toast isn't visible as request wasn't fired. Now when reducer state updates then Screen(A) also gets rendered causing some nast things.
Can anyone point out what strategies they follow in such scenarios and where I could improve here?
One way to do this is to utilize route params from react-navigation
In screen B
...
useEffect(() => {
// Navigate to screen A with a route param
navigation.navigate(A, { displaySuccessToast: true });
}, [showSuccessFormSubmitToast])
In Screen A
...
useEffect(() => {
if (route.params.displaySuccessToast) {
Toast.show({
type: 'success',
text1: 'Success',
text2: 'Successfully submitted.',
onHide: () => {
// Hide Toast Action
},
});
}
}, [route.params]);
Other wise you can use a global state management solution like redux
Its the same logic. You need to update a flag in the global state. Then navigate to the earlier screen and check if this flag is set and render the toast message.

how to call a function on press of a action button in push notification react native

i am able to generate notification along with action buttons but how to call a onpress event based on the button pressed by user? here yes or no
thanks in advance
import PushNotification from 'react-native-push-notification';
function configure() {
PushNotification.configure({
// (required) Called when a remote is received or opened, or local notification is opened
onNotification: function (notification) {
console.log('NOTIFICATION:', notification);
// process the notification
// (required) Called when a remote is received or opened, or local notification is opened
notification.finish();
},
// IOS ONLY (optional): default: all - Permissions to register.
permissions: {
alert: true,
badge: true,
sound: true,
},
// Should the initial notification be popped automatically
// default: true
popInitialNotification: true,
/**
* (optional) default: true
* - Specified if permissions (ios) and token (android and ios) will requested or not,
* - if not, you must call PushNotificationsHandler.requestPermissions() later
* - if you are not using remote notification or do not have Firebase installed, use this:
* requestPermissions: Platform.OS === 'ios'
*/
requestPermissions: true,
requestPermissions: Platform.OS === 'ios',
'content-available': 1,
});
}
function givenotification(title, message) {
PushNotification.localNotification({
channelId: 'channel',
message: message, // (required)
title: title,
message: message, // (required)
actions: ["Yes", "No"]
});
}
I have never used push notification directly,
for my notification i have use React Native Notifee that have this "displayNotification" inside when you try to log Notifee ..
I suggest you to try log "PushNotification" to find a function to display your notification.
You can setup the action as below code:
export const App = () => {
const [permissions, setPermissions] = useState({});
/**
* By calling this function, a notification with category `userAction` will have action buttons
*/
const setNotificationCategories = () => {
PushNotificationIOS.setNotificationCategories([
{
id: 'userAction',
actions: [
{id: 'open', title: 'Open', options: {foreground: true}},
{
id: 'ignore',
title: 'Desruptive',
options: {foreground: true, destructive: true},
},
{
id: 'text',
title: 'Text Input',
options: {foreground: true},
textInput: {buttonTitle: 'Send'},
},
],
},
]);
};
useEffect(() => {
PushNotificationIOS.addEventListener('notification', onRemoteNotification);
});
const onRemoteNotification = (notification) => {
const actionIdentifier = notification.getActionIdentifier();
if (actionIdentifier === 'open') {
// Perform action based on open action
}
if (actionIdentifier === 'text') {
// Text that of user input.
const userText = notification.getUserText();
// Perform action based on textinput action
}
};
};
For more, you can reach out to the official documentation of the library.
https://github.com/zo0r/react-native-push-notification

react-native-push-notification - local notifications not working on Android

can someone please let me know where Im going wrong.
From what I can see on instructions....theres no amendments required to Android specific files if you are only using local notifications and also using autolinking....except for adding googlePlayServicesVersion = "<Your play services version>" // default: "+" to android/build.gradle....and <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> plus <uses-permission android:name="android.permission.VIBRATE" /> to AndroidManifest.xml
Below is my main source code
PushNotification.configure({
// (optional) Called when Token is generated (iOS and Android)
onRegister: function(token) {
console.log('onRegister token:', token);
},
// (required) Called when a remote is received or opened, or local notification is opened
onNotification: function(notification) {
console.log('onNotification:', notification);
notification.finish(PushNotificationIOS.FetchResult.NoData);
},
// Should the initial notification be popped automatically
popInitialNotification: true,
requestPermissions: true,
});
userNowInactive = () => {
this.showNotification();
}
showNotification = () => {
PushNotification.localNotification({
//ios and android properties
title: 'Face2Face: Beacon Timer Expired',
message: 'Perhaps set your beacon timer for another hour?',
playSound: true,
soundName: 'sound.mp3',
//android only properties
channelId: 'your-channel-id',
autoCancel: true,
// largeIcon: 'ic_launcher',
// smallIcon: 'ic_launcher',
bigText: 'Face2Face: Beacon Timer Expired',
subText: 'Perhaps set your beacon timer for another hour?',
vibrate: true,
vibration: 300,
priority: 'high',
//ios only properties...is there any?
});
};
Did you create a channel?
It seems you need to create one to get it to work.
https://github.com/zo0r/react-native-push-notification#channel-management-android
To use channels, create them at startup and pass the matching channelId through to PushNotification.localNotification or PushNotification.localNotificationSchedule.
PushNotification.createChannel(
{
channelId: "channel-id", // (required)
channelName: "My channel", // (required)
channelDescription: "A channel to categorise your notifications", // (optional) default: undefined.
playSound: false, // (optional) default: true
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}'`) // (optional) callback returns whether the channel was created, false means it already existed.
);