通过透传消息实现输入指示器

大约 2 分钟

通过透传消息实现输入指示器

输入指示器显示其他用户何时输入消息。通过该功能,用户之间可进行有效沟通,增加了用户对聊天应用中交互的期待感。

前提条件

开始前,请确保满足以下条件:

实现过程

你可以通过透传消息实现输入指示器。下图为输入指示器的工作原理。

img

监听用户 A 的输入状态。一旦有文本输入,通过透传消息将输入状态发送给用户 B,用户 B 收到该消息,了解到用户 A 正在输入文本。

  • 用户 A 向用户 B 发送消息,通知其开始输入文本。
  • 收到消息后,如果用户 B 与用户 A 的聊天页面处于打开状态,则显示用户 A 的输入指示器。
  • 如果用户 B 在几秒后未收到用户 A 的输入,则自动取消输入指示器。

提示

输入状态属于瞬时状态,建议设置发送间隔,避免在每次文本变化时都发送消息。接收方在一段时间内未再次收到输入状态时,应自动隐藏输入指示器。

发送输入状态的透传消息

以下示例代码展示如何发送输入状态的透传消息。

//发送表示正在输入的透传消息
private static final String MSG_TYPING_BEGIN = "TypingBegin";
private long previousChangedTimeStamp;
// 示例间隔为 5 秒,业务侧可根据交互体验调整。
private static final long TYPING_SEND_INTERVAL = 5_000L;

private void textChange() {
    long currentTimestamp = System.currentTimeMillis();
    if (currentTimestamp - previousChangedTimeStamp >= TYPING_SEND_INTERVAL) {
        sendBeginTyping();
        previousChangedTimeStamp = currentTimestamp;
    }
}

private void sendBeginTyping() {
    EMMessage beginMsg = EMMessage.createSendMessage(EMMessage.Type.CMD);
    EMCmdMessageBody body = new EMCmdMessageBody(MSG_TYPING_BEGIN);
    // 接收方离线时丢弃该瞬时状态消息。
    body.deliverOnlineOnly(true);
    beginMsg.addBody(body);
    beginMsg.setTo(toChatUsername);
    EMClient.getInstance().chatManager().sendMessage(beginMsg);
}

接收和解析输入状态的透传消息

以下示例代码展示如何接收和解析输入状态的透传消息。

private static final int TYPING_SHOW_TIME = 10000;
private static final int MSG_TYPING_END = 1;
private Handler typingHandler;

private void initTypingHandler() {
    typingHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case MSG_TYPING_END :
                    cancelTimer();
                    break;
            }
        }
    };
}

@Override
public void onCmdMessageReceived(List<EMMessage> messages) {
    for (EMMessage msg : messages) {
        if (!TextUtils.equals(msg.conversationId(), currentConversationId)) {
            continue;
        }
        EMCmdMessageBody body = (EMCmdMessageBody) msg.getBody();
        if(TextUtils.equals(body.action(), MSG_TYPING_BEGIN)) {
            // 这里需更新 UI,显示“对方正在输入”
            beginTimer();
        }
    }
}

private void beginTimer() {
    if(typingHandler != null) {
        typingHandler.removeMessages(MSG_TYPING_END);
        typingHandler.sendEmptyMessageDelayed(MSG_TYPING_END, TYPING_SHOW_TIME);
    }
}

private void cancelTimer() {
    // 这里需更新 UI,不再显示“对方正在输入”
    if(typingHandler != null) {
        typingHandler.removeCallbacksAndMessages(null);
    }
}

上次编辑于: