Flutter: FirebaseMessaging.onBackgroundMessage never execute in iOS - firebase-cloud-messaging

I want to execute some code in onBackgroundMessage when app is in background or killed.
I am getting push notifications as aspected but onBackgroundMessage function is never executed in iOS. It works perfectly in Android devices.
Here is my code:
Future<void> _backgroundHandler(RemoteMessage message) async{
await Firebase.initializeApp();
dynamic isCall = message.data['status'];
print(isCall);
if(isCall == 'call'){
//.....
}else{
NotificationHandler.flutterLocalNotificationPlugin.cancelAll();
}
FirebaseNotifications.showNotification(message.data);
}
Future<void> main() async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(_backgroundHandler);
runApp(const MyApp());
}
I also add APNs and add capabilities Background Modes and Push Notifications. Tested on real device.
What should have to do to execute FirebaseMessaging.onBackgroundMessage function in iOS?

You need to set content-available to true in your notification payload from backend.
This value let OS know that some data is available with the notification and allow that callback to be executed even when your app is in terminated state.

Client
for ios:
foreground - onMessage;
background - onBackgroundMessage;
terminated - onBackgroundMessage.
BUT
if app was terminated, first notification will be handled with getInitialMessage, because first notification wakes up the app
Server
exapmle of config:
messaging.Message(
token=recipient['fcm_token'], data={**message_data, 'user_id': str(recipient['user_id'])},
notification=messaging.Notification(
title=message_data['title'], body=message_data['body'], image=message_data['image'],
),
fcm_options=messaging.FCMOptions(analytics_label=message_data.get('analytics_label', None)),
apns=messaging.APNSConfig(
payload=messaging.APNSPayload(
aps=messaging.Aps(
content_available=True,
),
),
headers={'apns-priority': '5'},
),
)
need content_available=True and maybe headers={'apns-priority': '5'}

Related

Duplicate fcm push notification in react native android backgroundhandler

I developed react native application with rnfirebase and notifee for sending the push notification. foreground is working properly, message is displayed only once. but the background notification is displaying twice like one is from messaging().setBackgroundMessageHandler and another one is android's default push notification. First message is from default push notification and next one is from firebase messaging. So how do I remove android's default push notification. I'm also checked that first default notification is not using the firebase messaging and notifee. It's comes from outside of react native like android's native push notification
The notifications that you are seeing are most likely one from firebase and another from Notifee.
In my project I was handling the notifications that were coming from firebase via firebase.messaging().onMessage and inside this listener I was showing a local notification using Notifee so that the notification shows in the foreground.
async showNotificationInForeground(message: FirebaseMessagingTypes.RemoteMessage) {
const { messageId, notification, data } = message
const channelId = await Notifee.createChannel({
id: messageId,
name: 'Pressable Channel',
importance: AndroidImportance.HIGH,
})
await Notifee.displayNotification({
title: notification?.title || '',
body: notification?.body || '',
data,
android: {
channelId,
importance: AndroidImportance.HIGH,
pressAction: {
id: messageId,
},
smallIcon: 'ic_stat_name',
localOnly: true,
},
})
}
However what was happening was that I was calling this showNotificationInForeground method to show the local Notifee notification on both firebase's background and messaging listeners ie: firebase.messaging().onMessage and firebase.messaging().setBackgroundMessageHandler
So what I ended up doing was only calling the showNotificationInForeground method in onMessage listener and not in setBackgroundMessageHandler, which resulted in showing the local notification in the foreground, and the firebase notification in the background.
If this is not the case for you, you are most likely registering an extra notification receiver inside your AndroidManifest.xml file which is causing the duplication
I had the same problem, where there were two notifications a) 1 from notifee (which I wanted to keep) b) from FCM (which I didnt want).
Sending a data only message from my custom server solved the issue. Below is a snippet of the serverside for sending data only message :
const admin = require("firebase-admin");
// Do other stuff like create an express server to listen and trigger sending message
// Note dont forget to to initialize the app
await admin.messaging().sendToDevice(
tokens, // ['token_1', 'token_2', ...]
{
data: {
owner: "Me",
user: "My Friend",
},
},
{
// Required for background/quit data-only messages on iOS
contentAvailable: true,
// Required for background/quit data-only messages on Android
priority: "high",
}
);
You can use other methods as well, just make sure that FCM doesnt include notification and is data only.

React-native FCM: Can't access notification data when the app is in background or killed

Im am trying to make work react-native-fcm, with firebase cloud messaging and a react-native app.
I am focusing mainly in Android
react-native#0.48.0
react-native-fcm#10.0.2
OS: Android - Emulator - 7.0.2
When my app is in foreground, its working perfectly, I receive the data in this function
FCM.on(FCMEvent.Notification, async (notif) => {
And I can handle everything
But when the app is in background, the notification is received, but when I tap the banner, the app goes foreground, the same function is triggered, but the notif object is different, and don't contains my data.
When the app is killed, also the notification is received, but when I tap the banner, the app starts, the
FCM.getInitialNotification()
is triggered, and my notif object doen't also contain the data, the same behaviour than in background
I am testing the format of the messages using node-gcm library, of firebase web interface, but nothing works.
This is a sample of my message, but I have tryed tons of combinations:
let message = new gcm.Message({
priority: 'high',
content_available: true,
timeToLive: 3,
data: {
key1: 'message1',
key2: 'message2'
},
notification: {
title: "Hello, World",
icon: "ic_launcher",
body: "This is a notification that will be displayed if your app is in the background."
},
custom_notification: {
key1: 'message1',
key2: 'message2'
}
});
How should I proceed to send and receive data in those cases? Because is driving me crazy.
If you need more data, ask for it :)
Thanks!!
in my case, i was missing the notification's data setup when building the notification on foreground notification event firebase.notifications().onNotification
new firebase.notifications.Notification()
.setNotificationId(fcmNotification.data.notificacionId)
.setTitle(fcmNotification.title)
.setBody(fcmNotification.body)
.setData(fcmNotification.data) // <- this little bastard
so, when tapping the notification data was undefined on firebase.notifications().onNotificationOpened even when the json that comes in firebase.notifications().onNotification had data field filled

Clear Previous Expo Push Notifications

I have my app in Expo pushing a notification when somebody sends a message, but if that person sends multiple messages a second notification is pushed.
Is there anything I can do to clear the previous notification, or simply update the notification instead of adding a second notification to the list?
Basically I need to force an override or dismiss previous notifications.
The approach I was hoping to use was to add a listener which cleared notifications before appending, but it seems that this only works when the app is in the foreground.
Is there a recommended approach to this currently?
You can clear any or all previous notifications in expo-notifications. Your question is not clear but I am guessing you want to clear all previous notification if new notification is received. You have to spot the best place when to clear notifications on your code. But here are some tips (use the following code in the useEffect hook) -
// This listener is fired whenever a user taps on or interacts with a notification (works when app is foregrounded, backgrounded, or killed)
responseListener.current =
Notifications.addNotificationResponseReceivedListener((response) => {
// DISMISS ALL NOTIFICATION AFTER INTERACTION
Notifications.dismissAllNotificationsAsync();
});
If you want to dismiss specific notification in that case, use dismissNotificationAsync(identifier: string): Promise method.
Just in case, if you want to dismiss all notifications when receiving a new one while the app is foregrounded (use the following code in the useEffect hook).
// This listener is fired whenever a notification is received while the app is foregrounded
notificationListener.current =
Notifications.addNotificationReceivedListener((notification) => {
// setNotification(notification);
// DISMISS ALL NOTIFICATION UPON RECEIVING NOTIFICATION WHILE IN FOREGROUND
Notifications.dismissAllNotificationsAsync();
});
You can use Notifications.dismissAllNotificationsAsync() method or dismissNotificationAsync(identifier: string): Promise method anywhere you like but you need to spot where to best use them.
_handleNotification = (notification) => {
this.setState({notification: notification});
console.log('get notification', this.state.notification);
let localnotificationId = this.state.notification.notificationId;
setTimeout(function () {
Notifications.dismissNotificationAsync(localnotificationId);
}, 10000)
};
This is how I do in NodeJS

React Native socket.io disconnects when app is on background mode

I am making a react native app for android devices using socket.io-client. Everything works fine but when the app goes on background mode (e.g. an other app launched) the socket connections disconnects from the server (app emits 'disconnect' event).
What is the best way to deal with it?
In the disconnect event of the socket I reconnect it, if user is not logging out.
socketInstance.on('disconnect', (err) => {
console.log('SOCKET DISCONNECT', err);
var deauthorize = store.getState().auth.account.deauthorize;
if (!deauthorize) {
store.dispatch(NotificationActions.addNotificationAction('SOCKET DISCONNECT'));
store.dispatch(AppActions.shouldConnectAction());
store.dispatch(CommunicationActions.connectSocketAction());
}
});

WL.Client.Push.isSubscribed() returns false if app reloaded

I have a simple Worklight V6 app using Push on Android. When the app starts up, it does a form based login against the SampleAppRealm. Then it subscribes if necessary:
function checkSubscribed() {
var subscribed = WL.Client.Push.isSubscribed("myPush");
alert("Is subscribed: " + subscribed);
return subscribed;
}
WL.Client.Push.onReadyToSubscribe = function() {
WL.Client.Push.registerEventSourceCallback("myPush", "PushAdapter",
"MyEventSource", function(props, payload) {
alert("Received message: " + props.alert);
});
if (!checkSubscribed()) {
WL.Client.Push.subscribe("myPush", {
onSuccess : function() {
alert("subscription succeeded!");
},
onFailure : function() {
alert("subscription failed!");
}
});
}
};
This all works swell. The app starts up, it logs in, onReadyToSubscribe() fires, it registers the callback, checks the subscription (which is false), and subscribes (which succeeds)
I can see the client subscription in the Worklight console, and if I call the adapter, I get the notification in the app.
If I hit the home button to do something else on the phone, and then return to the app, it still knows that it is subscribed. If I push a message when the app is in the background, I see it in the Android notification area, and see it in the app when I return to it. All good.
The problem is when I am running the app, it is subscribed, and I hit the Android back button. The app closes, but the Admin console still shows a subscribed client, and in fact if I push a message with the app closed, it shows up in the Android notification area. (so far so good)
But when I start the app, it goes through the authentication steps, onReadyToSubscribe() fires, checkSubscribed() gets called and WLClient.Push.isSubscribed() returns false.
If I restart the phone with the app subscribed, when the app restarts, WLClient.Push.isSubscribed() returns false.
How do I get the correct subscription state when an app restarts?
Answering my own question.
It turns out that the problem was that My app was explicitly calling WL.Client.login("SampleAppRealm") when it started. The application descriptor environment setting of a security test on the environment was not configured.
When I add the security test to the application descriptor, isSubscribed() returns the correct answer after an app is restarted. The funny bit is that everything else having to do with Push worked fine with authentication simply triggered by WL.Client.login()
I can't find any documentation around this requirement for the setting in the application descriptor, so it is hard to make out whether this is user error. At the least, the docs could be punched up in this area.