How to implement message read status like whatsapp blue tick mark?
Asked Answered
U

3

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.

Upthrow answered 11/3, 2015 at 18:28 Comment(0)
S
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);
Sidedress answered 12/3, 2015 at 4:2 Comment(27)
Hi Rakesh, i'm trying to implement your code. My messages are sending but not receiving by recipient.Beckmann
What is mConnection.sendPacket(sendReadStatus) ?Beckmann
it's xmpp connection object.Sidedress
It should be message object in sendPacket() isn't it ?Beckmann
hi @SRK ... where to add Message message = new Message(userJid); ReadReceipt read = new ReadReceipt(messagePacketID); message.addExtension(read); mConnection.sendPacket(sendReadStatus);Sublimity
@BMM, when u enter the user chat list activity.!Sidedress
@SRK can you please tell me what is sendReadStatus ?Roca
@chhameed, it is message packet object used for notifying message read status with.Sidedress
okay one more Question! when i implemented it says "ReadReceiptReceivedListener cannot be resolved to a type" where is ReadReceiptReceivedListener defined ?Roca
ReadReceiptReceivedListener is custom custom class of packet listener it receives read status.Sidedress
I used this example in my connection, the strange behaviour is, by adding this listener, I am not able to send a message anymore, but I can receive messages. Anybody has an idea what causes this behaviour? Maybe the ProviderManager?Looseleaf
not at the moment, not at home. But I just setting up a simple XMPP Connection with smack and use ChatManager to send messages. As soon as I add the ReceiptReceivedListener to the connection, I can get messages but not send. The strange thing is, the listener works. I can send the custom stanza that the message is read. But no usual message anymore....Looseleaf
My assumption is, that with adding ProviderManager extension provider like in Your example, it must overwrite something in the settings. I give it a try if I am at home and check what´s wrong. If it is not a mistake by myself, I will post how to avoid the problem.Looseleaf
Actually read status can be optimized since you don't need to send message for each receipt unlike delivery and send. there is no network call between read and delivery so just send it for the latest received message.Lecky
Hi @RakeshKalashetti.. I have done this successfully with asmack..But now I want to do it using SMACK..How to do it ???Sublimity
@Sublimity No difference between SMACK and ASMACK, some library added to the SMACK because of that support to AndroidSidedress
@RakeshKalashetti..yes.. Everything same but I am getting ClassCasteException at ReadReceipt dr = (ReadReceipt) packet.getExtension(ReadReceipt.ELEMENT, ReadReceipt.NAMESPACE); My ReadReceipt class implements ExtensionElement..and packet.getExtension(ReadReceipt.ELEMENT, ReadReceipt.NAMESPACE) returns DefaultExtensionElement.. So I am getting ClassCasteExceptionSublimity
and it doesn't allow type casting also.Sublimity
@Rakesh addPacketListener is deprecated so i am not getting any packets? any solution?Weatherbound
@mohit use addStazaListener instead of addPacketListener.Sidedress
addStazaListener is not coming can i use addStanzaAcknowledgedListener?Weatherbound
I am using smack 4.1Weatherbound
Use addAsyncStanzaListener to recieveSidedress
Have u adding this listener to xmpp connection class?Sidedress
@RakeshKalashetti I am having some trouble in understanding xmpp . can you help ?Theodoretheodoric
@ADM can you share your problem?Sidedress
Ok, no problem after some time I'll availableSidedress
O
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

Oersted answered 12/3, 2015 at 17:50 Comment(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).Valera
N
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.

Novelistic answered 11/3, 2015 at 18:41 Comment(4)
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.Upthrow
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.Novelistic
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.Straight
I agree with Robin, this is what I meant.Novelistic

© 2022 - 2024 — McMap. All rights reserved.