在即时通讯 IM 日益普及的今天,用户对隐私保护的需求催生了一种独特的消息模式——“阅后即焚”,其核心机制是通过自动销毁已读消息来实现隐私保护。它不仅在社交领域广泛应用,在金融、医疗、企业协作等对数据安全要求更高的场景中也发挥着重要作用。

本文将手把手教大家如何基于环信 IM SDK实现“阅后即焚“功能的开发。

技术原理

“阅后即焚”功能基于环信 SDK 的消息扩展机制和 已读回执功能实现,工作流程如下:
在这里插入图片描述

  1. 发送消息:用户 A 创建消息时,通过消息扩展字段添加阅后即焚标识,然后将消息发送给用户 B。

  2. 接收与删除消息:用户 B 收到消息后,解析消息扩展字段查看是否有阅后即焚标识。若有, 用户B查看消息后,发送已读回执且删除用户B该条消息。

  3. 发送方删除消息:用户 A 收到已读回执后,检查原消息是否带有阅后即焚标识。若是,删除用户 A 该条消息并更新显示。

实现过程

本节以Android端文本消息为例介绍阅后即焚方案的实现过程。对于图片、语音、视频等其他消息类型,均可参照此流程进行类似实现。

准备工作

发送阅后即焚消息

以下为发送阅后即焚消息的示例代码,通过 消息扩展字段 添加阅后即焚标识。

// 阅后即焚标识(这里只是举例,你可以自定义具体字段)
private final String FIRE_FLAG = "fire";
// 创建文本消息,toChatUsername 为接收方用户 ID
EMMessage message = EMMessage.createTextSendMessage("这是一条阅后即焚消息", toChatUsername);
// 设置为单聊
message.setChatType(EMMessage.ChatType.Chat);
// 设置消息扩展字段传递阅后即焚标识
message.setAttribute(FIRE_FLAG, true);
// 发送消息
EMClient.getInstance().chatManager().sendMessage(message);



接收和删除消息

收到消息后,判断是否为阅后即焚消息。若是,在用户查看消息后发送已读回执并删除该条阅后即焚消息。

// 阅后即焚标识(这里只是举例,你可以自定义具体字段)private final String FIRE_FLAG = "fire";// 注册消息监听器EMMessageListener msgListener = new EMMessageListener() {
    @Override
    public void onMessageReceived(List<EMMessage> messages) {
        for (EMMessage message : messages) {
            // 判断是否为阅后即焚消息
            // 使用 getBooleanAttribute(key, defaultValue) 避免捕获 HyphenateException
            if (message.getBooleanAttribute(FIRE_FLAG, false)) {
                // 更新 UI,提示用户有一条阅后即焚消息
            }
        }
    }

    // 其他回调方法...
    @Override
    public void onCmdMessageReceived(List<EMMessage> messages) {}
    @Override
    public void onMessageRead(List<EMMessage> messages) {}
    @Override
    public void onMessageDelivered(List<EMMessage> messages) {}
    @Override
    public void onMessageRecalledWithExt(List<EMRecallMessageInfo> recallMessageInfo) {}
    @Override
    public void onMessageChanged(EMMessage message, Object change) {}};EMClient.getInstance().chatManager().addMessageListener(msgListener);// 当用户已读消息后(例如,点击查看了详情),发送已读回执并删除服务器和本地消息try {
    // 发送已读回执
    EMClient.getInstance().chatManager().ackMessageRead(message.getFrom(), message.getMsgId());
    // 获取消息所属会话
    EMConversation conversation = EMClient.getInstance().chatManager().getConversation(message.getFrom(), EMConversation.EMConversationType.Chat, true);
    // 删除服务端和本地消息
    ArrayList msgIds = new ArrayList<>();
    msgIds.add(message.getMsgId());
    conversation.removeMessagesFromServer(msgIds, new EMCallBack() {
        @Override
        public void onSuccess() {
            //删除成功
            // 刷新你的数据集,更新 UI
        }

        @Override
        public void onError(int code, String error) {
            //删除失败
            //用户根据自己的业务需求进行处理
        }
    });} catch (HyphenateException e) {
    e.printStackTrace();}

发送方删除消息

发送方收到回执后,判断该消息是否阅后即焚。若是,删除该条阅后即焚消息。

// 注册消息监听器EMMessageListener msgListener = new EMMessageListener() {
    @Override
    // 收到已读回执的回调
    public void onMessageRead(List<EMMessage> messages) {
        for (EMMessage message : messages) {
            // 判断是否为阅后即焚消息
            if (message.getBooleanAttribute(FIRE_FLAG, false)) {
                // 消息所属会话:会话 ID 为接收方的用户 ID
                EMConversation conversation = EMClient.getInstance().chatManager().getConversation(message.getTo(), EMConversation.EMConversationType.Chat, true);
                // 删除服务端和本地消息
                ArrayList msgIds = new ArrayList<>();
                msgIds.add(message.getMsgId());
                conversation.removeMessagesFromServer(msgIds, new EMCallBack() {
                    @Override
                    public void onSuccess() {
                        //删除成功
                        // 刷新你的数据集,更新 UI
                    }

                    @Override
                    public void onError(int code, String error) {
                        //删除失败
                        //用户根据自己的业务需求进行处理
                    }
                });
            }
        }
    }
    
    // 其他回调方法...
    @Override
    public void onMessageReceived(List<EMMessage> messages) {}
    @Override
    public void onCmdMessageReceived(List<EMMessage> messages) {}
    @Override
    public void onMessageDelivered(List<EMMessage> messages) {}
    @Override
    public void onMessageRecalledWithExt(List<EMRecallMessageInfo> recallMessageInfo) {}
    @Override
    public void onMessageChanged(EMMessage message, Object change) {}};EMClient.getInstance().chatManager().addMessageListener(msgListener);

注意事项

为避免内存泄漏,务必在 Activity 销毁时移除已注册的监听器

// 在 Activity 中@Overrideprotected void onDestroy() {
    
    // 移除消息监听器
    if (msgListener != null) {
        EMClient.getInstance().chatManager().removeMessageListener(msgListener);
    }
    super.onDestroy();}

本次基于环信SDK的实战开发,我们实现了IM消息“阅后即焚“功能。如开发中遇到其他问题,请至 环信官网 联系技术支持咨询。

参考文档: