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

9

我正在使用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的区别是什么?

谢谢!


请在Stackoverflow上查看此问题:http://stackoverflow.com/questions/21154833/how-to-get-typing-status-notification-in-xmpp - Aneez
8个回答

12
为了启用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有什么区别? <-- 查看这里


谢谢Sunil。看起来不错,给了我解决方案。我会检查的。 - user2160008
没有userID是另一个参与者的jid,而不是登录的用户。 - Sunil Mishra
谢谢Sunil。如果您有时间,请也检查一下http://stackoverflow.com/questions/18437329/how-to-know-message-send-status-not-send-delivery-read-like-as-whatsapp?noredirect=1#comment27090174_18437329 - user2160008
处理消息事件请查看此链接:http://www.igniterealtime.org/builds/smack/docs/latest/documentation/extensions/messageevents.html - Sunil Mishra
抱歉,我只是在使用这段代码。我认为应该使用focusonEditText,当用户输入时,它会发送一个组合状态。你有任何例子吗? - user2160008
显示剩余8条评论

4

最终我找到了解决方法。我需要同时使用聊天监听器和聊天管理器,并且还需要使用内置的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指的是MessageEventManager类型,参考链接: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"); // 我的IDMessageEventManager event=new MessageEventManager(connection); // 接收者ID event.sendComposingNotification("tech1@192.168.0.98",msg1.getPacketId()); - Mohit
@Aneez,你需要处理在 processMessage() 中接收到的消息,因为它接收所有传入的数据包,不仅仅是 typing 状态。它可能是暂停、离线/在线状态数据包或者消息...所以尝试处理它,然后再进行处理。 - Kamalakannan J
嗨。我尝试了相同的方法,但它对我没有用...它既没有发送ComposingNotification也没有接收到它。在接收时给我null,在从iOS接收时也是如此。 帮我找出原因。 谢谢。 - Kutbi
FYI:合并自http://stackoverflow.com/questions/21154833/how-to-get-typing-status-notification-in-xmpp - Shog9

2
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与我联系。然后我们可以进一步讨论你的问题,并希望能够达成成功点。 - John smith
嘿,伙计, 你看过这个文档了吗 http://xmpp.org/extensions/xep-0085.html - John smith
这完全是理论,目前并不有趣,因为大多数事情都可以通过聊天客户端来清楚地了解。 - Ahesanali Suthar
我的意思是,请阅读链接中的文档。我希望你能在那里找到解决方案。否则我们可以在这里讨论。 - John smith
发送消息时,我需要添加什么吗? - Ahesanali Suthar
显示剩余3条评论

1
创建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 中始终得到 null 的 composing state 消息。 我的 EditText 文本更改方法是: newChat = chatmanager.createChat(send_to, messageListener); Message msg = new Message(send_to, Message.Type.chat); msg.setFrom(USERNAME_LOGIN+"@"+HOST_NAME); // my id newChat.sendMessage(msg); ChatStateManager.getInstance(connection).setCurrentState(ChatState.composing, newChat); 而且这也无法将状态发送给其他人。 - Kutbi
FYI:合并自http://stackoverflow.com/questions/21154833/how-to-get-typing-status-notification-in-xmpp - Shog9
如何检查用户是否已暂停或不再在EditText中输入? - Kaveesh Kanwal

1
我正在使用聊天状态监听器:
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");
            }

        }


    }

}

FYI:合并自http://stackoverflow.com/questions/21154833/how-to-get-typing-status-notification-in-xmpp - Shog9

0

你使用的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();
    }

也许你的服务器应用程序不支持它。 - Savas Adar
你的意思是说我们的服务器没有配置这个功能?但它在 iOS 到 iOS 的情况下运行良好。 我正在 EditText 的 textChangeListner 中编写这一行。 聊天对象是 chatmanager = connection.getChatManager(); Chat chat = chatmanager.createChat("user@", listner); 即使我从 iOS 收到了 compose 状态,processMessage 也会返回 null。 请帮我找到发送和接收的解决方案。 P.S. 我正在使用 asmack 库。 - Kutbi
FYI:合并自http://stackoverflow.com/questions/22225394/how-to-get-the-typing-status-in-asmack-android - Shog9
这需要在EditText文本更改监听器上完成,对吗? - Kaveesh Kanwal

0

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

FYI:合并自http://stackoverflow.com/questions/22225394/how-to-get-the-typing-status-in-asmack-android - Shog9
下一次,也许只回答一个问题并标记其余的重复问题,让我们知道它们是重复的;发布7次相同的答案相当过度。 - Shog9

0

不过你也可以从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
    }

现在根据您的要求处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接