Prevent websocket connection to drop when entering background state ios swift

This is solution-

var backgroundUpdateTask: UIBackgroundTaskIdentifier = UIBackgroundTaskIdentifier(rawValue: 0)
func endBackgroundUpdateTask() {
    UIApplication.shared.endBackgroundTask(self.backgroundUpdateTask)
    self.backgroundUpdateTask = UIBackgroundTaskIdentifier.invalid
}
func applicationWillResignActive(_ application: UIApplication) {
    self.backgroundUpdateTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
        self.endBackgroundUpdateTask()
    })
}
func applicationDidBecomeActive(_ application: UIApplication) {
    self.endBackgroundUpdateTask()

}

I believe there is no legitimate way to truly work around this. Apple doesn't want apps doing stuff in the background because background activity is a big battery drain and it could make iPhone users feel their battery doesn't last enough (in addition to other issues such as "unexplained" network usage and so on), so they only provide very limited options regarding background activity in iOS apps for the sake of user experience. However, we can keep the app alive in some manners:

From the App Programming Guide for iOS:

When you find it necessary to keep your app running in the background, iOS helps you do so efficiently and without draining system resources or the user’s battery. The techniques offered by iOS fall into three categories:

  • Apps that start a short task in the foreground can ask for time to finish that task when the app moves to the background.
  • Apps that initiate downloads in the foreground can hand off management of those downloads to the system, thereby allowing the app to be suspended or terminated while the download continues.
  • Apps that need to run in the background to support specific types of tasks can declare their support for one or more background execution modes.

So it seems that, other than asking iOS to allow the app to finish short tasks or downloads, the only way to request the system to allow the app to run in the background is to specify a background execution mode in our Info.plist. This can be done in XCode's Capabilities dialog for your project, or by editing the property list file directly. Let's check which background execution modes we have available:

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

Keeping a socket alive could fall into the "Apps that need to download and process new content regularly" use case, so let's check that:

Fetching Small Amounts of Content Opportunistically

Apps that need to check for new content periodically can ask the system to wake them up so that they can initiate a fetch operation for that content. To support this mode, enable the Background fetch option 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.) Enabling this mode is not a guarantee that the system will give your app any time to perform background fetches. The system must balance your app’s need to fetch content with the needs of other apps and the system itself. After assessing that information, the system gives time to apps when there are good opportunities to do so.

So it seems that this option is only usable for obtaining small amounts of content through HTTP requests (or other network requests), not for the kind of two-way constant communication a websocket would allow you to use. In fact, looking at other related answers, it seems there is indeed no legitimate manner to keep a socket open when the app enters background mode.

This means that, to do what you want, you cannot use websockets as your only communication channel. I'd recommend you to either use the fetch background mode (as described above) in order to fetch content in larger chunks than you would using the websocket while the app is in the background, or if you want the user to be able to see that new content is available, you could implement push notifications.

You can't use Push Notifications to send large amounts of content directly, but they can be used to prompt the user that there is new content available when they open your app. Regardless of whether you use background fetch or Push Notifications, you should implement methods on your App Delegate which will synchronize the app's state with your backend's state whenever your app is brought back from the background state.

Finally, regarding using audio as a workaround: The audio background state key will allow your app to stay alive indefinitely in the background - but if your app does not truly use it in order to play audio, it will get rejected by the app store.

Tags:

Sockets

Ios

Swift