Smack 4.1 重新连接问题

Posted

技术标签:

【中文标题】Smack 4.1 重新连接问题【英文标题】:Smack 4.1 Re-connection issue 【发布时间】:2015-07-22 20:40:52 【问题描述】:

我正在开发一个聊天应用程序,其中

    我有一个持续运行的后台服务。 应用程序运行平稳,我能够毫无问题地接收和发送消息。 我正在使用默认的 Smack 4.1 重新连接管理器,它会在连接丢失时立即连接(几乎 90% 的时间)。

但有时,当连接丢失时,Smack 重新连接管理器会停止工作。

我无法找出导致此问题的原因。

查看手机时,延迟 12 到 14 小时后,我可以看到 android 服务仍在运行,但 XMPP 重新连接已停止工作。然后我必须强制停止应用程序,然后重新启动服务并让它再次连接到 XMPP 服务器。

我的假设是当“电话网络从 Wifi-to-Data 或 Data-to-Wifi 切换”时发生。与此同时,Smack 4.1 Re-connection Manager 停止工作。虽然,我不确定。

我有问题

    PingManager 有什么用? PingManager 在这种情况下可以提供帮助吗? 什么是流管理?我该如何启用它?在这种情况下有用吗?

还有其他解决方案可以解决这个问题吗?我正在考虑以下解决方案:

    将GCM也与XMPP一起使用,所以当XMPP重新连接失败时,我可以得到PUSH并在PUSH的基础上重新连接。 使用警报服务。 (问题:由于连接丢失而在队列中的消息将取决于下一个警报时间表) 每次用户返回应用程序时连接 XMPP。 (问题:由于连接丢失而在队列中的消息将取决于用户返回应用程序)

【问题讨论】:

我认为您应该按照解决方案 1 中的说明使用 GCM。它将解决您的连接丢失问题,并减少服务器负载和用户的移动流量。 @shanrais 你有我的确切问题,但我很失望看到没有答案:(你得到答案了吗? 我现在正在使用 GCM。 使用 PingManager 怎么样?您选择 GCM 而不是 PingManager 有什么特别的原因吗?我也想知道更多关于使用 GCM 的细节?什么触发了 GCM PUSH 消息?任何服务器端逻辑? Smack 库对我来说总是有问题,II gae up 转移到另一个开源项目 Conversation..google.co.in/url?sa=t&source=web&rct=j&url=https://… 【参考方案1】:

有点晚,但也许它可以帮助其他人。我不是 XMPP 专家,但我遇到了一个名为 "XMPP and Android" 的 Ignite Realtime 演示文稿,它指出了这个问题以及如何处理这个问题。

它提供了将服务器 ping 与警报管理器一起使用的理想选择,间隔为 30 分钟。

我还发现了另一篇与此问题相关的帖子,并提供了 3 个选项。值得一看。 https://ramzandroidarchive.wordpress.com/2016/03/14/handling-connection-break-issue-in-smack-4-1/。

【讨论】:

【参考方案2】:

这是一个老问题,但我个人过去一直在努力使用 Smack 保持持久连接,并且不得不根据多种资源找出答案。我将尝试在此答案中解决我的发现。

注意 - 不要使用AbstractXMPPConnectionisConnected() 方法来确定连接是否处于活动状态。这仅仅是对象的内部状态。它无法知道连接是否真正处于活动状态。 唯一可以确定的方法是通过服务器或客户端 ping。

持久连接路由 - 不推荐

首先要了解 - 如果您确实想要与服务器建立持久连接(我一直走这条路线,不推荐它 - 更多信息请参见下文),您必须手动执行操作。 在服务器端 - 确保在合理的时间后断开空闲的客户端(太长,您将丢失消息,因为连接将被终止但服务器仍会认为它处于活动状态。太短并且您将重复如果您的用户互联网连接不佳,则连接断开。我个人使用 30 秒。我想 30 到 60 秒之间的任何时间都可以)。这将允许您在与服务器的连接丢失时在客户端进行检测。 第二件事是实现ConnectionListener Smack 接口。它包含对各种连接事件的回调,例如connectionClosedOnError,允许您恢复与服务器的连接。 然后您应该收听网络连接事件 - 如果用户更改了网络,您可能应该断开连接并重新连接。 这是有争议的,但我个人在以这种方式保持连接存在问题,依赖于服务器 ping 和回调。如果您也有 - 您应该从客户端 ping 服务器以确定。 Smack 有 ServerPingWithAlarmManager 类正是为此 - 它每 30 分钟 ping 服务器。唉,对我来说这行不通,因为一些 OEM(小米我在看你)在他们的自定义 Android 皮肤中限制了后台任务。对我有用的方法是使用自定义 PingManager ping 服务器。使用PingManager.getInstanceFor(connection) 获取它,并使用AlarmManager 安排它每X 分钟运行一次(对我来说是7 分钟)。 对于这个 ping 管理器,您应该注册一个 PingFailedListener,它将在其 pingFailed() 方法上重新连接。 这一切听起来很糟糕?这是最糟糕的部分 - 整个事情在 api >= 23 上崩溃了。这一切都很好,直到 Doze 和 App Standby 发挥作用。这就是为什么如果您采用持久连接路线 - 您必须请求可怕的 ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 权限,该权限允许您的应用绕过 Doze 和 App Standby。 恭喜!假设 Google 没有因为鲁莽地请求白名单电池优化权限而禁止您的应用程序进入 Play 商店 - 您现在与应用程序内的服务器建立了可靠且持久的 xmpp 连接,即使用户什么都不做,也会像疯了一样耗尽电池电量与它长期互动。 正如我之前所说,这不是一个理想的解决方案。

更好的解决方案 - FCM 高优先级消息

在了解与服务器保持连接的问题后 - 这是我推荐使用的方法。 不要试图与每个 Android 版本限制更多的网络连接和电池优化作斗争。 将 FCM 消息集成到您的服务器中,即使设备处于打盹模式,您的用户也可以实时接收消息。 这是我现在使用的方法,它的优点是大大降低了电池消耗。 我不 ping 服务器,服务器也不 ping 我的应用程序。当设备更改网络或连接因错误而关闭时 - 我只是断开连接。 连接时,消息由Message 类型StanzaListener 接收。 在断开连接时,FirebaseMessagingService() 实现会收到消息。 无需保持连接。无需与系统抗争。没有大量的电池消耗。

希望这个答案能在未来帮助某人并节省他们一些时间,因为我花了很多时间、精力和反复试验才能找到我满意的解决方案。

【讨论】:

以上是关于Smack 4.1 重新连接问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 smack 4.1 登录后如何重新加入群组/房间

与 gtalk 的 Smack 4.1 连接

无法使用 Smack 4.1 从 Android 连接 apache vysper XMPP 服务器

使用 Smack 4.1 连接到 Gtalk

Smack 4.1 SASL 身份验证错误

Smack:ReconnectionManager 在重新连接时发送重复的登录请求