I want send composing event in Group (Multiuser) chat in xmpp, I am using asmack library, I have done same functionality with One to One chat.
I am using below code:
mMessageEventManager = new MessageEventManager(XMPPConnectApplication.getInstance().getXmppConnection());
mMessageEventManager.addMessageEventNotificationListener(new MessageEventNotificationListener() {
@Override
public void offlineNotification(String arg0, String arg1) {
}
@Override
public void displayedNotification(String arg0, String arg1) {
}
@Override
public void deliveredNotification(String arg0, String arg1) {
}
@Override
public void composingNotification(String from, String to) {
Log.e("Receiver-composingNotification",from + " is started typing......"+to);
}
@Override
public void cancelledNotification(String from, String to) {
Log.e("Receiver-cancelledNotification",from + " is stopped typing......"+to);
}
});
Please let me know if you have any idea for the same.
Any help will be appreciated.
Yes, I have idea about it and I have done just before 1 week.
I have used MessageEventManager to manage Chat States.
private MessageEventManager mMessageEventManager;
Add this method for Chat State Receiving Listener:
private void chatStateRecognizer(){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
mMessageEventManager = new MessageEventManager(mXmppConnection);
mMessageEventManager.addMessageEventNotificationListener(new MessageEventNotificationListener() {
@Override
public void offlineNotification(String arg0, String arg1) {
}
@Override
public void displayedNotification(String arg0, String arg1) {
}
@Override
public void deliveredNotification(String from, String arg1) {
}
@Override
public void composingNotification(String from, String to) {
Log.i("Receiver:Compose state",from + " is started typing......"+to);
}
@Override
public void cancelledNotification(String from, String to) {
Log.i("Receiver:Stop state",from + " is stopped typing......"+to);
}
});
}
});
thread.start();
}
Create one Model class name with GroupInfoModel.java:
public class GroupInfoModel implements Comparable<GroupInfoModel>, Serializable{
private static final long serialVersionUID = 1L;
private String memberId = "", memberName = "";
private boolean isAdmin;
public String getMemberId() {
return memberId;
}
public void setMemberId(String memberId) {
this.memberId = memberId;
}
public String getMemberName() {
return memberName;
}
public void setMemberName(String memberName) {
this.memberName = memberName;
}
public boolean isAdmin() {
return isAdmin;
}
public void setAdmin(boolean isAdmin) {
this.isAdmin = isAdmin;
}
@Override
public int compareTo(GroupInfoModel another) {
return getMemberName().compareTo(another.getMemberName());
}
}
Now take ArrayList of GroupInfoModel.java class:
private ArrayList<GroupInfoModel> groupDetailsList = new ArrayList<GroupInfoModel>();
private boolean isComposingStarted;
on onCreate() of Activity / Fragment:
groupDetailsList.clear();
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(mXmppConnection);
DiscoverItems items = discoManager.discoverItems(mRoomId);
for (Iterator<Item> it = items.getItems(); it.hasNext();) {
DiscoverItems.Item item = (DiscoverItems.Item) it.next();
String occupant = item.getEntityID();
occupant = occupant.split("/")[1];
GroupInfoModel groupInfoModel = new GroupInfoModel();
groupInfoModel.setAdmin(false);
groupInfoModel.setMemberId(occupant+"@"+mServiceNameHere);
groupInfoModel.setMemberName(occupant);
groupDetailsList.add(groupInfoModel);
}
Now add TextWatcher on your EditText of Compose Message (Chat view) screen:
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(s.toString().length()==1&&!isComposingStarted){
isComposingStarted = true;
if(chatType.equals("OneToOneChat")){
mMessageEventManager.sendComposingNotification(myJabberId, friendJabberId);
}else if(chatType.equals("GroupChat")){
for (int i = 0; i < groupDetailsList.size(); i++) {
if(!groupDetailsList.get(i).getMemberId().contains(myJabberId)){
mMessageEventManager.sendComposingNotification(groupDetailsList.get(i).getMemberId(), roomId);
}
}
}
}else if(s.toString().length()==0){
isComposingStarted = false;
if(chatType.equals("OneToOneChat")){
mMessageEventManager.sendCancelledNotification(myJabberId, friendJabberId);
}else if(chatType.equals("GroupChat")){
for (int i = 0; i < groupDetailsList.size(); i++) {
if(!groupDetailsList.get(i).getMemberId().contains(myJabberId)){
mMessageEventManager.sendCancelledNotification(groupDetailsList.get(i).getMemberId(), roomId);
}
}
}
}
}
I strongly recommended that use above code in Application class, you can modify methods as your requirements.
Done.
// send multi user chat typing status
public static void sendMUCTypingStatus(ChatState state)
{
// check if you are connected to group
if(multiUserChat != null)
{
try{
// create packet
Message statusPacket = new Message();
// set body to null
statusPacket.setBody(null);
// set packet type to group chat
statusPacket.setType(Message.Type.groupchat);
// set subject to null
statusPacket.setSubject(null);
// set to the group name
statusPacket.setTo(multiUserChat.getRoom());
// set from my current jis example : me@domain.com
statusPacket.setFrom(new MyPrefrence(XmppBase.context).getUsername());
// get the chat state extension and pass our state
ChatStateExtension extension = new ChatStateExtension(state);
// add the extention to our packet
statusPacket.addExtension(extension);
// get the connection and send the packet
Utils.getConnection().sendStanza(statusPacket);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
}
}
Usage :
sendMucTypingStatus(ChatState.composing);
watch this : Quick overview of using
With RxJava and Jake Wharton's RxBinding, it's quite simple to do:
RxTextView.afterTextChangeEvents(editText)
.observeOn(Schedulers.io())
.skip(1)
.map({ input ->
// FIRE ChatState.composing EVENT HERE
input // just returning the argument here
})
.debounce(2, TimeUnit.SECONDS)
.observeOn(Schedulers.io())
.subscribe {
// FIRE ChatState.active EVENT HERE
}
Remember that we will have to write code to catch these events via smack stanzaListener and display it on the UI accordingly!
Code is written in Kotlin, but it is fairly straight forward.