如何使用 Smack 在 XMPP openfire 中了解打字状态

Posted

技术标签:

【中文标题】如何使用 Smack 在 XMPP openfire 中了解打字状态【英文标题】:How to know Typing Status in XMPP openfire using Smack 【发布时间】:2013-08-26 04:18:24 【问题描述】:

我正在使用 Openfire XMPP 服务器开发聊天应用程序。我可以在两个用户之间进行文字聊天。但是我想知道有人在输入消息时的输入状态。所以我创建了一个类:-

public class typingStatus implements ChatStateListener 

    @Override
    public void processMessage(Chat arg0, Message arg1) 
        // TODO Auto-generated method stub

    

    @Override
    public void stateChanged(Chat arg0, ChatState arg1) 
        // TODO Auto-generated method stub
        System.out.println(arg0.getParticipant() + " is " + arg1.name());

    


但我很困惑,所以它将如何工作?我知道我需要一个可以在侦听器中使用的数据包。但是我找不到那个包。

请任何人建议,它将如何工作?

还有 Smack 和 asmack 有什么区别?

谢谢!

【问题讨论】:

请在 *** 中检查这个问题:***.com/questions/21154833/… 【参考方案1】:

要启用ChatStateListener,您需要创建一个自定义MessageListener

public class MessageListenerImpl implements MessageListener,ChatStateListener  

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

    

    @Override
    public void stateChanged(Chat arg0, ChatState arg1) 
        if (ChatState.composing.equals(arg1)) 
            Log.d("Chat State",arg0.getParticipant() + " is typing..");
         else if (ChatState.gone.equals(arg1)) 
            Log.d("Chat State",arg0.getParticipant() + " has left the conversation.");
         else 
            Log.d("Chat State",arg0.getParticipant() + ": " + arg1.name());
        

    


然后你创建MessageListener 对象

MessageListener messageListener = new MessageListenerImpl();

然后在创建聊天方法中传递这个

Chat newChat = chatmanager.createChat(jabber_id_of_friend, messageListener);

Smack 和 asmack 有什么区别? Check This

【讨论】:

谢谢你。看起来不错,给了我解决方案。我会检查的。 no userID 是其他参与者的 jid,而不是登录者 谢谢你。如果你有一点时间。也请检查***.com/questions/18437329/… 要处理消息事件,请查看igniterealtime.org/builds/smack/docs/latest/documentation/… 我检查了但没有得到 stateChanged。请建议【参考方案2】:

我终于找到了解决方案。我需要使用聊天监听器和聊天管理器,还需要使用内置的 sendcomposingnotification 功能。无需为此使用 Messageeventrequestlistener 接口或任何其他自定义类。我添加了以下几行,

connection.getChatManager().addChatListener(new ChatManagerListener() 

            @Override
            public void chatCreated(final Chat arg0, final boolean arg1) 
                // TODO Auto-generated method stub

                arg0.addMessageListener(new MessageListener()
                

                    @Override
                    public void processMessage(Chat arg0, Message arg1) 
                    
                        // TODO Auto-generated method stub

                        Log.d("TYpe Stat",title[0] + " is typing......");
                        Toast.makeText(getApplicationContext(),title[0] + " is typing......",Toast.LENGTH_SHORT).show();
                    



                    
                ); 
            
        );

还需要像这样发送通知..

mem.sendComposingNotification(etRecipient.getText().toString(), message.getPacketID());
        System.out.println("Sending notification");

其中 mem 是 MessageEventManger 的类型。 参考:http://www.igniterealtime.org/builds/smack/docs/latest/javadoc/org/jivesoftware/smackx/MessageEventManager.html

【讨论】:

嗨,我在上面试过了..但没有用!这是我的代码!任何帮助将不胜感激....... Message msg1 = new Message(to, Message.Type.chat); msg1.setFrom("user1@192.168.0.98"); // 我的 id MessageEventManager event=new MessageEventManager(connection); //recipient id event.sendComposingNotification("tech1@192.168.0.98",msg1.getPacketId()); @Aneez,您需要处理在processMessage() 中收到的消息,因为它接收所有传入的数据包,而不仅仅是typing 状态。它可能是暂停,离线/在线状态包,或消息..所以尝试处理它然后处理.. 嗨。我尝试了同样的方法,但它对我不起作用..它既不发送组合通知也不接收它。在接收和从 ios 接收时给我 null。帮我找出来。谢谢。 仅供参考:从***.com/questions/21154833/…合并【参考方案3】:
ChatManager chatManager = ChatManager.getInstanceFor(connection);
Chat chat= chatManager.createChat(to, new ChatStateListener() 
      @Override
      public void stateChanged(Chat chat, ChatState state) 
                switch (state)
                        case active:
                             Log.d("state","active");
                             break;
                        case composing:
                             Log.d("state","composing");
                             break;
                        case paused:
                             Log.d("state","paused");
                             break;
                        case inactive:
                             Log.d("state","inactive");
                             break;
                        case gone:
                             Log.d("state","gone");
                             break;
                 
        

        @Override
        public void processMessage(Chat chat, Message message) 
               Log.d("processMessage","processMessage");
        
);

使用此代码。希望如此工作

【讨论】:

你好,Ahesanali Momin,你能告诉我你最后的确切情况吗?你在 XMPP 中遇到了什么样的错误。欲了解更多信息,请通过 skype@piyush.gupta326 给我发消息。然后我们可以讨论更多,你的问题,希望能达到成功点。 我没有收到任何错误,但是当我开始打字时,代码没有进入任何状态,我的意思是 stateChangeListener 没有被调用。 嘿伙计,你读过这个文档xmpp.org/extensions/xep-0085.html 这完全是理论上的,目前还没有什么有趣的,因为使用聊天客户端大部分事情都很清楚。 我的意思是,请阅读该链接中的文档。我希望你能在那里找到解决方案。否则我们可以在这里讨论。【参考方案4】:

我正在使用聊天状态监听器:

Chat chat = chatManager.createChat(jid,
                        new ChatStateChangedListener());

将 chatstatelistener 与上面的每个 jid 绑定,然后:

public class ChatStateChangedListener implements ChatStateListener 

    public ChatStateChangedListener() 
        printLog("Chat State Changed Listner Constructor");
    

    @Override
    public void processMessage(Chat arg0, Message arg1) 

    


    @Override
    public void stateChanged(Chat chat, ChatState state) 

        if (state.toString().equals(ChatState.composing.toString())) 
                tvLastSeen.setText("Typing...");
             else if (state.toString().equals(ChatState.paused.toString())) 
                tvLastSeen.setText("paused...");
             else 
                tvLastSeen.setText("nothing");
            

        


    


【讨论】:

仅供参考:从***.com/questions/21154833/…合并【参考方案5】:

在 MMessageListener 类上创建以侦听传入消息

私有类MMessageListener实现MessageListener、ChatStateListener

    public MMessageListener(Context contxt) 
    


    @Override
    public void stateChanged(Chat chat, ChatState chatState) 

        mStatus = "Online";

        if (ChatState.composing.equals(chatState)) 

            mStatus = chat.getParticipant() + " is typing..";
            Log.d("Chat State", chat.getParticipant() + " is typing..");
         else if (ChatState.gone.equals(chatState)) 
            Log.d("Chat State", chat.getParticipant() + " has left the conversation.");
            mStatus = chat.getParticipant() + " has left the conversation.";
         else if (ChatState.paused.equals(chatState))
            Log.d("Chat State", chat.getParticipant() + ": " + chatState.name());
            mStatus = "Paused";
        else if (ChatState.active.equals(chatState))
            mStatus = "Online";
        

        // do whatever you want to do once you receive status


    


    @Override
    public void processMessage(Message message) 

    

    @Override
    public void processMessage(Chat chat, Message message) 


    

将侦听器添加到您的聊天对象

Chat Mychat = ChatManager.getInstanceFor(connection).createChat( "user2@localhost"), mMessageListener);

在编辑文本文本更改时向接收用户发送状态

ChatStateManager.getInstance(connection).setCurrentState(ChatState.composing, Mychat);

这对我来说很好。

【讨论】:

嗨,Dharmesh,我也做了同样的事情,但是在 processMessage 中编写状态消息时我总是得到空值。我的 EditText 文本更改方法是:newChat = chatmanager.createChat(send_to, messageListener); Message msg = new Message(send_to, Message.Type.chat); msg.setFrom(USERNAME_LOGIN+"@"+HOST_NAME); // 我的 id newChat.sendMessage(msg); ChatStateManager.getInstance(connection).setCurrentState(ChatState.composing, newChat);这也不会将状态发送给其他人。 仅供参考:从***.com/questions/21154833/…合并 如何检查用户是否已暂停或不再在编辑文本中输入?【参考方案6】:

您或您使用的其他 xmpp 客户端应该发送聊天状态,以便您可以捕获状态。

像这样;

try 
      ChatStateManager.getInstance(GlobalVariables.xmppManager.connection).setCurrentState(ChatState.composing, chat);
     catch (XMPPException e) 
        e.printStackTrace();
    

try 
        ChatStateManager.getInstance(GlobalVariables.xmppManager.connection).setCurrentState(ChatState.gone, chat);
     catch (XMPPException e) 
        e.printStackTrace();
    

【讨论】:

也许你的服务器应用程序不支持它。 你的意思是说我们的服务器没有为此配置?但它在 ios 到 ios 上运行良好。我在 EditText 的 textChangeListner 上写下这一行。聊天对象是 chatmanager = connection.getChatManager();聊天聊天 = chatmanager.createChat("user@", listner);即使当我从 ios processMessage 收到撰写状态时,也会给我 null。请帮助我找到发送和接收的解决方案。附:我正在使用 asmack 库 仅供参考:从***.com/questions/22225394/…合并 这需要在editext text text change listener上完成。对吧?【参考方案7】:

但是,您也可以从 ProcessPacket 获取它。 在那里你会得到一个 Message 对象,你可以从那里提取 xml 部分并处理它们是否包含特定的聊天状态。

    Message message = (Message) packet;
    String msg_xml = message.toXML().toString();

    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"
     else 
       // normal msg
    

现在按您的要求处理。

【讨论】:

【参考方案8】:

只需在 ChatManager 后添加 ChatStateManager 即可:

chatManager =  ChatManager.getInstanceFor(getXmpptcpConnection());
ChatStateManager.getInstance(getXmpptcpConnection());

那你需要在createChat(to,chatMesageListener)期间加上ChatStateListener

chatManager.createChat(message.getTo(), chatMessageListener).sendMessage(message);

private ChatStateListener chatMessageListener = new ChatStateListener() 

    @Override
    public void stateChanged(Chat chat, ChatState state) 
        //State Change composing,active,paused,gone,etc
        Log.d(TAG, "ChatStateListener:::stateChanged -> " + chat.toString() + " \n -> " + state.toString());
    

    @Override
    public void processMessage(Chat chat, Message message) 
        //Incoming Message
        Log.d(TAG, "ChatStateListener:::processMessage -> " + chat.toString() + " \n -> " + message.toString());
    
;

【讨论】:

仅供参考:从***.com/questions/22225394/…合并 下一次,也许只回答一个问题并标记其余问题,让我们知道它们是重复的;发布相同的答案 7 次实在是太过分了。

以上是关于如何使用 Smack 在 XMPP openfire 中了解打字状态的主要内容,如果未能解决你的问题,请参考以下文章

使用 xmpp + smack + openfire 在 android 中阻止用户

我在使用 smack 4.2 Openfire 创建 XMPP 客户端时遇到问题

使用 Openfire 服务器和 XMPP(SMACK)客户端的 Android 聊天应用程序 [关闭]

Android 基于XMPP Smack openfire 开发的聊天室

Android基于XMPP Smack Openfire下学习开发IM连接断开重连

Android基于XMPP Smack及Openfire学习笔记