Swift Firebase Cloud Messaging - Sending upstream messages in the background - ios

I wasn't able to find anything on this topic in the documentation, so I thought I'd as it here.
The FCM documentation states that:
When your app goes into the background, disconnect from FCM.
But no where does it say why.
What I want to do is send an FCM upstream message from the device when a user interacts with a push notification (could be local or remote).
So I have two questions:
Why does Firebase recommend we disconnect from FCM when the app is sent to the background?
Can I send an upstream message while the app is killed, suspended, or in the background?
This type of feature, where the user interacts with a notification, and an immediate server response, is going to be a major part of my app, and I need to know if this is possible with Firebase, otherwise I need to start looking for another solution.
Thanks!

Since I wasn't able to find an answer online, I decided to implement my use case and observe the behaviour. I found a few things:
You can't rely on background execution in iOS, such as keeping an FCM connection. The system can and will kill your app in low memory states.
Trying to connect to FCM in the background will not work. Any messages sent in the background will be queued for when the app is next opened.
Even if your background code is guaranteed to run, such as during a notification action, FCM cannot connect.
Given my findings, the answers to my questions are:
Because you can't rely on background execution on iOS (see first bullet above).
No, the messages are queued for when the app is next opened and a valid FCM connection is made.

Related

Can you listen to Firestore updates when iOS app is in the background?

I'm very new to Firestore and trying to understand how the real-time updates work. I'm using something like this now to get the updates from Firestore:
db
.collection(Collections.session)
.whereField("participants", arrayContains:userID)
.addSnapshotListener { querySnapshot, error in
I noticed that the listener block is not getting fired when the app is in the background, but only when it's brought back to foreground.
Is there a way to get the update when the app is running in the background too? Maybe somehow send a push notification or something?
Any kind of help is highly appreciated.
Is there a way to get the update when the app is running in the background too?
Since backgrounded apps are eventually killed by the OS, you don't have a way to run a listener reliably when the app is not actively being used by the user.
You are correct in that the only way to (reliably) notify your app of some change in your backend is to send a push notification.
A very common approach is to use Cloud Functions to write a Firestore trigger that gets invoked when a document of interest is created, updated, or deleted. You can use this to write backend code that uses Firebase Cloud Messaging and the Firebase Admin SDK to send a notification to your app with a payload that tells it to respond to that change.
Push notification is not a reliable way to do this unfortunately. that backgrounded apps may be killed by the OS, if needed, but not always. The source of termination can be the OS or the user. If the user terminates your app, there is no way to receive a push notification.

How does WhatsApp bypass APNS restriction to display multiple push messages received while device was offline?

While working with APNS, I was able to have push notifications work flawlessly while device is online.
For any APNS push I send while device is offline, only the last one is received once the device is back online. This seems to be coherent with Apple's Store-and-Forward design.
However - I did notice, that when sending WhatsApp messages to an offline device, once this device goes online it receives all push notifications (one for each message). This is not something based on collapse identifier, but rather independent push notification for each message.
So how did WhatsApp do it?
Tried using Notification Extension and attempt to post multiple local notifications, but this also fails as extensions are not allowed to do that.
Instead of a normal push notification, use a Background Notification, which will not show anything visible, but wake up your app in background. Use this event, to make api call, get relevant data and generate multiple local notifications.
Note the following from the documentation when you implement application(_:didReceiveRemoteNotification:fetchCompletionHandler:) :
system calls this method when your app is running in the foreground or background
system does not automatically launch your app if the user has force-quit it
you must call the block in the handler parameter (fetchCompletionHandler) or your app will be terminated. Your app
has up to 30 seconds of wall-clock time to process the notification
and call the specified completion handler block
Apps that use significant amounts of power when processing remote notifications may not always be woken up early to process future
notifications
Please read relevant documentation completely before making ANY assumptions about how you think this should work.

Server sends data while iOS app is terminated

I have an application which has communication with a remote server. The server should push data into it using remote notification silently, and I need to get and store these data into a CoreData database. The user won't be aware of the whole process.
I can successfully get notified when the app receives a remote notification, while it is either in the foreground or background mode. However, I need to get data while the app is terminated as well.
I searched for the possible solutions. For example, this SO question was good if I don't tend to use silent notification. I also saw the PushKit capability, but I am not sure about the Apple Review result.
What is the possible solution?
If I want to use VoIP and PushKit to get notified when the app is terminated, would Apple reject my application?
If you’re not creating a VoIP app and you want your app to be in the App Store then the correct answer is: it is not possible. The only thing that can be done is adjusting your requirements in some way.
For instance you can send some notifications that will be visible for user in the Notification Center and wait until the user taps the notification or starts the app the usual way. Then the app will be able to do all the operations you need.
The delivery of push notifications is not guaranteed, so you should not rely on them to synchronise data.
For example, if multiple push notifications are sent while the device is offline, only the last notification is delivered when the device comes back online; the earlier notifications are lost.
When your app launches one of the first things it should do is check with your server for new data.

Firebase: Listen ChildEventListener even if app exits

I'm working on an iOS application, and want to achieve behavior like push notifications using firebase real time DB.
In case my app is listening to some firebase node and i'll send local push notification to the user in case that node is updated.
The issue is, if the app is not running i.e. user has killed it, will my app continue listening to that particular node?
I guess, in Android we've support like this, as explained in this link (Link).
Can we achieve the same behavior in iOS. If no, what can be the alternative?
Thanks
Update:
1- There's nothing like triggering push notifications locally in iOS app. I wanted to achieve remote notification's behavior and that can't be done.
2- As far as listening to some event is concerned, it can't be done when app is not in foreground or background.
You can’t do anything if an iOS app is killed/not present in memory.
However, you can do some tasks if app is in background, and is present in memory.
You can use background fetch request in this case.
In Android, there are Services which run even when the app is killed. But on iOS, there is no such thing like this.
You can add Firebase observers in your root view controller, and implement background fetch request to continue observing data when app is in background.
When you app is killed, the listeners are disconnected.
The typical way to send messages to your app in this state is by using a push notification, which in Firebase maps to Firebase Cloud Messaging.
This is why you'll often see the Firebase Database and Firebase Cloud Messaging (FCM) used hand-in-hand: the database is used for messaging while the user has the app open, and FCM is used to send messages when the app is not active.

Websockets message delivery when mobile app is in the background

I am trying to implement an iOS chat application using Pusher or PubNub (websockets).
Question: How does message delivery work when the iOS app is in the background?
I understand that Websockets implementations provide real-time messaging and don't cache the messages. Is the message lost because the socket connection is broken when the app is in the background?
If yes, how do I recover the lost messages? One idea is to implement a state refresh protocol every time the app comes to foreground.
PubNub Missed Message Recovery Options
You mentioned PubNub (the company I work for) and as #FrankG mentioned, unless you have permission from Apple to run your app in background (staying connected to internet, and therefore, PubNub), you will not receive any message in realtime.
You can use PubNub's Mobile Push Gateway and receive APNS push messages while you app is in background (but idle/not running) or completely not running (kill state).
When the app is activated again, PubNub can be configured to automatically retrieve missed messages from the channel(s) it was subscribed to, but this is good for short periods of disconnection.
For longer periods being offline, you can enable Storage & Playback and use the historyForChannel API to fetch all the missed messages of all channels you require.
Answer: It doesn't.
If the iOS app is in the background, you are out of luck. There is no official (and Apple sanctioned) way of keeping a connection open when the app is in the background. There are hacks like playing a silent audio track to keep it in the foreground, but Apple doesn't approve of such hacks. You'll need to use APNS to send an offline message to bring the app to the foreground so it can reconnect.
And you are 100% correct that the WS standard does not address caching. That has to be performed by another subsystem in your architecture.
The Kaazing Gateway (disclosure: the company I work for) has a feature in our messaging Gateway that caches the last value sent. When the client reconnects (our client libs auto-reconnect), they will see that value.

Resources