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

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

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

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

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

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

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

我有问题

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

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

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

标签: java android sockets xmpp smack


【解决方案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() 实现会收到消息。
    无需保持连接。无需与系统抗争。没有大量的电池消耗。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-25
      • 1970-01-01
      • 2015-05-24
      • 2015-09-28
      • 1970-01-01
      • 2016-02-14
      相关资源
      最近更新 更多