This is a general answer, there might be better ones, but this works for sure, it might contain stuff you already know, but I guess it can't hurt.
Base assumption - composing
messages are messages where the body is null, and the xml of the whole message contains a ChatState
tag with one of active, composing, paused, inactive, gone
values, and what you're looking for is composing
, and it's counterpart, paused
.
That being said, on the receiving component you need something like this (modify it to your needs):
yourComponent.addMessageListener(new PacketListener()
{
@Override
public void processPacket(Packet packet) throws NotConnectedException
{
try
{
Message msg = (Message) packet;
String msg_xml = msg.toXML().toString();
if (null != msg.getBody())
{
//handle as a regular chat message....
}
else
{
if (msg_xml.contains(ChatState.composing.toString()))
{
//handle is-typing, probably some indication on screen
}
else if (msg_xml.contains(ChatState.paused.toString()))
{
// handle "stopped typing"
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
EDIT:
Your log message shows you got an inactive
message, so for starters, try filtering all the messages, and find the pattern of what your looking for, to see if the sending side is even sending what you need.
A good way to understand would be to use another client that you know for a fact that's sending the composing state, and see what you get in your filter (e.g. under linux you could use pidgin or empathy for the sending side).
EDIT 2:
As per requested, I'm also adding some of the sending-side components for a more complete picture, again, this is a general example for reference purpose, and could be optimized and changed.
First, implement a custom EditText that implements a TextWatcher with a small thread that fires with the delay you want from the last text change to say "I stopped typing", set your interval as you want:
public class MyIsTypingEditText extends EditText implements TextWatcher
{
private static final int TypingInterval = 800;
//your listener interface that you implement anonymously from the Activity
public interface OnTypingModified
{
public void onIsTypingModified(EditText view, boolean isTyping);
}
private OnTypingModified typingChangedListener;
//members you would need for the small thread that declares that you have stopped typing
private boolean currentTypingState = false;
private Handler handler = new Handler();
private Runnable stoppedTypingNotifier = new Runnable()
{
@Override
public void run()
{
//part A of the magic...
if(null != typingChangedListener)
{
typingChangedListener.onIsTypingModified(MyIsTypingEditText.this, false);
currentTypingState = false;
}
}
};
public MyIsTypingEditText(Context context)
{
super(context);
this.addTextChangedListener(this);
}
public void setOnTypingModified(OnTypingModified typingChangedListener)
{
this.typingChangedListener = typingChangedListener;
}
@Override
public void afterTextChanged(Editable s)
{
//part B of the magic...
if(null != typingChangedListener)
{
if(!currentTypingState)
{
typingChangedListener.onIsTypingModified(this, true);
currentTypingState = true;
}
handler.removeCallbacks(stoppedTypingNotifier);
handler.postDelayed(stoppedTypingNotifier, TypingInterval);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
@Override
public void onTextChanged(CharSequence text, int start, int before, int after) { }
}
Next, in the activity that handles your chat, add a new anonymous interface and implement it's callback with your state-changing-message sending method call, this part C of the magic, as this will send your state corresponding to the TextWatcher mini-thread:
yourIsTypingEditText.setOnTypingModified(new MyIsTypingEditText.OnTypingModified()
{
@Override
public void onIsTypingModified(EditText view, boolean isTyping)
{
XmppConnectionClass.Composing composing = (isTyping) ? XmppConnectionClass.Composing.isTyping : XmppConnectionClass.Composing.stoppedTyping;
XmppConnectionClass.getInstance().sendIsComposing(composing);
}
});
And last but not least, in your connection handler class you should have the following:
//.... other stuff
//a mini enum Composing class for state setting
public enum Composing
{
private ChatState state;
Composing(ChatState state)
{
this.state = state;
}
isTyping(ChatState.composing), stoppedTyping(ChatState.paused);
public ChatState getState()
{
return (state);
}
}
//.... other stuff
public boolean sendIsComposing(Composing composing)
{
try
{
Message msg = new Message(...);
//other stuff...
msg.setBody(null);
msg.addExtension(new ChatStateExtension(composing.getState()));
//other stuff...
this.sendMessage(msg);
return (true);
}
catch (Exception e)
{
e.printStackTrace();
return (false);
}
}
Hope this Helps.