最近一个项目在接入融云1v1聊天,然后各种更换界面~先说下自定义消息,先上图,运行效果如下:
1、需要自定义message,继承 MessageContent
如:@MessageTag(value = "RCDTestMessage", flag = MessageTag.ISPERSISTED | MessageTag.ISCOUNTED) public class RCDTestMessage extends MessageContent {
注意:@MessageTag里面的value,如果需要收到服务端推送过来的自定义消息去展示或者和ios推送过来的自定义消息互通,value里面的值,一定要和后台还有ios端约定好,一模一样才可以。
flag 是 MessageTag.ISCOUNTED | MessageTag.ISPERSISTED 表示消息计数且存库。
下面是自定义message:
/**
* 自定义消息的实体类
*/
@MessageTag(value = "RCDTestMessage", flag = MessageTag.ISPERSISTED | MessageTag.ISCOUNTED)
public class RCDTestMessage extends MessageContent {
private String content;
private String extra;
/**
* 实现 encode() 方法,该方法的功能是将消息属性封装成 json 串,再将 json 串转成 byte 数组,该方法会在发消息时调用
*/
@Override
public byte[] encode() {
JSONObject object = new JSONObject();
object.put("content", content);
object.put("extra", extra);
try {
return object.toString().getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
public RCDTestMessage() {
}
/**
*覆盖父类的 MessageContent(byte[] data) 构造方法,该方法将对收到的消息进行解析, * 先由 byte 转成 json 字符串,再将 json 中内容取出赋值给消息属性。
*/
public RCDTestMessage(byte[] data) {
super(data);
String jsonStr = null;
try {
jsonStr = new String(data, "UTF-8");
JSONObject object = JSON.parseObject(jsonStr);//注意,这里一定要用setContent和setExtra
this.setContent(object.getString("content"));
this.setExtra(object.getString("extra"));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void writeToParcel(Parcel dest, int flags) {
ParcelUtils.writeToParcel(dest, this.getContent());//注意,这里一定要用getContent和getExtra
ParcelUtils.writeToParcel(dest, this.getExtra());
}
public static final Creator CREATOR = new Creator() {
@Override
public RCDTestMessage createFromParcel(Parcel source) {
return new RCDTestMessage(source);
}
@Override
public RCDTestMessage[] newArray(int size) {
return new RCDTestMessage[size];
}
};
public RCDTestMessage(Parcel parcel) {//注意,这里一定要用setContent和setExtra
this.setExtra(ParcelUtils.readFromParcel(parcel));
this.setContent(ParcelUtils.readFromParcel(parcel));
}
@Override
public int describeContents() {
return 0;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getExtra() {
return extra;
}
public void setExtra(String extra) {
this.extra = extra;
}
}
2、自定义plugin、如果下面扩展区域里面需要自定义plugin,可以这样写:
public class GiftPlugin implements IPluginModule {
Conversation.ConversationType conversationType;
String targetId;
@Override
public Drawable obtainDrawable(Context context) {
//设置插件 Plugin 图标、可以替换扩展区域的plugin
return ContextCompat.getDrawable(context, R.mipmap.rc_ext_plugin_image);
}
@Override
public String obtainTitle(Context context) {
//设置插件 Plugin 展示文字
return "送礼物";
}
@Override
public void onClick(final Fragment currentFragment, RongExtension extension) {
//示例获取 会话类型、targetId、Context,此处可根据产品需求自定义逻辑,如:开启新的 Activity 等。
conversationType = extension.getConversationType();
targetId = extension.getTargetId();
Log.e("送礼物",targetId);
sendGift("送出【某某礼物】", "https://jq.qq.com/?_wv=1027&k=5ecmpbK");
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
}
/**
* 赠送礼物
*/
public void sendGift(String giftName, String giftPath) {
final RCDTestMessage info = new RCDTestMessage();
info.setContent(giftName);
info.setExtra(giftPath);
//chatUserid 是接收消息方的id Conversation.ConversationType 是消息会话的类型在这里表示的是私聊
Message message = Message.obtain(targetId, Conversation.ConversationType.PRIVATE, info);
RongIM.getInstance().sendMessage(message, null, 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) {
}
});
}
}
3、自定义Provider
注意:头部需要@ProviderTag,messageContent:消息类型,showPortrait:是否显示头像
centerInHorizontal :发出的消息是否居中,showReadState 是否显示已读/未读状态
/**
* 送礼物布局
*/
@ProviderTag(messageContent = RCDTestMessage.class, showPortrait = true, centerInHorizontal = false,showReadState = true)
public class GiftProvider extends IContainerItemProvider.MessageProvider {
private Context mContext;
@Override
public View newView(Context context, ViewGroup viewGroup) {
this.mContext = context;
View view = LayoutInflater.from(context).inflate(R.layout.ry_chat_phone_layout, viewGroup, false);
PhoneHolder holder = new PhoneHolder();
holder.rcGiftLayoutRight = view.findViewById(R.id.rc_gift_layout_right);
holder.rcGiftLayoutLeft = view.findViewById(R.id.rc_gift_layout_left);
holder.tvGiftRight = view.findViewById(R.id.tv_gift_right);
holder.tvGiftLeft = view.findViewById(R.id.tv_gift_left);
holder.ivGiftRight = view.findViewById(R.id.iv_gift_right);
holder.ivGiftLeft = view.findViewById(R.id.iv_gift_left);
view.setTag(holder);
return view;
}
@Override
public void bindView(View view, int i, RCDTestMessage RCDTestMessage, UIMessage uiMessage) {
PhoneHolder holder = (PhoneHolder) view.getTag();
if (uiMessage.getMessageDirection() == Message.MessageDirection.SEND) {//消息方向,自己发送的
holder.rcGiftLayoutRight.setVisibility(View.VISIBLE);
holder.rcGiftLayoutLeft.setVisibility(View.GONE);
holder.tvGiftRight.setText(RCDTestMessage.getContent());
Glide.with(mContext).load(RCDTestMessage.getExtra()).into(holder.ivGiftRight);
} else {
holder.rcGiftLayoutRight.setVisibility(View.GONE);
holder.rcGiftLayoutLeft.setVisibility(View.VISIBLE);
holder.tvGiftLeft.setText(RCDTestMessage.getContent());
Glide.with(mContext).load(RCDTestMessage.getExtra()).into(holder.ivGiftLeft);
}
holder.rcGiftLayoutRight.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendGift("送出【某某礼物】", "https://jq.qq.com/?_wv=1027&k=5ecmpbK");
}
});
}
@Override //这里意思是你的这个自定义消息显示的内容
public Spannable getContentSummary(RCDTestMessage RCDTestMessage) {
return null;
}
@Override //点击你的自定义消息执行的操作
public void onItemClick(View view, int i, RCDTestMessage RCDTestMessage, UIMessage uiMessage) {
}
class PhoneHolder {
RelativeLayout rcGiftLayoutRight;
RelativeLayout rcGiftLayoutLeft;
TextView tvGiftRight;
TextView tvGiftLeft;
ImageView ivGiftRight;
ImageView ivGiftLeft;
}
/**
* 赠送礼物
*/
public void sendGift(String giftName, String giftPath) {
final RCDTestMessage info = new RCDTestMessage();
info.setContent(giftName);
info.setExtra(giftPath);
//chatUserid 是接收消息方的id Conversation.ConversationType 是消息会话的类型在这里表示的是私聊、对方融云id,打开单聊的时候,我存在本地了
Message message = Message.obtain(App.getRYUidOther(), Conversation.ConversationType.PRIVATE, info);
RongIM.getInstance().sendMessage(message, giftName, 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) {
}
});
}
}
4、自定义布局:ry_chat_phone_layout
5、在application里面注册自定义消息及provider:
注意:需要融云init之后
//发送礼物的自定义消息
RongIM.registerMessageType(RCDTestMessage.class);
RongIM.registerMessageTemplate(new GiftProvider());
6、自定义扩展区域、上面的自定义plugin用法
public class SampleModule extends DefaultExtensionModule {
@Override
public List getPluginModules(Conversation.ConversationType conversationType) {
// super.getPluginModules(conversationType); 如果需要对红包进行排序可从父类中的 getPluginModules 集合中过滤取出 JrmfExtensionModule
List pluginModuleList = new ArrayList();
pluginModuleList.add(new SamplePlugin());
pluginModuleList.add(new OrderPlugin());
pluginModuleList.add(new GiftPlugin());//礼物
return pluginModuleList;
}
@Override
public List getEmoticonTabs() {
return super.getEmoticonTabs();
}
}
在application的create里面执行自定义plugin:(融云init之后)
public void setMyExtensionModule() {
List moduleList = RongExtensionManager.getInstance().getExtensionModules();
IExtensionModule defaultModule = null;
if (moduleList != null) {
for (IExtensionModule module : moduleList) {
if (module instanceof DefaultExtensionModule) {
defaultModule = module;
break;
}
}
if (defaultModule != null) {
RongExtensionManager.getInstance().unregisterExtensionModule(defaultModule);
RongExtensionManager.getInstance().registerExtensionModule(new SampleModule());
}
}
}