【问题标题】:Receiving messages from ejabberd XMPP server on Android client在 Android 客户端上接收来自 ejabberd XMPP 服务器的消息
【发布时间】:2019-10-13 13:27:04
【问题描述】:

我正在尝试使用 ejabberd XMPP 服务器 (19.02)、Smack 库 (4.2.4) 和使用 Android Studio 的 Android SDK 25 创建一个 Android 聊天客户端。

我按照此处找到的示例应用程序进行操作:https://www.blikoontech.com/tutorials/android-smack-xmpp-introductionbuilding-a-simple-client

一切正常,我可以在运行该示例应用的两台不同 Android 设备之间发送消息。

在 ejabberd 中,有一些选项可以使用名为 ejabberdctl 或 ejabberd REST API 的 CLI 工具直接从服务器向客户端发送消息。当我以这种方式发送消息时,Android 客户端不会收到这些消息。我尝试与 Conversations 和 Gajim 等其他客户合作,他们都可以收到它。我很确定使用这些方法发送的消息会到达,因为它们在发送到离线客户端时是作为离线消息(在 ejabberd 网络管理员上)接收的。

这是用于接收传入消息的 Android (java) 代码部分(来自该示例应用程序的 roosterconnection.java)。如果我缺少任何东西,请建议我。非常感谢。

ChatManager.getInstanceFor(mConnection).addIncomingListener(new IncomingChatMessageListener() {
            @Override
            public void newIncomingMessage(EntityBareJid messageFrom, Message message, Chat chat) {
                ///ADDED
                Log.d(TAG,"message.getBody() :"+message.getBody());
                Log.d(TAG,"message.getFrom() :"+message.getFrom());

                String from = message.getFrom().toString();

                String contactJid="";
                if ( from.contains("/"))
                {
                    contactJid = from.split("/")[0];
                    Log.d(TAG,"The real jid is :" +contactJid);
                    Log.d(TAG,"The message is from :" +from);
                }else
                {
                    contactJid=from;
                }

                //Bundle up the intent and send the broadcast.
                Intent intent = new Intent(RoosterConnectionService.NEW_MESSAGE);
                intent.setPackage(mApplicationContext.getPackageName());
                intent.putExtra(RoosterConnectionService.BUNDLE_FROM_JID,contactJid);
                intent.putExtra(RoosterConnectionService.BUNDLE_MESSAGE_BODY,message.getBody());
                mApplicationContext.sendBroadcast(intent);
                Log.d(TAG,"Received message from :"+contactJid+" broadcast sent.");
                ///ADDED

            }
        });

【问题讨论】:

  • 如果您使用 ejabberdctl 发送消息,您的 Android 客户端不会收到它们。如果您使用任何其他客户端将消息发送到您的 Android 客户端怎么办?
  • 嗨@Badlop,我试过了,我的测试Android客户端可以接收来自其他客户端的消息。我有一种感觉,我关注的示例应用程序是一个不完整的应用程序,因此不包括接收以“非常规”方式发送的消息的功能。但是,我研究了 smack API 文档,这 - ChatManager.getInstanceFor(mConnection).addIncomingListener 是监听传入消息的唯一方法。

标签: android xmpp ejabberd smack


【解决方案1】:

这是一个可能的解释,基于我对桌面客户端 Tkabber 的实验:

  1. 我使用 Tkabber 客户端登录 ejabberd,帐户 user1@localhost,资源 tka1,优先级 -3。此实验中的负优先级很重要。

  2. 然后我执行命令发送到完整的 JID,包括正确的资源:

ejabberdctl send_stanza aaa@localhost user1@localhost/tka1 “...”

  1. 客户端正确接收节。

  2. 现在我发送到裸 JID(不提供资源),另一个设置另一个资源:

ejabberdctl send_stanza aaa@localhost user1@localhost “...”

ejabberdctl send_stanza aaa@localhost user1@localhost/sdsd “...”

  1. 在这些情况下,客户端都不会收到它们,因为资源不匹配,而且它的优先级为负。我可以看到那些离线存储在数据库中的消息。

在您的客户端中,也许您必须添加另一个调用以设置在线状态,并具有积极的优先级。

【讨论】:

  • 谢谢@Badlop,我会试一试。我通过发送这样的不存在的消息类型(大声笑)尝试了另一个实验 - ejabberdctl send_message lol sender@my.domain receiver@my.domain "mesage" "Hello world" 并且 smack 库抛出错误。至少,现在我们知道消息确实到达了 Android 客户端,但 smack 库没有(/无法)处理它们。 java.lang.IllegalArgumentException: No enum constant org.jivesoftware.smack.packet.Message.Type.lol at org.jivesoftware.smack.packet.Message$Type.valueOf(Message.java:668)
  • 嗨@Badlop,我尝试了很多东西,最后,send_stanza API 调用有效。因此,我没有使用 send_message API 调用,而是使用 send_stanza;将消息放入节中,客户端应用程序收到消息。谢谢。
猜你喜欢
  • 1970-01-01
  • 2013-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-09
  • 2012-04-06
相关资源
最近更新 更多