android环信easeui自定义消息--名片

前言

现在应用中即时通信的功能在app中应用的十分广泛,在即时通信这一块,公司在开发初期多数会选择第三方的库:环信/融云,特别是初创型公司的最爱,关于环信的基本使用,官方文档已经十分清晰了,下面我记录下我开发中的使用之:发送自定义消息—名片
先上效果图:
效果图

开发之路

集成easeui

easeui的集成,官方文档以及写得很详细了,这里不再多述。
easeui为我们提供了一个EaseChatFragment,我们可以直接使用这个EaseChatFragment,也可以自己写一个ChatFragment,继承EaseChatFragment并调用EaseChatFragmentHelper接口。这里我们为了方便,直接使用easeui提供的EaseChatFragment。

进入聊天页面

直接使用EaseChatFragment,通过Bundle,传入一系列参数(聊天模式,聊天对象)

//new出EaseChatFragment或其子类的实例
mChatFragment = new EaseChatFragment();
//传入参数
Bundle args = new Bundle();
//设置为单聊,否则单聊时,消息发送不成功
args.putInt(EaseConstant.EXTRA_CHAT_TYPE, EaseConstant.CHATTYPE_SINGLE);
userName = SPUtils.getString(this, SPUtils.KEY_USERNAME, "123");
//555,123是已经注册的环信账号
args.putString(EaseConstant.EXTRA_USER_ID, userName.equals("123")?"555":"123");
mChatFragment.setArguments(args);
replaceFragment(R.id.fl_container, mChatFragment);

发送扩展消息

根据官方文档,我们需要发送一个扩展消息,如下

//发名片(扩展消息)
EMMessage message = EMMessage.createTxtSendMessage("我的名片",userName.equals("123")?"555":"123");
//设置聊天模式为单聊
message.setChatType(EMMessage.ChatType.Chat);
//设置消息携带的一系列参数,为以后显示名片做准备
message.setAttribute("title", "title_title_title_title");
message.setAttribute("records", true);
message.setAttribute("icon", R.mipmap.ic_launcher);
message.setAttribute("senderid", userName.equals("123")?"555":"123");
message.setAttribute("text", "您的名片已经发送");
EMClient.getInstance().chatManager().sendMessage(message);
ToastUtil.showShort(getApplicationContext(),"名片发送成功");

消息布局

我们需要写一个接收消息的布局,写一个发送消息的布局。两个布局文件中的相对应的控件id要保持一致,方便之后代码中设置内容,这里只贴出发送消息的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:paddingTop="13dp" >

    <TextView
        android:id="@+id/timestamp"
        style="@style/chat_text_date_style"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:paddingLeft="20dp" >

        <ImageView
            android:id="@+id/iv_userhead"
            android:layout_width="@dimen/size_avatar"
            android:layout_height="@dimen/size_avatar"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:layout_marginRight="5dp"
            android:background="@drawable/ease_default_avatar"
            android:scaleType="fitXY" />

        <LinearLayout
            android:id="@+id/bubble"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:layout_toLeftOf="@id/iv_userhead"
            android:layout_toRightOf="@+id/ll_loading"
            android:background="@drawable/ease_chatto_bg" >

            <ImageView
                android:scaleType="fitXY"
                android:id="@+id/ease_chat_item_share_img"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_margin="5dp"
                android:src="@drawable/ease_chat_item_file" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="7dp"
                android:gravity="center_vertical"
                android:orientation="vertical" >

                <TextView
                    android:id="@+id/tv_title_name"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:ellipsize="middle"
                    android:singleLine="true"
                    android:textColor="#000"
                    android:textSize="15sp" />
            </LinearLayout>
        </LinearLayout>
        <ProgressBar
            android:id="@+id/progress_bar"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_centerVertical="true"
            android:layout_toLeftOf="@id/bubble"
            android:visibility="visible" />

        <ImageView
            android:id="@+id/msg_status"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toLeftOf="@id/bubble"
            android:clickable="true"
            android:src="@drawable/ease_msg_state_failed_resend"
            android:visibility="invisible" />

        <TextView
            android:id="@+id/tv_ack"
            style="@style/chat_text_name_style"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toLeftOf="@id/tv_chatcontent"
            android:text="@string/text_ack_msg"
            android:textSize="12sp"
            android:visibility="invisible" />

        <TextView
            android:id="@+id/tv_delivered"
            style="@style/chat_text_name_style"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toLeftOf="@id/tv_chatcontent"
            android:text="@string/text_delivered_msg"
            android:textSize="12sp"
            android:visibility="invisible" />

    </RelativeLayout>

</LinearLayout>

自定义消息内容

有了消息布局,我们需要在发送和接收时,控制消息内容,easeui提供了EaseChatRow,我们只需要继承这个类,就可以在消息发送和接收时,控制消息体:在onInflateView()方法中加载布局,在onFindViewById()方法中获取控件,在onSetUpView()中改变展示内容,在onBubbleClick()方法中写消息被点击时的逻辑

public class EaseChatRowCard extends EaseChatRow {
    ImageView img;//图片
    TextView title;//title
    private TextView text;

    public EaseChatRowCard(Context context, EMMessage message, int position, BaseAdapter adapter) {
        super(context, message, position, adapter);
    }
    /**
     * 加载布局
     */
    @Override
    protected void onInflatView() {
        inflater.inflate(message.direct() == EMMessage.Direct.RECEIVE ?
                R.layout.ease_row_received_card : R.layout.ease_row_sent_card, this);
    }

    /**
     * 实例化控件
     */
    @Override
    protected void onFindViewById() {
        title = (TextView) findViewById(R.id.tv_title_name);
        img = (ImageView) findViewById(R.id.ease_chat_item_share_img);
        text = (TextView) findViewById(R.id.timestamp);
    }

    /**
     * 更新适配器
     */
    @Override
    protected void onUpdateView() {
        adapter.notifyDataSetChanged();
    }

    /**
     * 设置内容
     */
    @Override
    protected void onSetUpView() {
        try {
            String titleString = message.getStringAttribute("title");
            title.setText(titleString);
            img.setImageResource(message.getIntAttribute("icon",R.drawable.ic_launcher));
            //消息状态变化
            handleTextMessage();
        } catch (HyphenateException e) {
            e.printStackTrace();
        }
    }


    protected void handleTextMessage() {
        if (message.direct() == EMMessage.Direct.SEND) {
            setMessageSendCallback();
            switch (message.status()) {
                case CREATE:
                    progressBar.setVisibility(View.GONE);
                    statusView.setVisibility(View.VISIBLE);
                    break;
                case SUCCESS:
                    progressBar.setVisibility(View.GONE);
                    statusView.setVisibility(View.GONE);
                    break;
                case FAIL:
                    progressBar.setVisibility(View.GONE);
                    statusView.setVisibility(View.VISIBLE);
                    break;
                case INPROGRESS:
                    progressBar.setVisibility(View.VISIBLE);
                    statusView.setVisibility(View.GONE);
                    break;
                default:
                    break;
            }
        }else{
            if(!message.isAcked() && message.getChatType() == EMMessage.ChatType.Chat){
                try {
                    EMClient.getInstance().chatManager().ackMessageRead(message.getFrom(), message.getMsgId());
                } catch (HyphenateException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    protected void onBubbleClick() {
        Toast.makeText(context, "点击了", Toast.LENGTH_SHORT).show();
    }
}

展示消息—EaseMessageAdapter

消息体已经写好了,那么在消息发送和接收时,我们还需要一个适配器去展示消息。这就需要easeui中的一个重要的类—EaseMessageAdapter。
在EaseMessageAdapter中的getViewTypeCount()方法中将默认的14种方法,改成16(包括自定义接收消息和发送消息)

public int getViewTypeCount() {
    if(customRowProvider != null && customRowProvider.getCustomChatRowTypeCount() > 0){
        //14改成16
        return customRowProvider.getCustomChatRowTypeCount() + 16;
    }
       //14改成16
       return 16;
   }

在getItemViewType(int position)方法中,增加消息类型:

public int getItemViewType(int position) {
    EMMessage message = getItem(position); 
    if (message == null) {
        return -1;
    }

    if(customRowProvider != null && customRowProvider.getCustomChatRowType(message) > 0){
        //13改成15
        return customRowProvider.getCustomChatRowType(message) + 15;
    }

    if (message.getType() == EMMessage.Type.TXT) {
        if(message.getBooleanAttribute(EaseConstant.MESSAGE_ATTR_IS_BIG_EXPRESSION, false)){
            return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_EXPRESSION : MESSAGE_TYPE_SENT_EXPRESSION;
        }else if (message.getBooleanAttribute("records", false)){//自定义消息扩展
            return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_EXTENDS : MESSAGE_TYPE_SEND_EXTENDS;
        }
        return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_TXT : MESSAGE_TYPE_SENT_TXT;
    }
    if (message.getType() == EMMessage.Type.IMAGE) {
        return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_IMAGE : MESSAGE_TYPE_SENT_IMAGE;

    }
    if (message.getType() == EMMessage.Type.LOCATION) {
        return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_LOCATION : MESSAGE_TYPE_SENT_LOCATION;
    }
    if (message.getType() == EMMessage.Type.VOICE) {
        return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_VOICE : MESSAGE_TYPE_SENT_VOICE;
    }
    if (message.getType() == EMMessage.Type.VIDEO) {
        return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_VIDEO : MESSAGE_TYPE_SENT_VIDEO;
    }
    if (message.getType() == EMMessage.Type.FILE) {
        return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_FILE : MESSAGE_TYPE_SENT_FILE;
    }

    return -1;// invalid
}

之前我们写一个自定义的ChatRow,我们需要在EaseMessageAdapter中的createChatRow方法中创建方法体

protected EaseChatRow createChatRow(Context context, EMMessage message, int position) {
    EaseChatRow chatRow = null;
    if(customRowProvider != null && customRowProvider.getCustomChatRow(message, position, this) != null){
        return customRowProvider.getCustomChatRow(message, position, this);
    }
    switch (message.getType()) {
    case TXT:
        if(message.getBooleanAttribute(EaseConstant.MESSAGE_ATTR_IS_BIG_EXPRESSION, false)){
            chatRow = new EaseChatRowBigExpression(context, message, position, this);
        }else if (message.getBooleanAttribute("records", false)){//自定义消息扩展
chatRow = new EaseChatRowShare(context,message,position,this);
} else{
            chatRow = new EaseChatRowText(context, message, position, this);
        }
        break;
    case LOCATION:
        chatRow = new EaseChatRowLocation(context, message, position, this);
        break;
    case FILE:
        chatRow = new EaseChatRowFile(context, message, position, this);
        break;
    case IMAGE:
        chatRow = new EaseChatRowImage(context, message, position, this);
        break;
    case VOICE:
        chatRow = new EaseChatRowVoice(context, message, position, this);
        break;
    case VIDEO:
        chatRow = new EaseChatRowVideo(context, message, position, this);
        break;
    default:
        break;
    }

    return chatRow;
}

消息刷新

以上基本可以完成发送名片的功能,存在一个小缺陷,消息在发送时,未刷新,所以我们需要手动刷新,在EaseChatFragment可以获取EaseChatMessageList进行刷新。
在EaseChatFragment写一个获取EaseChatMessageList 的方法

public EaseChatMessageList getMessageList(){
    return messageList;
}

在发送自定义消息后,进行刷新消息

...
mChatFragment.getMessageList().refresh();//刷新数据,否则发送时,无法接收到
ToastUtil.showShort(getApplicationContext(),"名片发送成功");

以上就完成了集成easeui后进行发送名片

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值