How can an iOS app keep a TCP connection alive indefinitely while in the background?

An iPhone app, connecting to a remote server via TCP. The use scenarios are:

  1. app (user) sends data to server and server responds data back.
  2. server might send data to app while it does nothing.

Assume that if app does not send data to server for 30 minutes, server will close the connection. I want to keep the connection alive for 120 minutes even if user does nothing.

Case 1: if app is in foreground, I can use timer to send some do-nothing data to server. No problem.

Case 2: if user pressed Home and app went to background, what could I do? I don't wan to show alert or something to interrupt user(he is away or playing games). I just wanna keep the connection alive for a longer period and when user comes back to the app, he found out that the connection will be still alive and be happy with that.

I have read documentations about background execution, multitasking, and local notifications of iphone APIs. I'm not sure whether if I can achieve Case 2.

Only use legal APIs, no jailbreaking.


Solution 1:

Tapbots solved this problem with Pastebot by prompting the user to run a silent background audio track at all times.

Note that Apple frowns on using hacks like employing the background audio or VOIP APIs to keep non audio or VOIP apps running (as evidenced by the 'workaround' described in the article above) so dabbling with these techniques risks rejection at the point of submission.

Unfortunately, though, there is no legal API to keep a connection alive in the background. Perhaps they'll introduce one in a future update to iOS, but you might consider submitting a feature request to voice your support for it.

Solution 2:

Please have a look at Implementing a VoIP Application in Apple's iOS Application Programming Guide. This is no tested solution, but I think it can be used to achieve what you are asking for.

Implementing a VoIP Application

A Voice over Internet Protocol (VoIP) application allows the user to make phone calls using an Internet connection instead of the device’s cellular service. Such an application needs to maintain a persistent network connection to its associated service so that it can receive incoming calls and other relevant data. Rather than keep VoIP applications awake all the time, the system allows them to be suspended and provides facilities for monitoring their sockets for them. When incoming traffic is detected, the system wakes up the VoIP application and returns control of its sockets to it.

I am not sure if you're developing a VoIP app but you'll be able to access the sockets and react on incoming packets. The text after the quote refers to [setKeepAliveTimeout:handler:][2] which allows you to set a block of code which allows you to keep alive a(your VoIP) connection. Minimum scheduling time is 10 minutes, though.

In Implementing a VoIP Application is a paragraph on Installing a Keep-Alive Handler. I am curious if this will help. Please give us a note if this solved your problem.

Solution 3:

1.Create your socket with VOIP property like this

[inputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;

[outputStream  setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;

2.Add required background mode as "App provides Voice over IP services" in app.plist

If your application in background mode the voip socket will not close. Using this socket with uilocal notification you can get.

"If your application is not an original voip application app store will reject"

Solution 4:

For when the app is in the foreground:

Look at STOMP http://stomp.codehaus.org/Protocol

The STOMP Framework in Obj-C http://code.google.com/p/stompframework/

and the ActiveMQ broker http://activemq.apache.org/

For when the app is in the background I would probably go for using APNS (Notifications) to prompt the user to wake the app back up...