Smack 4.1重新连接问题

时间:2015-05-12 06:04:19

标签: java android sockets xmpp smack

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

  1. 我有一个持续运行的后台服务。
  2. 应用程序运行顺畅,我可以毫无问题地接收和发送邮件。
  3. 我正在使用默认的Smack 4.1重新连接管理器,它会在连接丢失后立即连接(几乎90%的时间)。
  4. 但有时,当连接丢失时,Smack重新连接管理器将停止工作。

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

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

    我的假设是指"手机网络从Wifi转换为数据或数据转Wifi" 时发生的假设。与此同时,Smack 4.1重新连接管理器停止工作。虽然,我不确定。

    我有问题

    1. PingManager有什么用? PingManager在这种情况下可以提供帮助吗?
    2. 什么是StreamManagement?我该如何启用它?这种情况有用吗?
    3. 任何其他解决此问题的解决方案?我在考虑以下解决方案:

      1. 要使用GCM以及XMPP,所以当XMPP无法重新连接时,我可以获得PUSH并在PUSH的基础上再次连接。
      2. 使用闹钟服务。 (问题:由于连接丢失而在队列中的邮件将取决于下一个警报计划)
      3. 每次用户返回应用程序时连接XMPP。 (问题:由于连接丢失而在队列中的邮件将取决于用户返回应用程序)

2 个答案:

答案 0 :(得分:1)

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

page 2

它提供服务器ping与Alarm Manager理想情况下,间隔30分钟。

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

答案 1 :(得分:0)

这是一个古老的问题,但我个人在过去使用Smack维持持久连接时遇到了困难,并且必须根据多种资源找出答案。我将尝试在这个答案中解决我的发现。

注意 - 请勿使用isConnected()的{​​{1}}方法来确定连接是否处于活动状态。这仅仅是对象的内部状态。它没有真正的方法来了解连接是否真正活跃 唯一可以确定的方法是通过服务器或客户端进行ping操作。

持久连接路由 - 不推荐

首先要理解的是 - 如果你确实想要与服务器保持持久连接(而且我一直都是这条路线并且不推荐它 - 下面有更多相关内容),你必须手动完成。
在服务器端 - 确保在一段合理的时间后断开空闲的客户端(太长时间并且您将丢失消息,因为连接将被终止但服务器仍将其视为活动状态。太短并且您将重复如果您的用户网络连接不良,我们会断开连接。我个人用户30秒。我想30到60秒之间的任何事情都可以。)这将允许您在客户端检测何时丢失与服务器的连接 要做的第二件事是实现AbstractXMPPConnection Smack界面。它包含各种连接事件的回调,例如ConnectionListener,允许您恢复与服务器的连接 然后你应该听网络连接事件 - 如果用户改变了网络,你应该断开连接并再次重新连接 这是有争议的,但我个人遇到了以这种方式保持连接的问题,依赖于服务器ping和回调。如果你也有 - 你应该从客户端ping服务器以确定 Smack正好具有connectionClosedOnError类 - 它每30分钟对服务器进行一次ping操作。唉,对我来说这没用,因为一些原始设备制造商(小米我看着你)在他们的自定义Android皮肤中限制了后台任务。对我有用的方法是使用自定义PingManager ping服务器。使用ServerPingWithAlarmManager获取它,并使用PingManager.getInstanceFor(connection)安排它每X分钟运行一次(7分钟为我工作)。
对于此ping管理员,您应该注册一个AlarmManager,它将在PingFailedListener方法上重新连接 这一切听起来都不好?这是最糟糕的部分 - 整个事情在api> = 23时分开。这一切都很好,直到Doze和App Standby发挥作用。这就是为什么如果你去坚持连接路线 - 你必须要求可怕的pingFailed()权限,允许你的应用程序绕过Doze和App Standby。
恭喜!假设谷歌没有禁止你的应用程序从Play商店肆无忌惮地要求获得白名单电池优化许可 - 你现在可以在应用程序内部与服务器建立可靠且持久的xm​​pp连接,即使用户什么也不做,就像疯了一样消耗电池长期与它接触。 正如我之前所说,这不是一个理想的解决方案。

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

在了解了与服务器保持连接的问题之后 - 这是我建议使用的方法 请勿尝试对抗每个Android版本的网络连接和更严格的电池优化 将FCM消息集成到您的服务器中将允许您的用户即使在设备处于打盹模式时也能实时接收消息。
这是我现在使用的方法,它可以很好地利用更多更低的电池排水。
我没有ping服务器,服务器没有ping我的应用程序。当设备改变网络或由于错误导致连接关闭时 - 我只是断开连接 连接后,邮件会以ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS类型Message收到 断开连接时,StanzaListener实现会收到消息 无需坚持连接。无需与系统作斗争。没有巨大的电池排水。

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