【问题标题】:Chat App for Android using a XMPP Server and Google Cloud Messaging (or the newer Firebase Cloud Messaging) for Push Notifications使用 XMPP 服务器和 Google Cloud Messaging(或更新的 Firebase Cloud Messaging)推送通知的 Android 聊天应用程序
【发布时间】:2016-11-05 04:14:40
【问题描述】:

我正在为 Android 开发一个聊天应用程序。几周以来,我一直在阅读有关 XMPP 和 Google Cloud Messaging(以及 Firebase Cloud Messaging)的信息,但我仍然很困惑。

目前,我已经在本地(Ejabberd)设置了一个 XMPP 服务器,并使用 Smack 库成功地将我的 Android 应用程序连接到它。

据我了解,我需要使用 GCM 或更新的 FCM 进行推送通知,因此我已经在 Google Cloud Platform 中创建了一个项目。我的 Android 应用程序也可以使用 Smack 库连接到它(而不是直接连接到我的 XMPP 服务器)。在我的服务器中,我有一个小型 Java 应用程序,它也使用 Smack 库连接到 GCM。

到这里为止一切都很好。我最大的困惑是:我如何将 XMPP 服务器与 GCM 一起用于推送通知? 我为服务器端实现找到的每个文档、示例、指南、教程都只是告诉我如何连接到 GCM,但没有告诉我如何将我的 XMPP 服务器与 GCM 结合使用。 我错过了什么?我的 Java 应用程序只是连接到 GCM,从 GCM 接收和发送消息,但我的 XMPP 服务器只是坐在那里无所事事。实际上我的 Android 应用和服务器 Java 应用只使用 GCM,而不是我的 XMPP 服务器。

我希望有人可以帮助我从整体上理解这一点,我显然缺少实现此实现的一些关键要素。

【问题讨论】:

标签: java android google-cloud-messaging xmpp firebase-cloud-messaging


【解决方案1】:

您需要将 Ejabberd 和 FCM 混合在一起,这就是所有大型聊天应用程序的做法。最基本的,有 3 个组件:App Server 通过 XMPP 连接到 FCM、Ejabberd 和您的客户端应用程序。

  1. 当应用程序处于前台时,您使用 Smack 库直接连接到您的 Ejabberd 服务器、发送消息、更改用户的状态等。与您的 Ejabberd 的连接在此期间保持。您不要在此期间发送上游消息!
  2. 一旦用户离开您的应用,您关闭连接。用户现在被视为“离开”或“离线”。
  3. 从此时起,您的应用服务器与 FCM 通信,以使用 Smack 库向设备发送下游消息
  4. 在客户端设备上:您处理传入消息并显示通知。使用 Android N,用户可以直接从通知中回复。我假设在这种情况下,您将使用 FCM 向您的应用服务器发送上游消息,因为在此期间,您的 Ejabberd 服务器没有活动连接。
  5. 一旦用户点击通知,应用就会回到前台,您重新连接到 Ejabberd 并返回到第 1 步。

这是实现您想要的架构的基本描述。

【讨论】:

  • 在第 1 步中,当您说“您在此期间不发送上游消息”时,您的意思是上游消息到 FCM 对吗?换句话说,客户端设备总是在前台直接向 Ejabberd 发送消息。客户端设备从 FCM 和 Ejabberd 接收消息还是仅从 FCM 接收消息?
  • 是的,我提到了 FCM。客户端设备从 Ejabberd 接收消息。当应用程序处于后台时,您使用 FCM 通知设备新消息。即使您可以使用 FCM 发送高达 4KB 的有效负载,我建议您只使用 FCM 发送所谓的“推送同步”消息并从 Ejabberd 获取实际消息。所以 Ejabberd 是所有消息的主要数据存储,您的带有 FCM 下游消息的 App Server 只专注于一件事 - 使客户端与 Ejabberd 同步。这也意味着 Ejabberd 和您的 App Server 当然需要进行通信。
  • 现在我需要知道如何连接 Ejabberd 和 App Server。顺便说一句,我已经让客户端应用程序启动并运行,仅使用 FCM 进行下游和上游没有问题,我也需要使用 Ejabberd 来解决可扩展性问题,对吗?仅 FCM 方法的限制是什么?
  • 查看这篇文章stackoverflow.com/questions/16189612/…,将 Ejabberd 离线消息转发到您的应用服务器。这不仅是为了可扩展性,而且事实上 Ejabberd 被设计为聊天服务器,因此无需重新发明轮子 :) 除了每条消息 4KB 之外,我不确定 FCM 的其他限制。如果对你有帮助,请采纳这个答案,谢谢! :)
【解决方案2】:

这是一个示例 java 项目,用于展示 Firebase 云消息传递 (FCM) XMPP 连接服务器。这个项目是一个非常简单的独立服务器,我作为一个更大项目的基础开发。它是我们必须在我们的环境中实现的应用服务器。此服务器使用 XMPP 协议通过 FCM CCS 服务器将数据发送到客户端应用程序。

https://github.com/carlosCharz/fcmxmppserver

我还在 youtube 上创建了一个视频,我解释了它的作用。

https://www.youtube.com/watch?v=PA91bVq5sHw

希望你觉得它有用。

【讨论】:

  • @CarlosBecerraRodríguez 我已尝试在谷歌云模块(端点)上实现您的服务器,但出现错误并且未发送下游消息。
  • @CarlosBecerraRodríguez 错误是 The following addresses failed: 'fcm-xmpp.googleapis.com:5236' failed because java.net.SocketException: Permission denied: connection to (10, [2607:f8b0:4001:c06::bc]:5236,6) denied due to policy 我什至在 Github 上打开了一个问题
  • @JiTHiN 很抱歉回答得太晚了。我没有收到来自 stackoverflow 的通知。我确实收到了来自 GitHub 项目的通知。你把你的错误放在那里了吗?
【解决方案3】:

您应该设置一个连接到 FCM(以前称为 GCM)的 Java 服务器。然后,您可以从您的设备向 FCM 发送上游消息,然后 FCM 将该上游消息发送到您的 Java 服务器,然后在该 Java 服务器中,您可以处理该上游消息以将下游消息发送到目标设备。然后在设备端,您可以处理接收到的下游消息以发出推送通知。

一些有用的链接:

如何发送上游消息:
https://firebase.google.com/docs/cloud-messaging/upstream#sample-send

如何接收和处理下游消息:
https://firebase.google.com/docs/cloud-messaging/downstream#sample-receive

我如何设置示例 Java 服务器:
https://stackoverflow.com/a/38170310/4433653

【讨论】:

  • 非常感谢您的回答,但我仍然感到困惑。我已经有一个连接到 FCM 的 Java 服务器(与该链接的代码非常相似),但它可以在没有我的 XMPP 服务器的情况下工作,它只是使用 FCM 来处理所有事情。我错过了什么?
  • FCM 有两种支持的协议 HTTP 和 XMPP。 HTTP 仅用于通过 FCM 从您的服务器向您的设备发送消息。 XMPP 允许服务器到设备和设备到服务器的消息都通过 FCM。
  • @ArthurThompson 对,所以... 我如何将我的 XMPP 服务器与 FCM 一起用于推送通知?,我找到的每个实现、示例、指南(包括这个答案的链接)只是使用和解释FCM部分,XMPP呢?该 Java 服务器可以在我的 XMPP 服务器根本没有运行的情况下工作。
  • @Santiago Fermin 您将在您的应用服务器和 FCM(准确地说是 CCS)之间建立 XMPP 连接,您可以使用类似 Smack Java XMPP 库的东西建立该连接:igniterealtime.org/projects/smack。您的应用服务器将是 XMPP 服务器。
  • 您不需要 XMPP 服务器,CCS(FCM 的一部分)就是 XMPP 服务器。您的应用服务器将是 CCS 的 XMPP 客户端并与之通信。
【解决方案4】:

我还在使用最新版本的 Smack v.4.1.8 在 Android 中构建聊天应用程序,我们的服务器正在使用 ejabberd。我不使用任何第三方(如 GCM 或 Firebase)将下游消息从用户推送到用户消息。如果我没有错,您将使用 GCM 或 Firebase 将用户推送到用户消息,如果是,请不要这样做。

为什么? TCP 协议会在连接建立并仍然连接时继续侦听您在 App 中注册的调用侦听器。 Smack 有一个名为 "addAsyncStanzaListener()"

的监听器

addAsyncStanzaListener 用于监听 App 中的接收数据包。他们有

 public void processPacket(Stanza packet) 

您可以调用它,并且您将在一段时间内监听数据包。

我做了一项关于保持 Smack 稳定连接的研究。大多数 Android 智能手机都有各自的配置和限制。我们无法测试所有设备。 以下是我保持连接稳定的提示:

  1. 使用 ForegroundService 代替 BackgroundService,我提出这种方法是因为大多数 Android 设备都限制了在后台运行的应用程序。当应用程序从任务管理器滑动时,他们将杀死应用程序。 (例如华硕 zenphone 有电源管理)
  2. ForegroundService 将阻止应用空闲。
  3. 注册 ReconnectingManager
  4. 注册Ping失败
  5. 注册 ServerPingWithAlarmManager

就是这样。如有任何疑问,请在下方评论:)

最好的问候 R Aditya Gumay

【讨论】:

    【解决方案5】:

    您的建议适用于与 tcp/ip never drop 的连接。这在移动 3G/4G 网络中并非如此。所以在真实的3G/4G网络中,手机客户端/APP可能处于僵尸状态(断开连接)。 这就是您需要 Firebase/FCM 来发挥作用的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-10
      • 2016-06-24
      • 2022-12-14
      • 2014-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-03
      相关资源
      最近更新 更多