12

I am developing one application in that chatting is one module, for chatting i am using xmpp. when i am sending message i am getting that message delivery status using DeliveryReceiptManager.

DeliveryReceiptManager.getInstanceFor(connection).enableAutoReceipts();
DeliveryReceiptManager.getInstanceFor(connection).addReceiptReceivedListener(new ReceiptReceivedListener()
{
        @Override
        public void onReceiptReceived(String arg0, String arg1, String arg2)
        {
            Log.v("app", arg0 + ", " + arg1 + ", " + arg2);
        }
});

But i need to show that message is user READ or NOT like whatsApp blue tickmark, Can any one help me i am struck here. how to implement this message read concept.

Thanks in advance.

Flow
  • 23,572
  • 15
  • 99
  • 156
NareshRavva
  • 823
  • 3
  • 21
  • 50

3 Answers3

22

create custom packet extension class

public class ReadReceipt implements PacketExtension
{

public static final String NAMESPACE = "urn:xmpp:read";
public static final String ELEMENT = "read";

private String id; /// original ID of the delivered message

public ReadReceipt(String id)
{
    this.id = id;
}

public String getId()
{
    return id;
}

@Override
public String getElementName()
{
    return ELEMENT;
}

@Override
public String getNamespace()
{
    return NAMESPACE;
}

@Override
public String toXML()
{
    return "<read xmlns='" + NAMESPACE + "' id='" + id + "'/>";
}

public static class Provider extends EmbeddedExtensionProvider
{
    @Override
    protected PacketExtension createReturnExtension(String currentElement, String currentNamespace,
            Map<String, String> attributeMap, List<? extends PacketExtension> content)
    {
        return new ReadReceipt(attributeMap.get("id"));
    }
}
}

when enters the chat list send message tag with same packet id like this

Message message = new Message(userJid);
ReadReceipt read = new ReadReceipt(messagePacketID);
message.addExtension(read);
mConnection.sendPacket(sendReadStatus);

where mConnection is xmmppConnection object

add packet extension to message object

add this extension provider to ProviderManager before connecting to server

ProviderManager.getInstance().addExtensionProvider(ReadReceipt.ELEMENT, ReadReceipt.NAMESPACE, new ReadReceipt.Provider());

create packetListener class to receive read receipt from receiver

public class ReadReceiptManager implements PacketListener
    {



  private static Map<Connection, ReadReceiptManager> instances = Collections.synchronizedMap(new WeakHashMap<Connection, ReadReceiptManager>());
    static 
    {
        Connection.addConnectionCreationListener(new ConnectionCreationListener() 
        {
            public void connectionCreated(Connection connection) 
            {
                getInstanceFor(connection);
            }
        });
    }

private Set<ReceiptReceivedListener> receiptReceivedListeners = Collections.synchronizedSet(new HashSet<ReceiptReceivedListener>());

private ReadReceiptManager(Connection connection) 
{
    ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
    sdm.addFeature(ReadReceipt.NAMESPACE);
    instances.put(connection, this);

    connection.addPacketListener(this, new PacketExtensionFilter(ReadReceipt.NAMESPACE));
}

 public static synchronized ReadReceiptManager getInstanceFor(Connection connection) 
 {
    ReadReceiptManager receiptManager = instances.get(connection);

    if (receiptManager == null) 
    {
        receiptManager = new ReadReceiptManager(connection);
    }

    return receiptManager;
}

@Override
public void processPacket(Packet packet) 
{
    ReadReceipt dr = (ReadReceipt)packet.getExtension(ReadReceipt.ELEMENT, ReadReceipt.NAMESPACE);

    if (dr != null) 
    {
        for (ReceiptReceivedListener l : receiptReceivedListeners) 
        {
            l.onReceiptReceived(packet.getFrom(), packet.getTo(), dr.getId());
        }
    }
}

public void addReadReceivedListener(ReceiptReceivedListener listener) {
    receiptReceivedListeners.add(listener);
}

public void removeRemoveReceivedListener(ReceiptReceivedListener listener) {
    receiptReceivedListeners.remove(listener);
  }
 }

finally add listener to your xmpp connection object it works successfully

            ReadReceiptReceivedListener readListener = new ReadReceiptReceivedListener()
                {
                    @Override
                    public void onReceiptReceived(String fromJid, String toJid, String packetId) 
                    {
                        Log.i("Read", "Message Read Successfully");
                    }
                };  
                ReadReceiptManager.getInstanceFor(connection).addReadReceivedListener(readListener);
Opiatefuchs
  • 9,800
  • 2
  • 36
  • 49
Rakesh Kalashetti
  • 1,049
  • 8
  • 8
1

You need to implement displayed when message is seen, this is basic why how messaging apps implements typing, sent, delivered and seen status

http://xmpp.org/extensions/xep-0022.html#sect-idp643808

Jaspreet Chhabra
  • 1,431
  • 15
  • 23
  • 1
    xep-0022 has been obsoleted by the XMPP Standards Foundation. Implementation of the protocol described herein is not recommended. Developers desiring similar functionality are advised to implement the protocol that supersedes this on (XEP-0085, XEP-0184). – Shubham AgaRwal Feb 02 '18 at 06:06
0

Create a message with different attributes which indicate its a read receipt, which shall be sent when receiver reads the message. At the sender's end when you receive a message with read receipt attribute, then mark the message as read, as two blue ticks.

<message id='xxxxx' from='xxxxxxxx' to='xxxxxxxxx'>
<status_id>101</status_id>
</message>

Here status_id=101, I have used to send read receipt, which shall identify it at receiver end.

Iqbal S
  • 1,156
  • 10
  • 16
  • Message msg = new Message(); msg.setFrom(arg0); msg.setTo(arg0); msg.setPacketID(arg0) connection.sendPacket(msg); How to set status ID to this message there is no tag like status. – NareshRavva Mar 12 '15 at 05:07
  • You need to modify the message class to hold the status_id tag. You can add setters and getters for statusId in Message class. And modify the toXml() in Message class. And also modify the PacketParseUtils class to parse the status_id and set it to message status id by using the setter. And also when you are using in your code, use the setter for statusId and set it while sending read receipt. – Iqbal S Mar 12 '15 at 06:33
  • 1
    You don't modify the message class, you add an extension to it with your custom elements. Smack is designed to be extended in this way. – Robin Mar 12 '15 at 20:02
  • I agree with Robin, this is what I meant. – Iqbal S Mar 13 '15 at 05:00