我该如何利用Smack与XMPP XEP-0184“消息传递回执”进行通信?

7

你好,有没有一种方法可以创建一个 Android XMPP 客户端,使其能够接收消息确认(XEP-0184)?我了解到 Smack 中有 XEP-0184,但是普通的 Smack 在 Android 上无法使用(或者我不知道如何使用它),总是会出现 SASL 认证异常。

2个回答

15

Smack已经支持XEP-0184,具体信息可以查看SMACK-331。在Android平台上,你不能直接使用Smack低于4.1的版本,需要使用Smack 4.1或更高版本。

关于Smack的XEP-0184 API,可以在DeliveryReceiptManager的javadoc文档中阅读更多信息。


当我使用asmack时,我没有像xabber这样的程序中看到消息确认。我应该在asmack中启用xep-0184吗?如果是的话,请告诉我如何做,因为我找不到它。 - Mathew1990
我已经添加了一个Javadoc链接。 - Flow
2
现在它运行得很好,但我不得不手动发送确认,就像这样: Packet received = new Message(); received.addExtension(new DeliveryReceipt(packet.getPacketID())); received.setTo(packet.getFrom()); connection.sendPacket(received);我真的不知道为什么DeliveryReceiptManager无法检测到xml传递回执请求。DeliveryReceiptManager.hasDeliveryReceiptRequest(packet)返回false。 - Mathew1990
5
为了启用自动发送回执功能,您需要在连接登录后立即调用以下代码:DeliveryReceiptManager.getInstanceFor(mXMPPConnection).enableAutoReceipts(); - 这也将确保已创建并绑定到连接的管理器。 - ge0rg
尝试使用以下代码:DeliveryReceiptManager.getInstanceFor(connection).autoAddDeliveryReceiptRequests(); - Ivan Morgillo
@Flow 当我尝试发送多条消息时,有些消息没有收到送达回执,请问你能建议一种处理方式吗? - Sarthak Mittal

12

是的,这适用于普通的Smack。

Gradle依赖项

compile "org.igniterealtime.smack:smack-android:4.1.0"
compile "org.igniterealtime.smack:smack-tcp:4.1.0"
compile "org.igniterealtime.smack:smack-extensions:4.1.0" // <-- XEP-0184 classes

在连接之前先准备XMPPTCPConnection,即wire up a handler for when you get a delivery receipt

DeliveryReceiptManager.getInstanceFor(mConnection).addReceiptReceivedListener(new ReceiptReceivedListener() {
        @Override
        public void onReceiptReceived(String fromJid, String toJid, String deliveryReceiptId, Stanza stanza) {
            Log.d(TAG, "onReceiptReceived: from: " + fromJid + " to: " + toJid + " deliveryReceiptId: " + deliveryReceiptId + " stanza: " + stanza);
        }
    }); 

发送消息时,请确保包含MessageReceiptRequest

Chat chat;
if (StringUtils.isNullOrEmpty(threadId)) {
    chat = getChatManager().createChat(to);
    Log.d(TAG, "sendMessage: no thread id so created Chat with id: " + chat.getThreadID());
} else {
    chat = getChatManager().getThreadChat(threadId);
    Log.d(TAG, "sendMessage: thread id was used to continue this chat");
}
Message message = new Message(to);
message.addBody("EN", messageText);
String deliveryReceiptId = DeliveryReceiptRequest.addTo(message);
chat.sendMessage(message);
Log.d(TAG, "sendMessage: deliveryReceiptId for this message is: " + deliveryReceiptId);

全部完成

现在,您可以通过上面的 Chat.sendMessage(Message) 代码中获得的 deliveryReceiptId 在之前设置的 onReceiptReceived 回调中记录,从而知道对方已经收到了发送的消息。


通过删除冗余调用,修复了问题:DeliveryReceiptManager.getInstanceFor(mConnection).autoAddDeliveryReceiptRequests(); - fr1550n
1
你为什么只删了一行代码,而不是多删几行呢? - Flow
1
不是的,autoAddDeliveryReceiptRequest() 正是这样做的:它会自动将递送回执请求添加到每个发送的消息数据包中。然后您可以使用 DeliveryReceiptManager.addReceiptReceivedListener(ReceiptReceivedListener) 来获取已接收回执的回调。 - Flow
@fr1550n,你是否使用DeliveryReceiptManager获得了服务器的确认? - Radhey
一个使用DeliveryReceiptRequest.addTo的原因是,如果我不想接收某些消息类型(例如普通消息类型)的回执。非常感谢您的贡献@Flow。 - Shubham AgaRwal
显示剩余3条评论

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