Android/Smack:在睡眠模式下保持XMPP连接的活跃

8
我有一个安卓应用程序,其中聊天客户端是其特色之一。聊天客户端使用基于Smack库的XMPP,并在后台运行Openfire作为XMPP服务器。连接使用BOSH建立。整个XMPP连接处理被实现为服务以在后台运行并侦听传入消息,即使应用程序不在前台活动状态也可以接收消息。到目前为止,一切都运行得非常完美。
唯一的问题似乎是睡眠模式。在模拟器中(设置为“保持唤醒”)或手机正在使用时,XMPP连接保持并且应用程序可以发送和接收消息。然而,一旦手机进入睡眠模式,XMPP连接就会断开 - 我可以在Openfire服务器的管理控制台中看到用户处于离线状态。直觉上,我希望像WhatsApp一样始终能够接收消息。
当然,我已经在网上搜索过了,包括Stackoverflow,但是我没有得到一个明确的答案。通常情况下,使用场景似乎是定期执行任务,比如每小时执行一次。但这似乎不适用于聊天客户端。由于我认为这是一个常见的使用案例——毕竟有很多聊天应用程序或带有聊天功能的应用程序——所以这些是我的问题:
  • 我需要更改/扩展应用程序,以便在手机睡眠时可以接收聊天消息吗?

  • 我偶然发现了WakeLock。这是正确的方法,还是不适合我的用例?

  • 自Lollipop以来,还有JobScheduler API,它本身使用WakeLock。有更好的选择吗?

  • 例如,WhatsApp如何处理这种情况?

顺便提一下:我在使用模拟器进行调试时遇到了睡眠模式的问题。当我在模拟器中关闭“保持唤醒”后,屏幕会在1分钟后变黑并且XMPP连接断开。但是我不知道如何在它变黑后重新唤醒/打开模拟器。Android Studio实际上在某个时候告诉我设备或其他东西已经消失,我必须重新启动模拟器。

2个回答

5
解决这个问题的确切方法是使用推送通知。
当设备进入睡眠状态时,XMPP连接的自然行为是断开连接。
就WhatsApp而言,它也使用相同的XMPP,并维护一个充当消息交换包装类的服务器。该服务器检查消息状态是否已传递。
如果未传递,则发送推送通知。现在,在设备端的推送服务中,当收到消息时,它会检查连接是否处于活动状态并且是否已经通过身份验证。
如果未通过身份验证,则重新建立连接。这种方式是大多数聊天应用程序管理此超时异常的方式。
希望这有所帮助 :)

你不需要推送通知,也不是“XMPP连接在指定的空闲间隔后断开”的自然行为。 - Flow

3

您不需要推送通知,也不需要使用 WakeLock。相反,只需执行以下操作:

  • 将应用程序添加到省电模式的白名单中
  • 使用粘性(START_STICKY)后台服务
  • 使用 Smack 的 ServerPingWithAlarmManager
  • 在 Android 发送 CONNECTIVITY_CHANGED 意图,并在这种情况下使用 XMPPTCPConnectioninstantShutdown()

它会如何影响电池寿命?如果我理解正确,从待机模式中将应用程序列入白名单需要手机用户的确认。 - Christian
电池寿命的影响取决于通过无线电信号传输的XMPP数据包数量。因此,您应该避免不必要的流量。 - Flow
@Flow,最后一个主题的目标是什么?谢谢。 - joao2fast4u

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接