进入后台状态ios swift时防止websocket连接断开

Posted

技术标签:

【中文标题】进入后台状态ios swift时防止websocket连接断开【英文标题】:Prevent websocket connection to drop when entering background state ios swift 【发布时间】:2017-05-08 17:30:45 【问题描述】:

经过大量研究,这似乎是一个灰色地带......

一旦用户进入后台状态,我会尝试通过 websockets 发送偶尔的网络请求(使用 Swift 库 Starscream,但我认为问题一般出在 ios 和套接字上)。用户离开应用程序后不久,套接字连接会自动断开。我认为这与 Apple 关于后台第三方网络活动的政策有关。

在我的 AppDelegate 中,我尝试在用户离开等时重新连接,但这不起作用。我也听说过涉及播放音频的解决方法,但显然这会阻止我的应用程序发布到 App Store(如果不是这种情况,那么为什么以及如何工作?)。其他人说我需要 Apple 的某种资助,我该如何申请?如果有人能解决这个问题,并提供一个合法的解决方案,那就太好了。我觉得这是应用程序应该具备的能力,所以我正在等待找到解决方案。

【问题讨论】:

您找到解决方案了吗?我有同样的问题 嗨 Caspar Wylie,您能否找到适合后台模式问题的解决方案?或者,如果您可以分享您尝试过的其他解决方案作为替代解决方案的经验,谢谢!我面临与 GFayeSwift 库相同的问题,该库在后台使用 Startscream 库。 不幸的是,我记得推迟了我打算使用的功能。我从来没有找到一个可靠的解决方案。不知道现在有什么可能,4 年后,我想 IOS 世界发生了很多变化。 【参考方案1】:

我相信没有合法的方法可以真正解决这个问题。 Apple 不希望应用程序在后台执行操作,因为后台活动会消耗大量电池,并且可能会让 iPhone 用户觉得他们的电池不够用(除了其他问题,例如“无法解释的”网络使用等) ,因此为了用户体验,它们仅提供有关 iOS 应用程序中后台活动的非常有限的选项。但是,我们可以通过某些方式让应用保持活力:

来自App Programming Guide for iOS:

当您发现有必要让您的应用在后台运行时,iOS 可以帮助您高效地执行此操作,并且不会耗尽系统资源或用户的电池。 iOS 提供的技术分为三类:

在前台启动短任务的应用可以在应用移至后台时请求时间来完成该任务。 在前台启动下载的应用可以将这些下载的管理移交给系统,从而允许在下载继续时暂停或终止应用。 需要在后台运行以支持特定类型的应用程序 任务可以声明它们支持一个或多个后台执行 模式。

所以看起来,除了要求iOS允许应用程序完成短任务或下载之外,请求系统允许应用程序在后台运行的唯一方法是在我们的@987654324中指定后台执行模式@。这可以在 XCode 的 Capabilities 对话框中为您的项目完成,或者通过直接编辑属性列表文件来完成。让我们检查一下我们有哪些后台执行模式可用:

在 iOS 中,只允许特定的应用类型在后台运行:

在后台向用户播放有声内容的应用,例如音乐播放器应用 在后台录制音频内容的应用程序 让用户随时了解其位置的应用,例如导航应用 支持互联网协议语音 (VoIP) 的应用 需要定期下载和处理新内容的应用 从外部附件接收定期更新的应用

保持套接字处于活动状态可能属于“需要定期下载和处理新内容的应用”用例,所以让我们检查一下:

机会主义地获取少量内容

需要定期检查新内容的应用可以要求系统唤醒它们,以便它们可以启动对该内容的提取操作。要支持此模式,请从 Xcode 项目的 Capabilities 选项卡的 Background mode 部分启用 Background fetch 选项。 (您也可以通过在应用程序的 Info.plist 文件中包含带有获取值的 UIBackgroundModes 键来启用此支持。)启用此模式并不能保证系统会给您的应用程序任何时间执行后台获取。系统必须平衡您的应用程序获取内容的需求与其他应用程序和系统本身的需求。在评估该信息后,系统会在有好的机会时为应用留出时间。

所以这个选项似乎只能用于通过 HTTP 请求(或其他网络请求)获取少量内容,而不是 websocket 允许您使用的那种双向持续通信。事实上,看other related answers,似乎确实没有合法的方式让应用程序进入后台模式时保持套接字打开。

这意味着,做你想做的事,你不能使用 websockets 作为你唯一的通信渠道。我建议您使用fetch 后台模式(如上所述)以便在应用程序处于后台时使用比使用 websocket 更大的块获取内容,或者如果您希望用户能够要查看可用的新内容,您可以实现push notifications。

您不能使用推送通知直接发送大量内容,但它们可用于在用户打开您的应用时提示有新内容可用。无论您使用后台获取还是推送通知,您都应该在您的 App Delegate 上实现方法,当您的应用从后台状态恢复时,该方法将同步应用的状态和后端的状态。

最后,关于使用音频作为解决方法:audio 背景状态键将允许您的应用在后台无限期地保持活动状态 - 但如果您的应用没有真正使用它来播放音频,它被应用商店拒绝。

【讨论】:

感谢您的深入回答。 我是否想每小时发出一个套接字请求?所以不是那么频繁/持续的沟通。【参考方案2】:

这是解决方案-

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()


【讨论】:

这对我有用,但你能解释一下这段代码吗?我不明白它为什么起作用? 这不是 Apple 推荐的使用方式。请参考developer.apple.com/documentation/uikit/app_and_environment/…【参考方案3】:

我不确定您的应用程序在做什么,因此我可以保证 Apple 会批准,但您需要 Backgroundmodes 授权才能执行此操作。

在 Xcode 中:

Here 是指向 Apple Docs 的链接,用于向您的应用程序添加权利。

Here 是用于在 iOS 中编程后台执行的文档。

在 Xcode 中启用授权并将所需类型添加到您的 plist 后,您应该能够开始编写后台 websocket 连接

【讨论】:

不幸的是,即使添加后台模式也不允许套接字连接保持活动状态。后台模式仅允许 iOS 在 iOS 决定唤醒应用程序的短时间内唤醒应用程序,并且套接字连接将要求应用程序无限期地在后台保持唤醒状态。 @PedroCastilho 啊,我明白了。是的,应用程序绝对不允许无限期地保持在后台模式,因此您将无法使用该方法。介意我问你想通过套接字连接发送什么吗?你能用推送通知完成同样的事情吗? 我不是 OP :) 您应该将此作为评论添加到问题中。【参考方案4】:

如果你只有AppDelegate,你应该使用this

如果你有SceneDelegate,请使用我的答案:

var backgroundUpdateTask: UIBackgroundTaskIdentifier = UIBackgroundTaskIdentifier(rawValue: 0)

func sceneDidBecomeActive(_ scene: UIScene) 
    self.endBackgroundUpdateTask()


func sceneWillResignActive(_ scene: UIScene) 
    self.backgroundUpdateTask = UIApplication.shared.beginBackgroundTask(expirationHandler: 
      self.endBackgroundUpdateTask()
    )


func endBackgroundUpdateTask() 
    UIApplication.shared.endBackgroundTask(self.backgroundUpdateTask)
    self.backgroundUpdateTask = UIBackgroundTaskIdentifier.invalid

【讨论】:

这不是 Apple 推荐的使用方式。请参考developer.apple.com/documentation/uikit/app_and_environment/… @ThEuSeFuL 嘿,我关注了docs.microsoft.com/en-us/xamarin/ios/app-fundamentals/…,但它仅适用于调试,不适用于发布。

以上是关于进入后台状态ios swift时防止websocket连接断开的主要内容,如果未能解决你的问题,请参考以下文章

Swift - 当应用程序进入后台状态时,从 AppDelegate 更新 RootViewController 中的值

Swift 防止 TabBar 在键盘处于活动状态时向上移动

【iOS】后台播报TTS(防止APP后台被杀死)

进入后台状态时是不是可以在 iOS 4 设备上运行 NSThread 或 NSTimer?

如果应用程序在后台,iOS Swift Timer 不会触发

防止 iOS 在进入后台之前对应用进行屏幕截图