跳转至

自定义消息

注册消息

1、新建自定义消息类,继承自 MessageContent

public class CustomizeMessage extends MessageContent {
      private String content;//消息属性,可随意定义
 }

2、实现 encode() 方法,将消息属性封装成 json 串,再将 json 串转成 byte 数组,该方法会在发消息时调用。

@Override
public byte[] encode() {
    JSONObject jsonObj = new JSONObject();

    try {
        jsonObj.put("content", "这是一条消息内容");
    } catch (JSONException e) {
        Log.e("JSONException", e.getMessage());
    }

    try {
        return jsonObj.toString().getBytes("UTF-8");
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }

    return null;
}

覆盖父类的 MessageContent(byte[] data) 构造方法,该方法将对收到的消息进行解析,先由 byte 转成 json 字符串,再将 json 中内容取出赋值给消息属性。

public CustomizeMessage(byte[] data) {
    String jsonStr = null;

    try {
        jsonStr = new String(data, "UTF-8");
    } catch (UnsupportedEncodingException e1) {

    }

    try {
        JSONObject jsonObj = new JSONObject(jsonStr);

        if (jsonObj.has("content"))
            content = jsonObj.optString("content");

    } catch (JSONException e) {
        RLog.e(this, "JSONException", e.getMessage());
    }

}

MessageContent 已实现 Parcelable 接口,需要实现 Parcelable 中的方法:

//给消息赋值。
public CustomizeMessage(Parcel in) {
    content=ParcelUtils.readFromParcel(in);//该类为工具类,消息属性
    ...
    //这里可继续增加你消息的属性
  }

  /**
   * 读取接口,目的是要从Parcel中构造一个实现了Parcelable的类的实例处理。
   */
  public static final Creator<CustomizeMessage> CREATOR = new Creator<CustomizeMessage>() {

      @Override
      public CustomizeMessage createFromParcel(Parcel source) {
          return new CustomizeMessage(source);
      }

      @Override
      public CustomizeMessage[] newArray(int size) {
          return new CustomizeMessage[size];
      }
  };

  /**
   * 描述了包含在 Parcelable 对象排列信息中的特殊对象的类型。
   *
   * @return 一个标志位,表明Parcelable对象特殊对象类型集合的排列。
   */
  public int describeContents() {
      return 0;
  }

  /**
   * 将类的数据写入外部提供的 Parcel 中。
   *
   * @param dest  对象被写入的 Parcel。
   * @param flags 对象如何被写入的附加标志。
   */
  @Override
  public void writeToParcel(Parcel dest, int flags) {
      ParcelUtils.writeToParcel(dest, content);//该类为工具类,对消息中属性进行序列化
      ...
      //这里可继续增加你消息的属性
  }

3、增加注解信息

注解名:MessageTag ;

属性:value ,flag;

value 即 ObjectName 是消息的唯一标识不可以重复,开发者命名时不能以 RC 开头,避免和融云内置消息冲突; flag 是用来定义消息的可操作状态。

示例如下,自定义消息名称 CustomizeMessage ,vaule 是 app:custom ,flag 是 MessageTag.ISCOUNTED | MessageTag.ISPERSISTED 表示消息计数且存库。

@MessageTag(value = "app:custom", flag = MessageTag.ISCOUNTED | MessageTag.ISPERSISTED)
public class CustomizeMessage extends MessageContent {
  ...
}

flag 值如下表:

举值 说明
MessageTag.NONE 为空值,不表示任何意义,发送的自定义消息不会在会话页面和会话列表中展示。
MessageTag.ISCOUNTED 表示客户端收到消息后,要进行未读消息计数(未读消息数增加 1),所有内容型消息都应该设置此值。非内容类消息暂不支持消息计数。
MessageTag.ISPERSISTED 表示客户端收到消息后,要进行存储,并在之后可以通过接口查询,存储后会在会话界面中显示。
MessageTag.STATUS 在本地不存储,不计入未读数,并且如果对方不在线,服务器会直接丢弃该消息,对方如果之后再上线也不会再收到此消息(聊天室类型除外,此类消息聊天室会视为普通消息)。

4、注册自定义消息

自定义消息应在 init 后注册,代码如下:

RongIM.registerMessageType(CustomizeMessage.class);

消息展示

自定义消息在会话列表和会话页面显示。

步骤:

1、创建消息提供者

新建消息类继承 IContainerItemProvider.MessageProvider 类,实现对应接口方法,接口方法如下表:

方法名 描述
newView 初始化 View。
bindView 将数据填充 View 上。
getContentSummary 该条消息为该会话的最后一条消息时,会话列表要显示的内容,通过该方法进行定义。
onItemClick 点击该类型消息触发。
onItemLongClick 长按该类型消息触发。

代码示例如下:

@ProviderTag(messageContent = CustomizeMessage.class)
public class CustomizeMessageItemProvider extends IContainerItemProvider.MessageProvider<CustomizeMessage> {

    class ViewHolder {
        TextView message;
    }

    @Override
    public View newView(Context context, ViewGroup group) {
        View view = LayoutInflater.from(context).inflate(io.rong.imkit.R.layout.item_customize_message, null);
        ViewHolder holder = new ViewHolder();
        holder.message = (TextView) view.findViewById(android.R.id.text1);
        view.setTag(holder);
        return view;
    }

    @Override
    public void bindView(View v, int position, CustomizeMessage content, Message message) {
        ViewHolder holder = (ViewHolder) v.getTag();

        if (message.getMessageDirection() == Message.MessageDirection.SEND) {//消息方向,自己发送的
            holder.message.setBackgroundResource(io.rong.imkit.R.drawable.rc_ic_bubble_right);
        } else {
            holder.message.setBackgroundResource(io.rong.imkit.R.drawable.rc_ic_bubble_left);
        }
        holder.message.setText(content.getContent());
        AndroidEmoji.ensure((Spannable) holder.message.getText());//显示消息中的 Emoji 表情。
    }

    @Override
    public Spannable getContentSummary(CustomizeMessage data) {
        return new SpannableString("这是一条自定义消息CustomizeMessage");
    }

    @Override
    public void onItemClick(View view, int position, CustomizeMessage content, Message message) {

    }

    @Override
    public void onItemLongClick(View view, int position, CustomizeMessage content, Message message) {

    }

}

2、注册消息模板

RongIM.getInstance().registerMessageTemplate(new CustomizeMessageItemProvider);

发送消息

调用 RongIM.getInstance().sendMessage() 发送自定义消息。

参数说明:

参数 说明
message 将要发送的消息体。
pushContent 当客户端离线,接受推送通知时,通知的内容会显示为 pushContent 的内容。
pushData 收到该消息的推送时的附加信息。如果设置该字段,用户在收到该消息的推送时,能通过推送监听 onNotificationMessageArrived() 里的参数 PushNotificationMessage 的 getPushData() 方法获取。
callback 发送消息的回调。

提示

发送自定义消息, pushContent 字段必须填写,否则无法收到该消息的推送。

调用示例:

 RongIM.getInstance().sendMessage(Message.obtain(mTargetId, mConversationType, contactMessage),
                        pushContent, null, new IRongCallback.ISendMessageCallback() {
                            @Override
                            public void onAttached(Message message) {

                            }

                            @Override
                            public void onSuccess(Message message) {

                            }

                            @Override
                            public void onError(Message message, RongIMClient.ErrorCode errorCode) {

                            }
                        });