參考資料:http://www.rongcloud.cn/docs/android.html#新建消息
1. 自定義消息實體 –RedPackageMessage(一個自定義的紅包消息)
package com.onetoo.www.onetoo.bean.chat;import android.os.Parcel;import android.util.Log;import org.json.JSONException;import org.json.JSONObject;import java.io.UnsupportedEncodingException;import io.rong.common.ParcelUtils;import io.rong.imlib.MessageTag;import io.rong.imlib.model.MessageContent;/** * Created by longShun on 2017/2/24. *//** 注解名:MessageTag ;屬性:value ,flag; value 即 ObjectName 是消息的唯一標(biāo)識不可以重復(fù),* 開發(fā)者命名時不能以 RC 開頭,避免和融云內(nèi)置消息沖突;flag 是用來定義消息的可操作狀態(tài)。*如下面代碼段,自定義消息名稱 CustomizeMessage ,vaule 是 app:custom ,* flag 是 MessageTag.ISCOUNTED | MessageTag.ISPERSISTED 表示消息計數(shù)且存庫。* app:RedPkgMsg: 這是自定義消息類型的名稱,測試的時候用"app:RedPkgMsg";* */@MessageTag(value = "app:RedPkgMsg", flag = MessageTag.ISCOUNTED | MessageTag.ISPERSISTED)public class RedPackageMessage extends MessageContent{ //自定義的屬性 PRivate String title; private String storeName; private String desc1; private String desc2; /* * * 實現(xiàn) encode() 方法,該方法的功能是將消息屬性封裝成 json 串, * 再將 json 串轉(zhuǎn)成 byte 數(shù)組,該方法會在發(fā)消息時調(diào)用,如下面示例代碼: * */ @Override public byte[] encode() { JSONObject jsonObj = new JSONObject(); try { jsonObj.put("title", this.getTitle()); jsonObj.put("storeName",this.getStoreName()); jsonObj.put("desc1",this.getDesc1()); jsonObj.put("desc2",this.getDesc2()); } 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) 構(gòu)造方法,該方法將對收到的消息進(jìn)行解析, * 先由 byte 轉(zhuǎn)成 json 字符串,再將 json 中內(nèi)容取出賦值給消息屬性。 * */ public RedPackageMessage(byte[] data) { String jsonStr = null; try { jsonStr = new String(data, "UTF-8"); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } try { JSONObject jsonObj = new JSONObject(jsonStr); if (jsonObj.has("title")) setTitle(jsonObj.optString("title")); if (jsonObj.has("storeName")) setStoreName(jsonObj.optString("storeName")); if (jsonObj.has("desc1")) setDesc1(jsonObj.optString("desc1")); if (jsonObj.has("desc2")) setDesc2(jsonObj.optString("desc2")); } catch (JSONException e) { Log.d("JSONException", e.getMessage()); } } //給消息賦值。 public RedPackageMessage(Parcel in) { setTitle(ParcelUtils.readFromParcel(in));//該類為工具類,消息屬性 //這里可繼續(xù)增加你消息的屬性 setStoreName(ParcelUtils.readFromParcel(in));//該類為工具類,消息屬性 setDesc1(ParcelUtils.readFromParcel(in));//該類為工具類,消息屬性 setDesc2(ParcelUtils.readFromParcel(in));//該類為工具類,消息屬性 } /** * 讀取接口,目的是要從Parcel中構(gòu)造一個實現(xiàn)了Parcelable的類的實例處理。 */ public static final Creator<RedPackageMessage> CREATOR = new Creator<RedPackageMessage>() { @Override public RedPackageMessage createFromParcel(Parcel source) { return new RedPackageMessage(source); } @Override public RedPackageMessage[] newArray(int size) { return new RedPackageMessage[size]; } }; @Override public int describeContents() { return 0; } /** * 將類的數(shù)據(jù)寫入外部提供的 Parcel 中。 * @param dest 對象被寫入的 Parcel。 * @param flags 對象如何被寫入的附加標(biāo)志。 */ @Override public void writeToParcel(Parcel dest, int flags) { ParcelUtils.writeToParcel(dest, getTitle()); ParcelUtils.writeToParcel(dest, getStoreName()); ParcelUtils.writeToParcel(dest, getDesc1()); ParcelUtils.writeToParcel(dest, getDesc2()); } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getStoreName() { return storeName; } public void setStoreName(String storeName) { this.storeName = storeName; } public String getDesc1() { return desc1; } public void setDesc1(String desc1) { this.desc1 = desc1; } public String getDesc2() { return desc2; } public void setDesc2(String desc2) { this.desc2 = desc2; }}2.自定義消息提供者
package com.onetoo.www.onetoo.bean.chat;import android.content.Context;import android.text.Spannable;import android.text.SpannableString;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import com.onetoo.www.onetoo.R;import io.rong.imkit.emoticon.AndroidEmoji;import io.rong.imkit.model.ProviderTag;import io.rong.imkit.model.UIMessage;import io.rong.imkit.widget.provider.IContainerItemProvider;import io.rong.imlib.model.Message;import io.rong.imlib.model.MessageContent;import io.rong.message.TextMessage;/** * Created by longShun on 2017/2/24. * desc新建一個消息類繼承 IContainerItemProvider.MessageProvider 類,實現(xiàn)對應(yīng)接口方法, * 1.注意開頭的注解! * 2.注意泛型! */@ProviderTag( messageContent = RedPackageMessage.class,(這里是你自定義的消息實體) showReadState = true)public class RedPackageItemProvider extends IContainerItemProvider.MessageProvider<RedPackageMessage> { public RedPackageItemProvider() { } @Override public View newView(Context context, ViewGroup viewGroup) { //這就是展示在會話界面的自定義的消息的布局 View view = LayoutInflater.from(context).inflate(R.layout.item_redpackage_message, null); ViewHolder holder = new ViewHolder(); holder.tvTitle = (TextView) view.findViewById(R.id.tv_title); holder.tvStoreName = (TextView) view.findViewById(R.id.tv_store_name); holder.tvDesc1 = (TextView) view.findViewById(R.id.tv_desc1); holder.tvDesc2 = (TextView) view.findViewById(R.id.tv_desc2); view.setTag(holder); return view; } @Override public void bindView(View view, int i, RedPackageMessage redPackageMessage, UIMessage message) { //根據(jù)需求,適配數(shù)據(jù) ViewHolder holder = (ViewHolder) view.getTag(); if (message.getMessageDirection() == Message.MessageDirection.SEND) {//消息方向,自己發(fā)送的 //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); } //AndroidEmoji.ensure((Spannable) holder.message.getText());//顯示消息中的 Emoji 表情。 //holder.tvTitle.setText(redPackageMessage.getTitle()); holder.tvStoreName.setText(redPackageMessage.getStoreName()); //holder.tvDesc1.setText(redPackageMessage.getDesc1()); //holder.tvDesc2.setText(redPackageMessage.getDesc2()); } @Override public Spannable getContentSummary(RedPackageMessage redPackageMessage) { return new SpannableString(redPackageMessage.getDesc1()); } @Override public void onItemClick(View view, int i, RedPackageMessage redPackageMessage, UIMessage uiMessage) { } @Override public void onItemLongClick(View view, int i, RedPackageMessage redPackageMessage, UIMessage uiMessage) { //實現(xiàn)長按刪除等功能,咱們直接復(fù)制融云其他provider的實現(xiàn) String[] items1;//復(fù)制,刪除 items1 = new String[]{view.getContext().getResources().getString(io.rong.imkit.R.string.rc_dialog_item_message_copy), view.getContext().getResources().getString(io.rong.imkit.R.string.rc_dialog_item_message_delete)}; OptionsPopupDialog.newInstance(view.getContext(), items1).setOptionsPopupDialogListener(new OptionsPopupDialog.OnOptionsItemClickedListener() { public void onOptionsItemClicked(int which) { if (which == 0) { ClipboardManager clipboard = (ClipboardManager) view.getContext().getSystemService(Context.CLIPBOARD_SERVICE); clipboard.setText(content.getContent());//這里是自定義消息的消息屬性 } else if (which == 1) { RongIM.getInstance().deleteMessages(new int[]{message.getMessageId()}, (RongIMClient.ResultCallback) null); } } }).show(); } private static class ViewHolder { TextView tvTitle, tvStoreName, tvDesc1, tvDesc2; }}3.注意自定義消息的布局:
寫法一(會出問題):整體就一層布局,那么效果圖如下,紅包布局會占滿右邊所有空間 
寫法二(正常):整體布局外面再嵌套一層,顯示正常,如圖所示,至于原因,暫時還不清楚。

4.注冊消息類型以及消息提供者
RongIM.init(this); //注意,要在初始化之后注冊 RongIM.registerMessageType(RedPackageMessage.class); RongIM.registerMessageTemplate(new RedPackageItemProvider());5.官網(wǎng)測試 
新聞熱點
疑難解答