Smack 4.1 重新连接问题持久连接路由 - 不推荐更好的解决方案 - FCM 高优先级消息

2022-09-03 02:58:19

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

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

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

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

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

我的假设是,当“电话网络从Wifi切换到数据或数据切换到Wifi”时,就会发生这种情况。在此期间,Smack 4.1 重新连接管理器停止工作。虽然,我不确定。

我有问题

  1. PingManager有什么用?在这种情况下,PingManager能有所帮助吗?
  2. 什么是流管理?如何启用它?在这种情况下有帮助吗?

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

  1. 为了将GCM与XMPP一起使用,因此当XMPP无法重新连接时,我可以获取PUSH并在PUSH的基础上再次连接。
  2. 使用警报服务。(问题:由于连接丢失而在队列中的消息将取决于下一个警报计划)
  3. 每次连接 XMPP 时,当用户返回到应用程序时。(问题:由于连接丢失而在队列中的消息将取决于用户返回应用程序)

答案 1

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

page 2

它提供使用服务器ping和警报管理器,理想情况下间隔为30分钟。

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


答案 2

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

注意 - 不要使用您的方法来确定连接是否处于活动状态。这只是对象的内部状态。它没有真正知道连接是否实际处于活动状态的方法。
唯一确定的方法是通过 ping,无论是通过服务器还是由客户端。isConnected()AbstractXMPPConnection

持久连接路由 - 不推荐

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

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

在了解了与服务器保持连接的问题之后 - 这是我推荐使用的方法。
不要试图对抗网络连接和电池优化,这些优化在每个Android版本中都会变得更加严格。
将 FCM 消息集成到服务器中将允许您的用户实时接收消息,即使设备处于低电耗模式也是如此。
这就是我现在使用的方法,它运行良好,电池消耗量大大降低
我不 ping 服务器,服务器也不会 ping 我的应用程序,当设备更改网络或连接由于错误而关闭连接时 - 我只是断开连接。
连接时,消息由 类型 接收。
断开连接时,实现将接收消息。
无需保留连接。无需与系统作斗争。没有巨大的电池消耗。MessageStanzaListenerFirebaseMessagingService()

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


推荐