Android

实现自定义消息收发

更新时间: 2025/09/11 14:15:56

网易云信即时通讯 IM SDK 内置了包括图片,音频,视频等多媒体消息,但基于不同的应用场景,您可能需要某些特殊的消息类型,因此需要自定义消息类型。本文介绍了如何从创建自定义 Attachment 到绘制 UI,逐步实现自定义消息类型。

IM UIKit 的会话消息模块(chatkit-ui)默认实现了文本消息、图片消息等 基本消息类型 的发送和展示。如果这些消息类型无法满足您的业务需求,您可 新增自定义消息类型

消息类型

实现自定义消息收发涉及的基础消息类型如下:

消息类型 显示效果 是否需要额外集成
文本消息 否,集成会话界面即可用
图片消息
语音消息
视频消息
表情
文件消息
地理位置 是,参考 实现地理位置消息功能

前提条件

根据本文操作前,请确保您已 集成会话消息界面

第一步:处理自定义消息

实现自定义消息收发之前,您需先自行实现消息数据的封装和相关解析规则。IM UIKit 可按照您实现的封装和解析规则对消息进行处理,将消息返回给您的应用。

  1. 创建自定义 Attachment,需要继承 CustomAttachment,并重写数据解析方法(parse)、数据封装方法(packData)以及序列化方法(toJsonStr)。

    • 必须提供无参构造方法:自定义的 Attachment 必须提供一个无参数的构造方法,因为 IM UIKit 内部会通过反射方式创建对象。

    • 必须调用父类构造方法传入类型:在构造方法中,必须调用父类的构造方法并传入自定义消息类型值(建议从 1000 开始)。

    假设自定义 AttachmentCustomerSampleAttachment 进行说明:

    1. 创建 CustomerSampleAttachment 类。

    2. 将您的自定义消息处理逻辑添加到 CustomerSampleAttachment 类,主要包括数据解析方法 parse 和数据封装方法 packData。前者将收到的消息进行解析,后者将数据进行封装用于发送。

      Javapublic class CustomerSampleAttachment extends CustomAttachment{
          // 定义消息类型常量
          private static final int TYPE = 1002;
      
          //自定义消息解析之后的值,本例代表自定义消息只有一个 String 类型的值
          private String custmoerText;
      
          // 必须提供无参构造方法,IM UIKit 内部会通过反射方式创建对象
          // 构造方法中必须调用父类构造方法并传入自定义消息类型值
          public CustomerSampleAttachment() {
              super(TYPE); // 调用父类构造方法并传入消息类型
          }
      
          //重写数据解析方法,这里面数据以 JSONObject 格式进行传输,所以您可以制定自己的数据格式。
          //这个示例表示,自定义数据格式为 {"customer_message_key": "我是一个自定义消息" }
          @Override
          protected void parseData(JSONObject data) {
              //todo 从接收到的消息内容中解析您的数据
              try {
                  this.custmoerText = data.getString("customer_message_key");
              } catch (Exception exception){
              }
          }
      
          //重写数据封装方法,将您需要传递的内容转换为 JSONObject 格式进行传输,所以您可以制定自己的数据格式。
          //这个示例表示,把属性 custmoerText 的内容转换为 JSONObject,用于消息发送过程中的传递
          @Override
          protected JSONObject packData() {
              //将消息进行封装即可
              JSONObject data = new JSONObject();
              try {
                  data.put("customer_message_key", custmoerText);
              }catch (Exception exception){}
      
              return data;
          }
      
          public void setData(String data){
              this.custmoerText = data;
          }
          //设置自定义消息的信息摘要,在会话列表中根据该方法返回进行展示
          @Override
          public String getContent() {
              return "...";
          }
      
          //通过序列化后的 String 放到消息的 Attachment 中传输
          @NonNull
          @Override
          public String toJsonStr() {
              try {
                  JSONObject map = new JSONObject();
                  map.put("type", TYPE);
                  map.put("data", packData());
                  return map.toString();
              } catch (Exception e) {
                  e.printStackTrace();
                  return "";
              }
          }
      }
      
  2. 在消息数据处理逻辑中,增加自定义消息的映射关系。所有自定义消息都会在 ChatCustomMsgFactory 中进行分发,SDK 将确定您的自定义消息是采用哪个 CustomAttachment 进行处理。

    ChatKit-UI 中,网易云信已经创建了 ChatCustomMsgFactory,专门用于自定义消息的处理。您只需要添加您自定义消息的映射关系即可。

    示例代码如下:

    JavaChatKitClient.addCustomAttach(1002, CustomerSampleAttachment.class);
    

    您注册的自定义消息解析器,只有您接入 ChatRepo 收发消息的时候才会自动解析,在 SDK 的 V2NIMMessageV2NIMMessageAttachment 只提供 JSON 字符串。

    至此,您已经完成了自定义消息的处理逻辑。如果您获取的消息为该自定义消息类型,就能从 IMMessageInfo 中获取到 CustomerSampleAttachment 对象值。

第二步:绘制自定义消息 UI

如果需要在会话界面将您的自定义消息按照您自定义的 UI 样式进行展示,那么需要完成如下步骤。

  1. 添加消息展示的 ViewHolder,并使其继承 NormalChatBaseMessageViewHolder(基础版)。也可参考 ChatTextMessageViewHolderChatImageMessageViewHolder 等中已实现的代码逻辑。

    若集成了通用版 UI 组件,需要使其继承 FunChatBaseMessageViewHolder(通用版)。也可参考 FunChatTextMessageViewHolderFunChatImageMessageViewHolder 等中已实现的代码逻辑。

    Javapublic class CustomerSampleViewHolder extends NormalChatBaseMessageViewHolder {
        private final static String TAG = "ChatStickerViewHolder";
    
        private CustomerSampleViewBinding binding;//创建自己的 layout 布局
    
        public CustomerSampleViewHolder(@NonNull ChatBaseMessageViewHolderBinding parent, int viewType) {
            super(parent, viewType);
        }
    
        @Override
        public void addViewToMessageContainer() {
            binding = CustomerSampleViewBinding.inflate(LayoutInflater.from(parent.getContext()),
                    getContainer(),true);
        }
    
        @Override
        public void bindData(ChatMessageBean message, ChatMessageBean lastMessage) {
            super.bindData(message, lastMessage);
            currentMessage = message;
            CustomerSampleAttachment attachment = (CustomerSampleAttachment) message.getMessageData().getAttachment();
            if (attachment == null) {
                return;
            }
            //todo 设置 ViewHolder 展示 UI 的内容
        }
    }
    
  2. CustomerSampleViewHolder 添加到 IM UIkit,使 IM UIKit 在加载后能够运行您的自定义消息相关代码逻辑。

    JavaChatKitClient.addCustomViewHolder(1002, CustomerSampleViewHolder.class);
    

第三步:收发自定义消息

通过 IM UIKit 实现自定义消息收发的流程如下:

  1. 调用 createCustomMessage 方法创建自定义消息。

    Java    CustomerSampleAttachment customerAttachment = new CustomerSampleAttachment();
        //设置自己的 Attachment 中的数据
        customerAttachment.setData("your data");
        String attachStr = customerAttachment.toJsonStr()
        //创建 V2NIMMessage,用于发送,content 代表内容,attachStr 代表序列化后的附件
        V2NIMMessage customMsg = V2NIMMessageCreator.createCustomMessage(content, attachStr);
    
  2. 调用 ChatRepo.sendMessage 方法发送消息。

    IM UIKit 中的实现请参考 ChatBaseViewModelsendCustomMessage() 方法。

    Java//ChaRepo 提供的发送消息接口,任何消息类型都可以使用该接口进行发送
    //customMessage 表示创建的消息体,conversationId 表示发送给对方的会话 ID,可以由用户/群组 ID 和 type 生成,params 为配置参数,callback 表示消息发送回调
    ChatRepo.sendMessage(customMessage, conversationId, params,callback);
    
  3. 接收方接收消息。

    IM UIKit 中已经实现该接收逻辑,请参考 ChatBaseViewModeladdListener() 方法和 messageListener 对象值。

    Javaprivate final NEChatListener messageListener =
      new NEChatListener() {
            // 接收到新消息
            @Override
            public void onReceiveMessages(@NonNull List<IMMessageInfo> messages) {
                //处理收到的消息
            }
        };
    
        //注册消息接收监听
        ChatRepo.addMessageListener(messageListener);
    
    

注意事项

当通过 服务端 API 发送自定义消息时,为确保客户端能够正确识别和解析不同类型的自定义消息,您需要按照特定格式构造 attachment 字段的 JSON 内容。

自定义消息的 attachment 字段应遵循以下 JSON 格式:

JSON{
    "type": 1002,
    "data": {
        "customer_message_key": "这是一条自定义消息"
    }
}

字段说明

字段 类型 说明
type Integer 自定义消息类型标识,用于客户端区分不同类型的自定义消息,必须 与客户端定义的类型保持一致。
data JSON 对象 自定义消息的业务数据载体,可包含任意自定义的键值对。

下一步

如果需要在会话界面添加发送自定义消息的 UI 控件,可在单击 更多 按钮(见下图)后展示的区域增加相应的按钮。具体实现方式可参考 更多 区域增加按钮

image
此文档是否对你有帮助?
有帮助
去反馈
  • 消息类型
  • 前提条件
  • 第一步:处理自定义消息
  • 第二步:绘制自定义消息 UI
  • 第三步:收发自定义消息
  • 注意事项
  • 下一步