1. 程式人生 > >環信聊天,可發圖片和語音2

環信聊天,可發圖片和語音2

1、錄音的程式碼實現,先寫一個按鈕了,當點選時執行的事件

/**
         * 錄音
         */
        recording.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                if (MotionEvent.ACTION_DOWN == event.getAction()) {
                    if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                        Toast.makeText(getApplication(), "記憶體卡不存在", Toast.LENGTH_SHORT).show();
                        return false;
                    }

                    v.setPressed(true);

                    try {
                        voiceRecorder.startRecording(null, userName, getApplicationContext());

                    } catch (Exception e) {
                        e.printStackTrace();
                        v.setPressed(false);
                        Toast.makeText(getApplication(), "錄音失敗,請重試", Toast.LENGTH_SHORT).show();

                        if (voiceRecorder != null) {
                            voiceRecorder.discardRecording();
                        }
                    }
                } else if (MotionEvent.ACTION_MOVE == event.getAction()) {

                    if (event.getY() < 0) {
                        Toast.makeText(getApplication(), "鬆開手指,取消傳送", Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(getApplication(), "手指上滑,取消傳送", Toast.LENGTH_SHORT).show();
                    }
                    return true;
                } else if (MotionEvent.ACTION_UP == event.getAction()) {

                    v.setPressed(false);
                    if (event.getY() < 0) {//如果已經上滑後
                        voiceRecorder.discardRecording();
                        return true;
                    }
                    try {
                        int length = voiceRecorder.stopRecoding(); // 停止錄音
                        if (length > 0) {

                            EMMessage message = EMMessage.createVoiceSendMessage(voiceRecorder.getVoiceFilePath(), length, userName);
                            EMClient.getInstance().chatManager().sendMessage(message);
                            recording.setBackgroundResource(R.drawable.record_animate_01);

                            Message msg3 = mHandler.obtainMessage();
                            msg3.what = 0;
                            mHandler.sendMessage(msg3);

                        } else if (length == EMError.FILE_INVALID) {
                            Toast.makeText(getApplication(), "無錄音許可權", Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(getApplication(), "錄音時間太短", Toast.LENGTH_SHORT).show();

                        }
                    } catch (Exception e) {

                    }

                }

                return false;
            }
        });

    }
2、實現聊天佈局,先新增一個chatAdapter繼承BaseAdapter,這裡需要用到兩個佈局檔案,一個是傳送的,一個是接收的,通過判斷使用者名稱來實現用哪個佈局顯示,顯示的時候還要判斷是文字圖片還是語音,是對方發的還是自己發的,
class ChatAdapter extends BaseAdapter {
        List<EMMessage> emMessages;

        ChatAdapter(List<EMMessage> emMessages) {
            this.emMessages = emMessages;
        }

        @Override
        public int getCount() {
            return emMessages.size();
        }

        @Override
        public Object getItem(int i) {
            return emMessages.get(i);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {

            final EMMessage message = emMessages.get(i);//每條訊息
            if (message.getFrom().equals(userName)) {
                view = getLayoutInflater().inflate(R.layout.chat_item1, null);
            } else {
                view = getLayoutInflater().inflate(R.layout.chat_item2, null);
            }

            final TextView time = (TextView) view.findViewById(R.id.time);
            ImageView head = (ImageView) view.findViewById(R.id.head);
//            Bitmap b = message.getBody()
//            head.setImageBitmap();

            TextView tv = (TextView) view.findViewById(R.id.tv);
            final DraweeView image = (DraweeView) view.findViewById(R.id.image);

            long msgTime = message.getMsgTime(); // 資訊時間
            if (i == 0 || msgTime - emMessages.get(i - 1).getMsgTime() > 120000) {
                time.setVisibility(View.VISIBLE);

                long dateTaken = System.currentTimeMillis(); // 當前系統時間
                String currentDate = (String) DateFormat.format("yyyy/MM/dd",
                        dateTaken); // 當前系統日期
                String messageDate = (String) DateFormat.format("yyyy/MM/dd",
                        msgTime); // 資訊的日期
                if (currentDate.equals(messageDate)) { // 如果是當天

                    time.setText(DateFormat.format("kk:mm:ss", msgTime));// 只顯示時間
                } else {
                    time.setText(DateFormat.format("yyyy/MM/dd kk:mm:ss",// 顯示日期加時間
                            msgTime));
                }
            }

            if (message.getType() == EMMessage.Type.TXT) {//文字顯示
                String mess = ((EMTextMessageBody) message.getBody()).getMessage();
                tv.setText(mess);
            } else if (message.getType() == EMMessage.Type.IMAGE) {//圖片顯示
                tv.setVisibility(View.GONE);
                image.setVisibility(View.VISIBLE);

                if (message.getFrom().equals(userName)) { // 對方發的訊息
                    String ThumbnailUrl = ((EMImageMessageBody) message.getBody()).getThumbnailUrl(); // 獲取縮圖片地址
                    String thumbnailPath = ImageUtils.getScaledImage(getApplication(), ThumbnailUrl);
                    String imageRemoteUrl = ((EMImageMessageBody) message.getBody()).getRemoteUrl();// 獲取遠端原圖片地址

                    fb.display(image, thumbnailPath);//顯示圖片
                    imageClick(image, imageRemoteUrl);//圖片新增監聽
                } else {
                    // 自己發的訊息
                    String LocalUrl = ((EMImageMessageBody) message.getBody()).getLocalUrl(); // 獲取本地圖片地址
                    Bitmap bm = ImageUtils.decodeScaleImage(LocalUrl, 160, 160);//獲取縮圖
                    image.setImageBitmap(bm);//顯示圖片
                    Log.e(TAG, "bm=" + bm + "==LocalUrl=" + LocalUrl);

                    imageClick(image, LocalUrl);//圖片新增監聽
                }
            } else if (message.getType() == EMMessage.Type.VOICE) {//語音
                tv.setVisibility(View.GONE);
                tv.setGravity(Gravity.TOP);
                image.setVisibility(View.VISIBLE);
                tv.setText(((EMVoiceMessageBody) message.getBody()).getLength() + "”"); // 設定語音的時長
                // 設定為語音的圖片
                if (message.direct() == EMMessage.Direct.RECEIVE) {
                    image.setImageResource(R.drawable.chatfrom_voice_playing);
                } else {
                    image.setImageResource(R.drawable.chatto_voice_playing);
                }

                image.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View arg0) {
                        // 開始播放錄音
                        startPlay(message, image);
                    }
                });

            }

            return view;
        }

        // 圖片點選監聽
        private void imageClick(ImageView image, final String imageUrl) {
            image.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View arg0) {

                    //new PopWindow_Image(Chat.this, imageUrl).showAtLocation(arg0, 0, 0, 0);
                    new PopWindow_image(fb, Chat.this, imageUrl).showAtLocation(arg0, 0, 0, 0);
                }
            });
        }
    }
兩個佈局的程式碼,chat_item1.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:padding="10dip"
    android:layout_height="match_parent">

    <TextView
        android:gravity="center_horizontal"
        android:id="@+id/time"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:visibility="gone"
        android:text="2015.16"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_marginRight="50dp"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <ImageView
            android:id="@+id/head"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginRight="5dp"
            android:background="@drawable/ic_launcher" />

        <com.facebook.drawee.view.DraweeView
            android:id="@+id/image"
            android:layout_width="100dip"
            android:layout_height="100dip"
            android:maxWidth="150dp"
            android:visibility="gone" />

        <TextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:maxWidth="220dp"
            android:text="5555"
            android:textSize="16dp" />
    </LinearLayout>


</LinearLayout>

chat_item2.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:padding="10dip"
    android:layout_height="match_parent">

    <TextView
        android:gravity="center_horizontal"
        android:id="@+id/time"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:visibility="gone"
        android:text="2015.16"/>

    <LinearLayout
        android:layout_marginTop="30dip"
        android:layout_alignParentRight="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:maxWidth="220dp"
            android:text="5555"
            android:textSize="16dp" />
        <com.facebook.drawee.view.DraweeView
            android:id="@+id/image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:maxWidth="220dp"
            android:visibility="gone"
            />

        <ImageView
            android:id="@+id/head"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginRight="5dp"
            android:background="@drawable/ic_launcher" />




    </LinearLayout>


</RelativeLayout>
3、播放語音的方法
// 開始播放
    private void startPlay(final EMMessage message, ImageView image) {

        EMVoiceMessageBody voiceBody = (EMVoiceMessageBody) message.getBody();

        if (message.direct() == EMMessage.Direct.SEND) {
            // for sent msg, we will try to play the voice file directly
            playVoice(voiceBody.getLocalUrl(), message, image);
        } else {
            if (message.status() == EMMessage.Status.SUCCESS) {
                playVoice(voiceBody.getLocalUrl(), message, image);

            } else if (message.status() == EMMessage.Status.INPROGRESS) {
                //toast("資訊還在傳送中");
                Toast.makeText(getApplication(), "資訊還在傳送中", Toast.LENGTH_SHORT).show();
            } else if (message.status() == EMMessage.Status.FAIL) {
                // toast("接收失敗");
                Toast.makeText(getApplication(), "接收失敗", Toast.LENGTH_SHORT).show();
            }
        }
    }
// 播放錄音
    public void playVoice(String filePath, final EMMessage message, final ImageView image) {
        File file = new File(filePath);
        if (!file.exists() || !file.isFile()) {
            System.err.println("file not exist");
            // toast("語音檔案不存在");
            return;
        }
        playMsgId = message.getMsgId();
        mPlayer = new MediaPlayer();

        try {
            mPlayer.setDataSource(filePath);
            mPlayer.prepare();
            mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

                @Override
                public void onCompletion(MediaPlayer mp) {
                    // TODO Auto-generated method stub
                    if (mPlayer == null) // 表示因為要播放其他語音時已經被停止了,所以不需要再次呼叫停止
                        return;
                    stopPlayVoice(message); // stop animation
                }
            });
            isPlaying = true;
            mPlayer.start();
            playIv = image;
            showAnimation(message);

        } catch (Exception e) {
        }
    }
4、停止語音方法
/**
     * 停止語音
     *
     * @param message
     */
    public void stopPlayVoice(final EMMessage message) {
        voiceAnimation.stop();
        if (message.direct() == EMMessage.Direct.RECEIVE) {
            playIv.setImageResource(R.drawable.chatfrom_voice_playing);
        } else {
            playIv.setImageResource(R.drawable.chatto_voice_playing);
        }
        // stop play voice
        if (mPlayer != null) {
            mPlayer.stop();
            mPlayer.release();
        }
        isPlaying = false;
        playMsgId = null;
        adapter.notifyDataSetChanged();
    }
5、顯示語音時的動畫
 // show the voice playing animation
    private void showAnimation(final EMMessage message) {

        // play voice, and start animation
        if (message.direct() == EMMessage.Direct.RECEIVE) {
            playIv.setImageResource(R.drawable.voice_from_icon);
        } else {
            playIv.setImageResource(R.drawable.voice_to_icon);
        }
        voiceAnimation = (AnimationDrawable) playIv.getDrawable();
        voiceAnimation.start();
    }
6、傳送圖片實現方法
 /**
     * 選擇本地圖片
     */
    protected void selectPicFromLocal() {
        Intent intent;
        if (Build.VERSION.SDK_INT < 19) {
            intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.setType("image/*");

        } else {
            intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        }
        startActivityForResult(intent, REQUEST_CODE_LOCAL);
    }
返回的data資料處理
/**
     * 選取圖片
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {
            if (requestCode == REQUEST_CODE_LOCAL) {//傳送圖片

                if (data != null) {
                    Uri selectedImage = data.getData();
                    if (selectedImage != null) {
                        sendPicByUri(selectedImage);//傳送圖片
                    }
                }

            }

        }
    }
  /**
     * send image
     *
     * @param selectedImage
     */
    protected void sendPicByUri(Uri selectedImage) {
        String[] filePathColumn = {MediaStore.Images.Media.DATA};
        Cursor cursor = getApplication().getContentResolver().query(selectedImage, filePathColumn, null, null, null);
        if (cursor != null) {
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            String picturePath = cursor.getString(columnIndex);
            cursor.close();
            cursor = null;

            if (picturePath == null || picturePath.equals("null")) {
                Toast toast = Toast.makeText(getApplication(), R.string.cant_find_pictures, Toast.LENGTH_SHORT);
                toast.setGravity(Gravity.CENTER, 0, 0);
                toast.show();
                return;
            }
            sendImageMessage(picturePath);
        } else {
            File file = new File(selectedImage.getPath());
            if (!file.exists()) {
                Toast toast = Toast.makeText(getApplication(), R.string.cant_find_pictures, Toast.LENGTH_SHORT);
                toast.setGravity(Gravity.CENTER, 0, 0);
                toast.show();
                return;

            }
            sendImageMessage(file.getAbsolutePath());
        }

    }

    /**
     * 傳送圖片
     *
     * @param imagePath
     */
    protected void sendImageMessage(String imagePath) {
        EMMessage message = EMMessage.createImageSendMessage(imagePath, false, userName);
        if (message == null) {
            return;
        }
        EMClient.getInstance().chatManager().sendMessage(message);
        Message msg2 = mHandler.obtainMessage();
        msg2.what = 0;
        mHandler.sendMessage(msg2);
    }

最後完整程式碼
package com.example.apple.huanxin.ui;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.AnimationDrawable;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.example.apple.huanxin.R;
import com.example.apple.huanxin.presenter.ChatPresenter;
import com.example.apple.huanxin.presenter.IChatPresenter;
import com.example.apple.huanxin.utils.MyListView;
import com.example.apple.huanxin.utils.PopWindow_image;
import com.facebook.drawee.view.DraweeView;
import com.hyphenate.EMError;
import com.hyphenate.EMMessageListener;
import com.hyphenate.chat.EMChatManager;
import com.hyphenate.chat.EMClient;
import com.hyphenate.chat.EMCmdMessageBody;
import com.hyphenate.chat.EMConversation;
import com.hyphenate.chat.EMImageMessageBody;
import com.hyphenate.chat.EMMessage;
import com.hyphenate.chat.EMTextMessageBody;
import com.hyphenate.chat.EMVoiceMessageBody;
import com.hyphenate.util.ImageUtils;
import com.hyphenate.util.VoiceRecorder;

import net.tsz.afinal.FinalBitmap;

import java.io.File;
import java.util.List;


public class Chat extends AppCompatActivity implements View.OnClickListener, EMMessageListener, IChatPresenter {

    private EditText input_text;
    private Button send;
    private TextView text_content;
    private Button sendImage;
    private Button recording;
    private MyListView listView;

    private VoiceRecorder voiceRecorder;// 環信封裝的錄音功能類

    private String userName;// 當前聊天的 ID

    // 當前會話物件
    private EMConversation mConversation;

    // 訊息監聽器
    private EMMessageListener mMessageListener;

    private final String TAG = "Chat";

    private ChatAdapter adapter;
    private boolean message_more = true;// 聊天記錄是否還有更多
    private String startMsgId;// 獲取聊天記錄時的第一條資訊id

    private ChatPresenter chatPresenter;

    protected static final int REQUEST_CODE_LOCAL = 3;

    private FinalBitmap fb;//顯示圖片

    public static boolean isPlaying = false;

    private MediaPlayer mPlayer = null;// 播放語音的物件(播放器)
    private String playMsgId = null;// 正在播放的語音資訊id,用於判斷播放的是哪一個語音資訊
    private AnimationDrawable voiceAnimation = null;
    private ImageView playIv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat);

        Intent intent = getIntent();
        userName = intent.getStringExtra("userName");
        mMessageListener = this;

        listView = (MyListView) findViewById(R.id.listview);

        chatPresenter = new ChatPresenter(this, this);

        initView();
        initConversation();//獲取歷史記錄資料
    }

    private void initView() {

        fb = FinalBitmap.create(Chat.this);
        fb.configLoadfailImage(R.drawable.ic_launcher);
        fb.configLoadingImage(R.drawable.ic_launcher);

        input_text = (EditText) findViewById(R.id.input_text);
        send = (Button) findViewById(R.id.send);
        send.setOnClickListener(this);

        sendImage = (Button) findViewById(R.id.sendImage);
        sendImage.setOnClickListener(this);

        recording = (Button) findViewById(R.id.recording);

        //錄音時的動畫
        voiceRecorder = new VoiceRecorder(new Handler() {
            @Override
            public void handleMessage(android.os.Message msg) {
                // 切換msg切換圖片
                recording.setBackgroundResource(R.drawable.record_animate_01);
            }
        });

        text_content = (TextView) findViewById(R.id.text_content);
        // 設定textview可滾動,需配合xml佈局設定
        text_content.setMovementMethod(new ScrollingMovementMethod());

        listView.setonRefreshListener(new MyListView.OnRefreshListener() {
            @Override
            public void onRefresh() {
               // new Thread(new LoadMoreMsgRun()).start();// 載入聊天記錄
            }
        });

        /**
         * 錄音
         */
        recording.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                if (MotionEvent.ACTION_DOWN == event.getAction()) {
                    if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                        Toast.makeText(getApplication(), "記憶體卡不存在", Toast.LENGTH_SHORT).show();
                        return false;
                    }

                    v.setPressed(true);

                    try {
                        voiceRecorder.startRecording(null, userName, getApplicationContext());

                    } catch (Exception e) {
                        e.printStackTrace();
                        v.setPressed(false);
                        Toast.makeText(getApplication(), "錄音失敗,請重試", Toast.LENGTH_SHORT).show();

                        if (voiceRecorder != null) {
                            voiceRecorder.discardRecording();
                        }
                    }
                } else if (MotionEvent.ACTION_MOVE == event.getAction()) {

                    if (event.getY() < 0) {
                        Toast.makeText(getApplication(), "鬆開手指,取消傳送", Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(getApplication(), "手指上滑,取消傳送", Toast.LENGTH_SHORT).show();
                    }
                    return true;
                } else if (MotionEvent.ACTION_UP == event.getAction()) {

                    v.setPressed(false);
                    if (event.getY() < 0) {//如果已經上滑後
                        voiceRecorder.discardRecording();
                        return true;
                    }
                    try {
                        int length = voiceRecorder.stopRecoding(); // 停止錄音
                        if (length > 0) {

                            EMMessage message = EMMessage.createVoiceSendMessage(voiceRecorder.getVoiceFilePath(), length, userName);
                            EMClient.getInstance().chatManager().sendMessage(message);
                            recording.setBackgroundResource(R.drawable.record_animate_01);

                            Message msg3 = mHandler.obtainMessage();
                            msg3.what = 0;
                            mHandler.sendMessage(msg3);

                        } else if (length == EMError.FILE_INVALID) {
                            Toast.makeText(getApplication(), "無錄音許可權", Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(getApplication(), "錄音時間太短", Toast.LENGTH_SHORT).show();

                        }
                    } catch (Exception e) {

                    }

                }

                return false;
            }
        });

    }

    /**
     * @param msg
     */
    @Override
    public void setMessage(String msg) {
        Message msg1 = mHandler.obtainMessage();
        msg1.what = 0;
        msg1.obj = msg;
        mHandler.sendMessage(msg1);
    }

    /**
     * 下拉更多
     */
//    class LoadMoreMsgRun implements Runnable {
//        public void run() {
//            // 判斷是否還有更多
//            if (message_more == true) {
//                // 獲取startMsgId之前的pagesize條訊息,此方法獲取的messages
//                // sdk會自動存入到此會話中,app中無需再次把獲取到的messages新增到會話中
//
//                mConversation.loadMoreMsgFromDB(mConversation.getAllMessages().get(0).getMsgId(), 10);// 載入更多記錄
//
//                if (mConversation.getUnreadMsgCount() > mConversation.getAllMsgCount()) {// 表示獲取到更多資訊了
//
////                    loadFinish(1, mConversation.get - messageCount);// 重新設定介面卡
////                    messageCount = conversation.getMsgCount();
//                    startMsgId = mConversation.getAllMessages().get(0).getMsgId();// 設定第一條資訊的id
//
//                } else { // 沒有獲取到
//                    loadFinish(2, 0); // 提示沒有更多
//                    message_more = false;// 設定沒有更多標記
//                }
//            } else if (message_more == false) {
//                loadFinish(2, 0); // 提示沒有更多
//            }
//
//            loadFinish(3, 0);// lisetview下拉重新整理完成
//        }
//    }

    // 載入完成後的ui處理
//    private void loadFinish(final int tag, final int index) {
//        runOnUiThread(new Runnable() {
//            public void run() {
//                if (tag == 1) {
//                    // 重新設定介面卡
//                    listView.setAdapter(adapter);
//                    listView.setSelection(index);
//                } else if (tag == 2) {
//                    // toast("沒有更多記錄了");
//                } else if (tag == 3)
//                    listView.onRefreshComplete(); // 重新整理完成
//            }
//        });
//    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {

            case R.id.send:
                String content = input_text.getText().toString();
                chatPresenter.sendMessage(content, userName);
                break;

            case R.id.sendImage:
                selectPicFromLocal();

                break;

            default:

                break;

        }
    }

    /**
     * 選擇本地圖片
     */
    protected void selectPicFromLocal() {
        Intent intent;
        if (Build.VERSION.SDK_INT < 19) {
            intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.setType("image/*");

        } else {
            intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        }
        startActivityForResult(intent, REQUEST_CODE_LOCAL);
    }

    /**
     * 初始化會話物件,並且根據需要載入更多訊息
     */
    private void initConversation() {

        /**
         * 初始化會話物件,這裡有三個引數麼,
         * 第一個表示會話的當前聊天的 useranme 或者 groupid
         * 第二個是繪畫型別可以為空
         * 第三個表示如果會話不存在是否建立
         */
        mConversation = EMClient.getInstance().chatManager().getConversation(userName, null, true);

        // 設定當前會話未讀數為 0
        mConversation.markAllMessagesAsRead();
        // startMsgId = mConversation.getAllMessages().get(0).getMsgId();// 設定第一條資訊的id
        Log.e(TAG, "mConversation.getAllMessages()=" + mConversation.getAllMessages());
        if (mConversation.getAllMessages() != null) {
            adapter = new ChatAdapter(mConversation.getAllMessages());
            listView.setAdapter(adapter);
            listView.setSelection(listView.getBottom());
        }

        int count = mConversation.getAllMessages().size();
        if (count < mConversation.getAllMsgCount() && count < 20) {
            // 獲取已經在列表中的最上邊的一條訊息id
            String msgId = mConversation.getAllMessages().get(0).getMsgId();
            // 分頁載入更多訊息,需要傳遞已經載入的訊息的最上邊一條訊息的id,以及需要載入的訊息的條數
            mConversation.loadMoreMsgFromDB(msgId, 20 - count);
        }
    }

    /**
     * 自定義實現Handler,主要用於重新整理UI操作
     */
    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 0:
                    mConversation = EMClient.getInstance().chatManager().getConversation(userName, null, true);
                    adapter.emMessages.add(mConversation.getLastMessage());
                    adapter.notifyDataSetChanged();
                    listView.setSelection(listView.getBottom());
                    break;

            }
        }
    };


    @Override
    protected void onResume() {
        super.onResume();
        // 新增訊息監聽
        EMClient.getInstance().chatManager().addMessageListener(mMessageListener);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // 移除訊息監聽
        EMClient.getInstance().chatManager().removeMessageListener(mMessageListener);
    }

    @Override
    protected void onPause() {
        super.onPause();
        try {
            //停止語音播放
            if (mPlayer.isPlaying()) {

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 收到新訊息
     *
     * @param messages
     */
    @Override
    public void onMessageReceived(List<EMMessage> messages) {
        //收到訊息
        // 迴圈遍歷當前收到的訊息
        for (EMMessage message : messages) {
            if (message.getFrom().equals(userName)) {
                // 設定訊息為已讀
                mConversation.markMessageAsRead(message.getMsgId());

                // 因為訊息監聽回撥這裡是非ui執行緒,所以要用handler去更新ui
                Message msg = mHandler.obtainMessage();
                msg.what = 0;
                msg.obj = message;
                mHandler.sendMessage(msg);
            } else {
                // 如果訊息不是當前會話的訊息傳送通知欄通知
            }
        }
    }

    /**
     * 收到新的 CMD 訊息
     *
     * @param list
     */
    @Override
    public void onCmdMessageReceived(List<EMMessage> list) {
        for (int i = 0; i < list.size(); i++) {
            // 透傳訊息
            EMMessage cmdMessage = list.get(i);
            EMCmdMessageBody body = (EMCmdMessageBody) cmdMessage.getBody();
            Log.e("nsc", body.action());
        }
    }

    /**
     * 收到新的已讀回執
     *
     * @param list
     */
    @Override
    public void onMessageReadAckReceived(List<EMMessage> list) {

    }

    /**
     * 收到新的傳送回執
     *
     * @param list
     */
    @Override
    public void onMessageDeliveryAckReceived(List<EMMessage> list) {

    }

    /**
     * 訊息的狀態改變
     *
     * @param emMessage
     * @param o
     */
    @Override
    public void onMessageChanged(EMMessage emMessage, Object o) {

    }

    class ChatAdapter extends BaseAdapter {
        List<EMMessage> emMessages;

        ChatAdapter(List<EMMessage> emMessages) {
            this.emMessages = emMessages;
        }

        @Override
        public int getCount() {
            return emMessages.size();
        }

        @Override
        public Object getItem(int i) {
            return emMessages.get(i);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {

            final EMMessage message = emMessages.get(i);//每條訊息
            if (message.getFrom().equals(userName)) {
                view = getLayoutInflater().inflate(R.layout.chat_item1, null);
            } else {
                view = getLayoutInflater().inflate(R.layout.chat_item2, null);
            }

            final TextView time = (TextView) view.findViewById(R.id.time);
            ImageView head = (ImageView) view.findViewById(R.id.head);
//            Bitmap b = message.getBody()
//            head.setImageBitmap();

            TextView tv = (TextView) view.findViewById(R.id.tv);
            final DraweeView image = (DraweeView) view.findViewById(R.id.image);

            long msgTime = message.getMsgTime(); // 資訊時間
            if (i == 0 || msgTime - emMessages.get(i - 1).getMsgTime() > 120000) {
                time.setVisibility(View.VISIBLE);

                long dateTaken = System.currentTimeMillis(); // 當前系統時間
                String currentDate = (String) DateFormat.format("yyyy/MM/dd",
                        dateTaken); // 當前系統日期
                String messageDate = (String) DateFormat.format("yyyy/MM/dd",
                        msgTime); // 資訊的日期
                if (currentDate.equals(messageDate)) { // 如果是當天

                    time.setText(DateFormat.format("kk:mm:ss", msgTime));// 只顯示時間
                } else {
                    time.setText(DateFormat.format("yyyy/MM/dd kk:mm:ss",// 顯示日期加時間
                            msgTime));
                }
            }

            if (message.getType() == EMMessage.Type.TXT) {//文字顯示
                String mess = ((EMTextMessageBody) message.getBody()).getMessage();
                tv.setText(mess);
            } else if (message.getType() == EMMessage.Type.IMAGE) {//圖片顯示
                tv.setVisibility(View.GONE);
                image.setVisibility(View.VISIBLE);

                if (message.getFrom().equals(userName)) { // 對方發的訊息
                    String ThumbnailUrl = ((EMImageMessageBody) message.getBody()).getThumbnailUrl(); // 獲取縮圖片地址
                    String thumbnailPath = ImageUtils.getScaledImage(getApplication(), ThumbnailUrl);
                    String imageRemoteUrl = ((EMImageMessageBody) message.getBody()).getRemoteUrl();// 獲取遠端原圖片地址

                    fb.display(image, thumbnailPath);//顯示圖片
                    imageClick(image, imageRemoteUrl);//圖片新增監聽
                } else {
                    // 自己發的訊息
                    String LocalUrl = ((EMImageMessageBody) message.getBody()).getLocalUrl(); // 獲取本地圖片地址
                    Bitmap bm = ImageUtils.decodeScaleImage(LocalUrl, 160, 160);//獲取縮圖
                    image.setImageBitmap(bm);//顯示圖片
                    Log.e(TAG, "bm=" + bm + "==LocalUrl=" + LocalUrl);

                    imageClick(image, LocalUrl);//圖片新增監聽
                }
            } else if (message.getType() == EMMessage.Type.VOICE) {//語音
                tv.setVisibility(View.GONE);
                tv.setGravity(Gravity.TOP);
                image.setVisibility(View.VISIBLE);
                tv.setText(((EMVoiceMessageBody) message.getBody()).getLength() + "”"); // 設定語音的時長
                // 設定為語音的圖片
                if (message.direct() == EMMessage.Direct.RECEIVE) {
                    image.setImageResource(R.drawable.chatfrom_voice_playing);
                } else {
                    image.setImageResource(R.drawable.chatto_voice_playing);
                }

                image.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View arg0) {
                        // 開始播放錄音
                        startPlay(message, image);
                    }
                });

            }

            return view;
        }

        // 圖片點選監聽
        private void imageClick(ImageView image, final String imageUrl) {
            image.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View arg0) {

                    //new PopWindow_Image(Chat.this, imageUrl).showAtLocation(arg0, 0, 0, 0);
                    new PopWindow_image(fb, Chat.this, imageUrl).showAtLocation(arg0, 0, 0, 0);
                }
            });
        }
    }

    // 開始播放
    private void startPlay(final EMMessage message, ImageView image) {

        EMVoiceMessageBody voiceBody = (EMVoiceMessageBody) message.getBody();

        if (message.direct() == EMMessage.Direct.SEND) {
            // for sent msg, we will try to play the voice file directly
            playVoice(voiceBody.getLocalUrl(), message, image);
        } else {
            if (message.status() == EMMessage.Status.SUCCESS) {
                playVoice(voiceBody.getLocalUrl(), message, image);

            } else if (message.status() == EMMessage.Status.INPROGRESS) {
                //toast("資訊還在傳送中");
                Toast.makeText(getApplication(), "資訊還在傳送中", Toast.LENGTH_SHORT).show();
            } else if (message.status() == EMMessage.Status.FAIL) {
                // toast("接收失敗");
                Toast.makeText(getApplication(), "接收失敗", Toast.LENGTH_SHORT).show();
            }
        }
    }

    // 播放錄音
    public void playVoice(String filePath, final EMMessage message, final ImageView image) {
        File file = new File(filePath);
        if (!file.exists() || !file.isFile()) {
            System.err.println("file not exist");
            // toast("語音檔案不存在");
            return;
        }
        playMsgId = message.getMsgId();
        mPlayer = new MediaPlayer();

        try {
            mPlayer.setDataSource(filePath);
            mPlayer.prepare();
            mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

                @Override
                public void onCompletion(MediaPlayer mp) {
                    // TODO Auto-generated method stub
                    if (mPlayer == null) // 表示因為要播放其他語音時已經被停止了,所以不需要再次呼叫停止
                        return;
                    stopPlayVoice(message); // stop animation
                }
            });
            isPlaying = true;
            mPlayer.start();
            playIv = image;
            showAnimation(message);

        } catch (Exception e) {
        }
    }

    /**
     * 停止語音
     *
     * @param message
     */
    public void stopPlayVoice(final EMMessage message) {
        voiceAnimation.stop();
        if (message.direct() == EMMessage.Direct.RECEIVE) {
            playIv.setImageResource(R.drawable.chatfrom_voice_playing);
        } else {
            playIv.setImageResource(R.drawable.chatto_voice_playing);
        }
        // stop play voice
        if (mPlayer != null) {
            mPlayer.stop();
            mPlayer.release();
        }
        isPlaying = false;
        playMsgId = null;
        adapter.notifyDataSetChanged();
    }

    // show the voice playing animation
    private void showAnimation(final EMMessage message) {

        // play voice, and start animation
        if (message.direct() == EMMessage.Direct.RECEIVE) {
            playIv.setImageResource(R.drawable.voice_from_icon);
        } else {
            playIv.setImageResource(R.drawable.voice_to_icon);
        }
        voiceAnimation = (AnimationDrawable) playIv.getDrawable();
        voiceAnimation.start();
    }


    /**
     * 選取圖片
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {
            if (requestCode == REQUEST_CODE_LOCAL) {//傳送圖片

                if (data != null) {
                    Uri selectedImage = data.getData();
                    if (selectedImage != null) {
                        sendPicByUri(selectedImage);//傳送圖片
                    }
                }

            }

        }
    }

    /**
     * send image
     *
     * @param selectedImage
     */
    protected void sendPicByUri(Uri selectedImage) {
        String[] filePathColumn = {MediaStore.Images.Media.DATA};
        Cursor cursor = getApplication().getContentResolver().query(selectedImage, filePathColumn, null, null, null);
        if (cursor != null) {
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            String picturePath = cursor.getString(columnIndex);
            cursor.close();
            cursor = null;

            if (picturePath == null || picturePath.equals("null")) {
                Toast toast = Toast.makeText(getApplication(), R.string.cant_find_pictures, Toast.LENGTH_SHORT);
                toast.setGravity(Gravity.CENTER, 0, 0);
                toast.show();
                return;
            }
            sendImageMessage(picturePath);
        } else {
            File file = new File(selectedImage.getPath());
            if (!file.exists()) {
                Toast toast = Toast.makeText(getApplication(), R.string.cant_find_pictures, Toast.LENGTH_SHORT);
                toast.setGravity(Gravity.CENTER, 0, 0);
                toast.show();
                return;

            }
            sendImageMessage(file.getAbsolutePath());
        }

    }

    /**
     * 傳送圖片
     *
     * @param imagePath
     */
    protected void sendImageMessage(String imagePath) {
        EMMessage message = EMMessage.createImageSendMessage(imagePath, false, userName);
        if (message == null) {
            return;
        }
        EMClient.getInstance().chatManager().sendMessage(message);
        Message msg2 = mHandler.obtainMessage();
        msg2.what = 0;
        mHandler.sendMessage(msg2);
    }
}
程式碼下載地址:由於工程太大,所以上傳到github上了,https://github.com/ningxingxing/-demo