键入状态 Smack 4.1

Typing Status Smack 4.1

嘿,我正在尝试在其他人开始写作时获取键入状态,即使它正在返回一条带有状态的空消息作为消息,但它来自 proccessMessage 方法。它不应该在 stateChanged 中返回吗?我还没有启用任何 PacketProvider,我是否必须这样做才能在 stateChanged 方法中返回?如果有任何帮助,我将不胜感激。

   newChat = chatmanager.createChat(contactUsername + sc.DOMAIN, new ChatStateListener() {
        @Override
        public void stateChanged(Chat chat, ChatState state) {
            if (ChatState.composing.equals(state)) {
               Log.d("Chat State",chat.getParticipant() + " is typing..");
            } else if (ChatState.gone.equals(state)) {
               Log.d("Chat State",chat.getParticipant() + " has left the conversation.");
            } else {
             Log.d("Chat State",chat.getParticipant() + ": " + state.name());
            }
        }

        @Override
        public void processMessage(Chat chat, Message message) {
            System.out.println("Received message: " + message);
        }
   });

日志:

06-15 14:28:47.679    9949-9983/com.example.example I/System.out﹕ Received message: <message to='+931111111111@example.com' from='+930000000000@example.com/Spark 2.6.3' id='AUJG0-42' type='chat'><thread>097uC9</thread><inactive xmlns='http://jabber.org/protocol/chatstates'/></message>

这是一个笼统的答案,可能还有更好的答案,但这肯定有效,它可能包含您已经知道的内容,但我想它不会造成伤害。

基本假设 - composing 消息是正文为空的消息,并且整个消息的 xml 包含具有 active, composing, paused, inactive, gone 值之一的 ChatState 标记,而您要查找的是 composing,它的对应项是 paused.

也就是说,在 receiving 组件上你需要这样的东西(根据你的需要修改它):

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();
                    }
               }
            });

编辑:

您的日志消息显示您收到了一条 inactive 消息,因此对于初学者,请尝试过滤 所有 消息,并找到您要查找的内容的模式,以看看发送方是否发送了你需要的东西。

一个很好的理解方法是使用另一个你知道的客户端来发送组合状态,然后看看你在过滤器中得到了什么(例如,在 linux 下你可以使用 pidgin 或 empathy对于发送端)。

编辑 2:

根据要求,我还添加了一些发送方组件以获得更完整的图片,同样,这是一个通用示例,供参考,可以进行优化和更改。

首先,实现一个自定义 EditText,它实现了一个带有小线程的 TextWatcher,该线程以您想要的延迟从上次文本更改开始说 "I stopped typing",根据需要设置间隔:

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) { }

  }

接下来,在处理您的聊天的 activity 中,添加一个新的匿名接口并使用您的状态更改消息发送方法调用实现它的回调,这是神奇的 C 部分,因为这将发送TextWatcher 迷你线程对应的状态:

    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);
        }
    });

最后但同样重要的是,在您的连接处理程序中 class 您应该具有以下内容:

//.... 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);
    }
}

希望对您有所帮助。

对于查看用户聊天状态我有更好的实现思路

             if (packet instanceof Message) {
                Message message = (Message) packet;
                if (message.getBody() != null) {
                    processMessage(message);
                } else {
                    //process chat states here
                    processChatState(message);
                }
            }

processChatState的方法是

 private void processChatState(Message message) {
        ExtensionElement element = message.getExtension(ChatStateExtension.NAMESPACE);

        if (element != null) {
            switch (element.getElementName()) {
                case "composing":
                    updateStatusOfUser("typing...");
                    break;
                case "paused":
                    updateStatusOfUser("online");
                    break;
                case "active":
                    updateStatusOfUser("online");
                    break;
                case "inactive":
                    updateStatusOfUser("online");
                    break;
                case "gone":
                    updateStatusOfUser("online");
                    break;
            }
        }
    }