How do iOS chat apps keep running in the background? - ios

I have always coded for Android, and now I'm looking to expand my knowledge to iOS development; so I'm really new at this, please be patient.
I understand that only a small group of apps are allowed to run indefinitely in the background. Those are VoIP, Music players and location tracking apps.
I want to write a chat app using the XMPP framework. Everything is fine until the user puts the app in the background, in which case, the app will stay connected for about ten minutes to then be killed by the system and therefore the user won't be able to receive new messages.
I am aware of hacks to keep the app alive. Hacks such as defining it as a music playing app in the info.plist file and then just play some empty sound indefinitely. But I'm also aware that Apple will reject the app when it's time to publish to the App Store.
So, normally, how do other apps do it? How can other chat apps stay alive in the background to receive new messages from the servers? Apps like Google Hangouts, IM+ and such?

Ideally, they aren't really running in the background, but use push notifications, as others have mentioned.
But some chat clients seem to do something else: I've verified (by sniffing the traffic of an idle iOS device) that at least Google Hangouts, Facebook and Skype all keep a persistent socket opened in the background, and regularly send traffic to keep it alive.
I'm suspecting that they are using the VoIP exceptions to Apple's otherwise strict background execution policies. iOS allows "VoIP apps" to run in the background and keep one socket open to be notified about incoming calls and messages.
Maybe they are also using the new "background fetch" feature of iOS 7, but as far as I know, that doesn't allow persistent socket connections.

The iOS operating system allows for the existence of something called a PUSH NOTIFICATION
There exists hundreds of tutorials online which teach you how to implement the notification code and how to respond accordingly when you receive such a message!
http://www.raywenderlich.com/32960/apple-push-notification-services-in-ios-6-tutorial-part-1
Check this link out for an in-depth tutorial on push notifications!
http://maniacdev.com/2011/05/tutorial-ios-push-notification-services-for-beginners

I think most of these apps use push notifications and just load the last messages from the server as soon as the app is being opened.

While there are some hacks, and your app can ask for more time when it goes in background (up to a point, and with no guarantees), this is a perfect application for push notifications.
The server tells the phone there's a message, and iOS wakes your app up to process it.
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Introduction.html

As of iOS 7 there is a new background-execution mode - 'fetch' for apps that need to periodically fetch new data. It sounds like your case would meet that definition.
You can find the information in the iOS App Programming Guide -
Fetching Small Amounts of Content Regularly
In iOS 7 and later, an app that retrieves content regularly from the
network can ask the system for background execution time to check for
new content. You enable support for background fetches from the
Background modes section of the Capabilities tab in your Xcode
project. (You can also enable this support by including the
UIBackgroundModes key with the fetch value in your app’s Info.plist
file.) At appropriate times, the system gives background execution
time to the apps that support this background mode, launching the app
directly into the background if needed. The app object calls the
application:performFetchWithCompletionHandler: method of its app
delegate to let you know when execution time is available.
You can also use push notifications, but that requires some server infrastructure

An app running in the background has limited capability. Read App States and Multitasking thoroughly to decide how best to design your app. Chat is not listed as one of the specific exceptions that can operate with a more relaxed policy. You will never be able to "keep [your] app live in background forever." You might be able to leverage an iOS 7 feature also described in this guide, Fetching Small Amounts of Content Regularly.
iOS App Programming Guide: App States and Multitasking
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOS ProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html

Related

Allowing Application to Run in the Background in iOS Swift

I want my iOS Swift app to run in the background. The things I want to run in the background are:
Timer - that pings server periodically and retrieves data from it and then its displayed on the tableView.
Audio - If a certain condition is encountered in the retrieved data, I play a local audio clip from the app via the avf framework.
The app is working as expected. I have done the following to allow backgrounding:
It does work in the background. However, is there any additional thing that I need to do? such that the app doesn't get rejected from the Apple App store.
“Timer That pings the server periodically” - that will make Apple hate you. And if Apple allowed it on the App Store, users whose battery you are emptying will hate you.
Read up on push notifications. No pinging, no energy use at all. Doesn’t even use WiFi or mobile data - your phone service provider sends you the push at a level below mobile data.

How to run a Background Task on iOS application when Internet connection is detected?

I'm using a third party library "Reachability.swift"
https://github.com/ashleymills/Reachability.swift
Followed this blog post to identify network event using Notification Center, So the change in network event can be identified dynamically in the foreground
https://blog.pusher.com/handling-internet-connection-reachability-swift/
My Requirement:-
I need to run a background service that uses Alamofire(Information not needed for alamofire) to push the locally saved SQLite data to the server whenever internet connection status is Active
Important note:-
iOS Application should not run in the foreground, everything should happen in the background
Please help me out to understand the topic, Thank in advance!
You should fully read and understand Apple's excellent documentation on background execution: Background Execution
There are only a few application types that are allowed to run permanently in background mode:
Apps that play audible content to the user while in the background, such as a music player app
Apps that record audio content while in the background
Apps that keep users informed of their location at all times, such as a navigation app
Apps that support Voice over Internet Protocol (VoIP)
Apps that need to download and process new content regularly
Apps that receive regular updates from external accessories
Apps of those types must ask for specific permission to run in the background. Declaring a wrong type for your app may lead to app rejection by Apple.

Does iOS have something like Android's AlarmManager?

What is iOS' alternative to Android AlarmManager class?
So far the closest thing that I found is NSTimer. But that works only when your application is up, once it goes to the background it won't work, and I need to run some function in the background and from my business logic to decide if I want to do something or not. For example if some condition is satisfied to display local notification.
The only workaround I found is to use remote pushing notifications (silent notifications) just to wake up app, and from there you can implement your business logic.
IMPORTANT NOTE
From what I have found on few places is that people are complaining about using silent notifications to do this because your application might be rejected on app store.
There is none.
As already stated in the comments, the documenation is quite clear on that:
Always try to avoid doing any background work unless doing so improves the overall user experience. An app might move to the background because the user launched a different app or because the user locked the device and is not using it right now. In both situations, the user is signaling that your app does not need to be doing any meaningful work right now.
with the following exceptions:
For tasks that require more execution time to implement, you must request specific permissions to run them in the background without their being suspended. In iOS, only specific app types are allowed to run in the background:
Apps that play audible content to the user while in the background, such as a music player app
Apps that record audio content while in the background
Apps that keep users informed of their location at all times, such as a navigation app
Apps that support Voice over Internet Protocol (VoIP)
Apps that need to download and process new content regularly
Apps that receive regular updates from external accessories
There is no exact equivalent. Please read this: https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
The relevant part:
For tasks that require more execution time to implement, you must request specific permissions to run them in the background without their being suspended. In iOS, only specific app types are allowed to run in the background:
Apps that play audible content to the user while in the background, such as a music player app
Apps that record audio content while in the background
Apps that keep users informed of their location at all times, such as a navigation app
Apps that support Voice over Internet Protocol (VoIP)
Apps that need to download and process new content regularly
Apps that receive regular updates from external accessories
Apps that implement these services must declare the services they support and use system frameworks to implement the relevant aspects of those services. Declaring the services lets the system know which services you use, but in some cases it is the system frameworks that actually prevent your application from being suspended.
If the function you are trying to call does one of the above, the documentation explains how to use background tasks or other methods to accomplish that.

How does the web version of Whatsapp work on iOS devices considering the OS shuts apps in 30 seconds?

Now for those who don't know, can go to https://web.whatsapp.com/ and sync your Whatsapp chats by exchanging a QR code and chat via the web extension of the app.
I am not interested in how they have an initial handshake( might be communicating with whatsapp servers) nor how they sync data so fast for chatting (might be using Open sockets directly from device to client).
I am curious as to how the app works in Background on iOS . AFAIK running a background Intent Service is pretty simple. But not for iOS. iOS allows only up to 30 seconds after the app is shut down normally.
1) I tried crashing the App(swipe up) (Still the web version was running normally)
2) I disabled Background App refresh the web version didn't stop.
3) Even disable Notifications still the web version worked normally.
4) As well they do not have a Blue bar the likes when Google Maps is giving you directions that indicates the app is running in BG
5) Are they using Dummy Geo Fencing to keep them alive? (but that d require BG App Refresh too)
Is it some new feature on iOS 8 that was introduced and I am not aware of
Just as a side note, Apple introduced the Notification Service extension point in iOS 10, which can be used to achieve this. The following applies only to iOS 9.x or earlier.
No app in iOS can be long alive in background with a keep-alive socket, or
guaranteed to wake by remote notifications except those using VoIP background mode (OT: and IIRC Bluetooth background modes).
An app has only ~5 seconds of runtime on applicationDidEnterBackground: after being put in background, unless it is registered for any background modes or tasks. The app would be terminated if it runs out of time in this delegate method.
The background task model mentioned by #xoail has a app-specific, system-imposed time limit (up to 30 seconds...?) and cannot be extended. It is for an app to complete its current work, e.g. uploading a media, before being suspended. Background Transfer Service, since iOS 7.0, is an alternative for long running file transfer.
Silent Remote Notificaiton is observed to be triggered consistently only on charger and Wi-Fi, but always throttled by iOS otherwise. So it is sort of indeterministic - let alone the fact that this can be switched off by flipping the app's Background App Refresh switch.
VoIP background mode (in iOS 8 and later) guarantees to call the app's handler when a VoIP notification is received from APNs. But App Review Guidelines states clearly that background modes should only be used for their intended purpose.
So either Apple waives WhatsApp the use of VoIP background mode for purpose other than WhatsApp Call, or WhatsApp happens to get away from the "use your phone to sync" architecture and does something new for the iPhones.
As per the docs the app can remain in the background performing finite updates to the App. You can continue extending the background process one after the other. Look into Perform finite-length tasks. I think killing the app from background still executes registered actions by the system.
Whatsapp does some clever web session token + background app token generation to keep session valid.
As mentioned in #32112433 by Steven Darbey this is most likely implemented using the new iOS 8 PushKit Service which includes a VoIP service notification type, allowing applications to resume from background. A misuse of the API for non-VoIP purposes, but Apple apparently putting a blind eye on it.
https://developer.apple.com/library/prerelease/ios/documentation/Performance/Conceptual/EnergyGuide-iOS/OptimizeVoIP.html

Implementing a way to upload data to a server when the app is terminated/ i background in Phonegap iOS

I am creating this app which uploads some data to a server. User can change data offline and app can upload this data when phone comes online. But this upload process must be able to accomplish even the app is closed. How this can be done?
You may find limitations in your way. Although iOS enables you to define specific "background modes" for apps that incorporate voip or location services, normally, when an iOS app is terminated, it means really terminated, unless you keep it open but minimized or unless you ask for additional time for the app to stop running once you terminate it:
Best practice to send a lot of data in background on iOS4 device?
But in the best case, you can't simply keep the app running when it is not running.

Resources