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.
Related
Maybe someone ever solve the problem with stable connection to server when application is in background? I need to transfer audio data from server to client app.
I know about all hacks for iOS how to keep alive application, but I need legal methods to solve this problem. Maybe you have any idea?
I found that I can send VoIP push to device that will wakeup my app and then establish tcp connect to my server but this socket will be keep alive about 30 seconds (as I see in log, every 3 seconds fires timer in iOS app that send data to server) this is not enough for me.
Maybe this project https://github.com/SmallSharpToolsOpenSource/Speakerbox will be helpful for someone.
And this video https://www.youtube.com/watch?v=lXJ1LDjL4Os
And official answer from Apple tech support:
PushKit is how voip apps can
reliable receive silent notifications, while CallKit is basically a UI
framework voip apps can use to notify the user about calls. Note that there
is NOT any direct connection within the APIs- for example, a voip app can
generate a local notification (instead of using CallKit) or simply do nothing
and “ignore” the notification entirely. Similarly, a voip app could “fake” a
call at anytime by simply telling CallKit that there was an incoming call (our
sample code for CallKit did exactly this).
Anything your app could previously have done when
it received voip socket traffic, it could also do when it received a PushKit
notification.
Standard voip apps
actually operate in two COMPETELY unrelated “modes”:
1) While waiting for an incoming call, the app is suspended until “something”
(PushKit OR a voip socket) wakes the app to tell it about the call.
2) Once a call has started, the app has an active audio session and is relying
an the standard “background audio” behavior of iOS, just like a wide variety
of other audio apps (for example, any streaming music app).
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.
I am considering using EventSource (server-sent events) to send notifications to my iOS App users, instead of APNS. This is great when app is active, but is it possible to ensure these users receive my messages when my app is not currently running on their device? Or is the only way to do this APNS?
If you need your events to arrive in real-time (like a messaging system), then APNS is probably your best bet. APNS is the only way to send realtime messages from a server to your app. However, it is wise to know that there are downsides to push notifications.
If you don't care about real-time events (not a messaging system), or if it's okay if you get the events a bit delayed, you can use background fetching to periodically poll your server for new events.
Objc.io has a great article discussing some of these: http://www.objc.io/issue-5/multitasking.html
I want to create an iOS chatting app using APNS. If I have 10,000 active and they are continuing chatting, will apple block my developer account ? Is there any limitation regarding this?
I would discourage you from using APNS as a backbone of an "chatting app".
If you need fast chatting functionality you should write your own TCP-socket based server.
If every-few-second syncing is o.k. you can get away with a HTTP-based server backend (but all the pull-syncing can be hard on network traffic - so TCP-socket is still better choice).
You could however use APNS for fallback - when your app on certain device is not responding (i.e. is not connected to server) you can send an initial message trough APNS (to wake up your app & to notify the user there is a message waiting for him).
As soon as the user opens your app you should switch back to your TCP-socket or HTTP request based server communication.
As for your question: no, Apple would most probably (one can never know for sure) not reject your app just because of using APNS for chatting. But note (as the others said allready): messages between two users will get "lost" if they would interact too frequently - see the link Roman Barzyczak gave you.
"If you are sending multiple notifications to the same device or computer within a short period of time, the push service will send only the last one."
more information: http://developer.apple.com/library/ios/#technotes/tn2265/_index.html
but Apple wont block your developer account :)
You can use them for messaging but you are going to quickly find out that there is no guarantee they will arrive. This is known as the black hole of push notifications. ;-)
I like this answer here.
First try to use an APNS only solution.
Make your push notifications stateless (they only serve as "Hey you have some new stuff in the server").
So when the client gets a push notification it asks the server for new data (messages or other stuff).
Use OneSignal to simplify the code that sends push notifications (from the back-end). If a user in your app gets a message after 10 seconds he dose not care if you used TCP,socket.io or xmpp...
Even Whatsapp's messages can take couple of seconds to arrive.
A chat app is not a realtime game. A delay of couple of seconds will be acceptable by end users.
This is more of an is-it-possible question.
I am building a pubsub application for the iphone using XMPPFramework and Openfire.
When the user has the pubsub app in the background, the app sends "keep alive" packets every 10 minutes or so to keep a persistent connection. Any messages delivered will show up as local notifications.
But what about if the user has killed the app or it's been a week since they've used it and the app isn't in the background? How would they know that they have a message waiting for them?
Is it possible to combine Openfire's pubsub service with Apple's push notifications? Am I on the right track? Thanks!
The limitations you're envisioning were constructed purposely to only allow certain types of applications to run in the background with long-lived connections indefinitely (namely, VOIP applications). You could experiment with setting the UIBackgroundModes key to 'voip' (see: Apple's Documentation).
Non-VOIP applications don't have this luxury (presumably as a safeguard against battery life or network utilization issues) and won't be permitted in the appstore if they have the VOIP UIBackgroundModes value set.
Consideration of Apple's Push Notification Service is definitely the right approach, IMHO.