/** * Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.kaixin.android.activity; import java.io.File; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.PowerManager; import android.provider.MediaStore; import android.support.v4.view.ViewPager; import android.text.ClipboardManager; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.easemob.EMCallBack; import com.easemob.chat.EMChat; import com.easemob.chat.EMChatManager; import com.easemob.chat.EMChatOptions; import com.easemob.chat.EMConversation; import com.easemob.chat.EMGroup; import com.easemob.chat.EMMessage; import com.easemob.chat.OnMessageNotifyListener; import com.easemob.chat.OnNotificationClickListener; import com.easemob.chat.EMMessage.ChatType; import com.easemob.chat.ImageMessageBody; import com.easemob.chat.LocationMessageBody; import com.easemob.chat.TextMessageBody; import com.easemob.chat.VoiceMessageBody; import com.easemob.exceptions.EaseMobException; import com.easemob.util.PathUtil; import com.easemob.util.VoiceRecorder; import com.kaixin.android.KXActivity; import com.kaixin.android.R; import com.kaixin.android.adapter.ExpressionAdapter; import com.kaixin.android.adapter.ExpressionPagerAdapter; import com.kaixin.android.adapter.MessageAdapter; import com.kaixin.android.listener.VoicePlayClickListener; import com.kaixin.android.result.ConversationResult; import com.kaixin.android.service.MessagePushService; import com.kaixin.android.utils.CommonUtils; import com.kaixin.android.utils.Encrypter; import com.kaixin.android.utils.ImageUtil; import com.kaixin.android.utils.SmileUtils; import com.kaixin.android.utils.StorageUtil; import com.kaixin.android.utils.TextUtil; import com.kaixin.android.view.ExpandGridView; import com.kaixin.android.view.PasteEditText; /** * 聊天页面 * */ public class ChatActivity extends KXActivity implements OnClickListener { private static final int REQUEST_CODE_PICK_PICTURE = 1; private static final int REQUEST_CODE_EMPTY_HISTORY = 2; public static final int REQUEST_CODE_CONTEXT_MENU = 3; private static final int REQUEST_CODE_MAP = 4; public static final int REQUEST_CODE_TEXT = 5; public static final int REQUEST_CODE_VOICE = 6; public static final int REQUEST_CODE_PICTURE = 7; public static final int REQUEST_CODE_LOCATION = 8; public static final int REQUEST_CODE_NET_DISK = 9; public static final int REQUEST_CODE_RESEND_NET_DISK = 10; public static final int REQUEST_CODE_COPY_AND_PASTE = 11; public static final int REQUEST_CODE_PICK_VIDEO = 12; public static final int REQUEST_CODE_DOWNLOAD_VIDEO = 13; public static final int REQUEST_CODE_VIDEO = 14; public static final int REQUEST_CODE_DOWNLOAD_VOICE = 15; public static final int REQUEST_CODE_SELECT_USER_CARD = 16; public static final int REQUEST_CODE_SEND_USER_CARD = 17; public static final int REQUEST_CODE_CAMERA = 18; public static final int REQUEST_CODE_LOCAL = 19; public static final int REQUEST_CODE_CLICK_DESTORY_IMG = 20; public static final int REQUEST_CODE_GROUP_DETAIL = 21; public static final int RESULT_CODE_COPY = 1; public static final int RESULT_CODE_DELETE = 2; public static final int RESULT_CODE_FORWARD = 3; public static final int RESULT_CODE_OPEN = 4; public static final int RESULT_CODE_DWONLOAD = 5; public static final int RESULT_CODE_TO_CLOUD = 6; public static final int RESULT_CODE_EXIT_GROUP = 7; public static final int CHATTYPE_SINGLE = 1; public static final int CHATTYPE_GROUP = 2; public static final String COPY_IMAGE = "EASEMOBIMG"; private View recordingContainer; private ImageView micImage; private TextView recordingHint; private ListView listView; private PasteEditText mEditTextContent; private View buttonSetModeKeyboard; private View buttonSetModeVoice; private View buttonSend; private View buttonPressToSpeak; private ViewPager expressionViewpager; private LinearLayout expressionContainer; private LinearLayout btnContainer; private ImageView locationImgview; private View more; private int position; private ClipboardManager clipboard; private InputMethodManager manager; private List<String> reslist; private Drawable[] micImages; private int chatType; private EMConversation conversation; private NewMessageBroadcastReceiver receiver; public static ChatActivity activityInstance = null; // 给谁发送消息 private String toChatUsername; private VoiceRecorder voiceRecorder; private MessageAdapter adapter; private File cameraFile; static int resendPos; private ImageView iv_emoticons_normal; private ImageView iv_emoticons_checked; private RelativeLayout edittext_layout; private ProgressBar loadmorePB; private boolean isloading; private final int pagesize = 20; private boolean haveMoreData = true; private Handler micImageHandler = new Handler() { @Override public void handleMessage(android.os.Message msg) { // 切换msg切换图片 micImage.setImageDrawable(micImages[msg.what]); } }; private EMGroup group; private String mEmail; private String mName; private String mAvatar; private Button mBack; private RelativeLayout mParent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.chat_activity); EMChatManager.getInstance().login(StorageUtil.getString(ChatActivity.this, "username"), Encrypter.md5(StorageUtil.getString(ChatActivity.this, "password")), new EMCallBack() { @Override public void onError(int arg0, final String errorMsg) { runOnUiThread(new Runnable() { public void run() { Toast.makeText(ChatActivity.this, "登录聊天服务器失败:" + errorMsg, Toast.LENGTH_SHORT).show(); } }); } @Override public void onProgress(int arg0, String arg1) { } @Override public void onSuccess() { runOnUiThread(new Runnable() { public void run() { } }); } }); initView(); setUpView(); } /** * initView */ protected void initView() { mParent = (RelativeLayout) findViewById(R.id.root_layout); recordingContainer = findViewById(R.id.recording_container); micImage = (ImageView) findViewById(R.id.mic_image); recordingHint = (TextView) findViewById(R.id.recording_hint); listView = (ListView) findViewById(R.id.list); mBack = (Button) findViewById(R.id.chat_back); mEditTextContent = (PasteEditText) findViewById(R.id.et_sendmessage); buttonSetModeKeyboard = findViewById(R.id.btn_set_mode_keyboard); edittext_layout = (RelativeLayout) findViewById(R.id.edittext_layout); buttonSetModeVoice = findViewById(R.id.btn_set_mode_voice); buttonSend = findViewById(R.id.btn_send); buttonPressToSpeak = findViewById(R.id.btn_press_to_speak); expressionViewpager = (ViewPager) findViewById(R.id.vPager); expressionContainer = (LinearLayout) findViewById(R.id.ll_face_container); btnContainer = (LinearLayout) findViewById(R.id.ll_btn_container); locationImgview = (ImageView) findViewById(R.id.btn_location); iv_emoticons_normal = (ImageView) findViewById(R.id.iv_emoticons_normal); iv_emoticons_checked = (ImageView) findViewById(R.id.iv_emoticons_checked); loadmorePB = (ProgressBar) findViewById(R.id.pb_load_more); iv_emoticons_normal.setVisibility(View.VISIBLE); iv_emoticons_checked.setVisibility(View.INVISIBLE); more = findViewById(R.id.more); // 动画资源文件,用于录制语音时 micImages = new Drawable[] { getResources().getDrawable(R.drawable.record_animate_01), getResources().getDrawable(R.drawable.record_animate_02), getResources().getDrawable(R.drawable.record_animate_03), getResources().getDrawable(R.drawable.record_animate_04), getResources().getDrawable(R.drawable.record_animate_05), getResources().getDrawable(R.drawable.record_animate_06), getResources().getDrawable(R.drawable.record_animate_07), getResources().getDrawable(R.drawable.record_animate_08), getResources().getDrawable(R.drawable.record_animate_09), getResources().getDrawable(R.drawable.record_animate_10), getResources().getDrawable(R.drawable.record_animate_11), getResources().getDrawable(R.drawable.record_animate_12), getResources().getDrawable(R.drawable.record_animate_13), getResources().getDrawable(R.drawable.record_animate_14), }; // 表情list reslist = getExpressionRes(35); // 初始化表情viewpager List<View> views = new ArrayList<View>(); View gv1 = getGridChildView(1); View gv2 = getGridChildView(2); views.add(gv1); views.add(gv2); expressionViewpager.setAdapter(new ExpressionPagerAdapter(views)); voiceRecorder = new VoiceRecorder(micImageHandler); buttonPressToSpeak.setOnTouchListener(new PressToSpeakListen()); // 监听文字框 mEditTextContent.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (!TextUtils.isEmpty(s)) { buttonSetModeVoice.setVisibility(View.GONE); buttonSend.setVisibility(View.VISIBLE); } else { if (buttonSetModeKeyboard.getVisibility() != View.VISIBLE) { buttonSetModeVoice.setVisibility(View.VISIBLE); buttonSend.setVisibility(View.GONE); } } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); mBack.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { finish(); } }); } private void setUpView() { Intent intent = new Intent(this, MessagePushService.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); stopService(intent); // 获取当前聊天的用户的姓名和头像,并显示姓名到标题栏 mEmail = getIntent().getStringExtra("email"); mName = getIntent().getStringExtra("name"); mAvatar = getIntent().getStringExtra("avatar"); activityInstance = this; iv_emoticons_normal.setOnClickListener(this); iv_emoticons_checked.setOnClickListener(this); // position = getIntent().getIntExtra("position", -1); clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); wakeLock = ((PowerManager) getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "demo"); // 判断单聊还是群聊 toChatUsername = mEmail; ((TextView) findViewById(R.id.chat_title)).setText(mName); conversation = EMChatManager.getInstance().getConversation(toChatUsername); // 把此会话的未读数置为0 conversation.resetUnsetMsgCount(); adapter = new MessageAdapter(mKXApplication,this, toChatUsername, chatType, mAvatar); // 显示消息 listView.setAdapter(adapter); listView.setOnScrollListener(new ListScrollListener()); int count = listView.getCount(); if (count > 0) { listView.setSelection(count - 1); } listView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { hideKeyboard(); more.setVisibility(View.GONE); iv_emoticons_normal.setVisibility(View.VISIBLE); iv_emoticons_checked.setVisibility(View.INVISIBLE); expressionContainer.setVisibility(View.GONE); btnContainer.setVisibility(View.GONE); return false; } }); // 注册接收消息广播 receiver = new NewMessageBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(EMChatManager.getInstance().getNewMessageBroadcastAction()); // 设置广播的优先级别大于Mainacitivity,这样如果消息来的时候正好在chat页面,直接显示消息,而不是提示消息未读 intentFilter.setPriority(5); registerReceiver(receiver, intentFilter); // 注册一个ack回执消息的BroadcastReceiver IntentFilter ackMessageIntentFilter = new IntentFilter(EMChatManager.getInstance().getAckMessageBroadcastAction()); ackMessageIntentFilter.setPriority(5); registerReceiver(ackMessageReceiver, ackMessageIntentFilter); // show forward message if the message is not null String forward_msg_id = getIntent().getStringExtra("forward_msg_id"); if (forward_msg_id != null) { // 显示发送要转发的消息 forwardMessage(forward_msg_id); } // 获取到配置options对象 EMChatOptions options = EMChatManager.getInstance().getChatOptions(); options.setNotificationEnable(true); // 设置自定义的文字提示 options.setNotifyText(new OnMessageNotifyListener() { @Override public String onNewMessageNotify(EMMessage message) { // 可以根据message的类型提示不同文字,这里为一个简单的示例 try { return "你的好基友" + message.getStringAttribute("mName") + "发来了一条消息"; } catch (EaseMobException e) { // TODO Auto-generated catch block e.printStackTrace(); } return ""; } @Override public String onLatestMessageNotify(EMMessage message, int fromUsersNum, int messageNum) { return fromUsersNum + "个基友,发来了" + messageNum + "条消息"; } }); /*options.setOnNotificationClickListener(new OnNotificationClickListener() { @Override public Intent onNotificationClick(EMMessage message) { Intent intent = new Intent(C.this, ChatActivity1.class); intent.putExtra("email", message.getFrom()); intent.putExtra("isNews", "yes"); intent.putExtra("isNews", message.getMsgId()); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (msgReceiver != null) { try { unregisterReceiver(msgReceiver); } catch (Exception e) { e.printStackTrace(); } } return intent; } });*/ // timer = new Timer(); // timer.schedule(new RemindTask(), 1* 1000, 4 * 1000); mFaceGridView.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 获取当前光标所在位置 int currentPosition = mEditTextContent.getSelectionStart(); // 添加有表情的文字 mEditTextContent.setText(new TextUtil(mKXApplication).replace(mEditTextContent .getText().insert(currentPosition, mKXApplication.mFacesText.get(position)))); // 关闭表情对话框 dismissFace(); } }); //app初始化完毕 EMChat.getInstance().setAppInited(); } /** * 转发消息 * * @param forward_msg_id */ protected void forwardMessage(String forward_msg_id) { EMMessage forward_msg = EMChatManager.getInstance().getMessage(forward_msg_id); EMMessage.Type type = forward_msg.getType(); switch (type) { case TXT: // 获取消息内容,发送消息 String content = ((TextMessageBody) forward_msg.getBody()).getMessage(); sendText(content); break; case IMAGE: // 发送图片 String filePath = ((ImageMessageBody) forward_msg.getBody()).getLocalUrl(); if (filePath != null) { File file = new File(filePath); if (!file.exists()) { // 不存在大图发送缩略图 filePath = ImageUtil.getThumbnailImagePath(filePath); } sendPicture(filePath); } break; default: break; } } /** * */ protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_CODE_EXIT_GROUP) { setResult(RESULT_OK); finish(); return; } if (requestCode == REQUEST_CODE_CONTEXT_MENU) { switch (resultCode) { case RESULT_CODE_COPY: // 复制消息 EMMessage copyMsg = ((EMMessage) adapter.getItem(data.getIntExtra("position", -1))); if (copyMsg.getType() == EMMessage.Type.IMAGE) { ImageMessageBody imageBody = (ImageMessageBody) copyMsg.getBody(); // 加上一个特定前缀,粘贴时知道这是要粘贴一个图片 clipboard.setText(COPY_IMAGE + imageBody.getLocalUrl()); } else { // clipboard.setText(SmileUtils.getSmiledText(ChatActivity.this, // ((TextMessageBody) copyMsg.getBody()).getMessage())); clipboard.setText(((TextMessageBody) copyMsg.getBody()).getMessage()); } break; case RESULT_CODE_DELETE: // 删除消息 EMMessage deleteMsg = (EMMessage) adapter.getItem(data.getIntExtra("position", -1)); conversation.removeMessage(deleteMsg.getMsgId()); adapter.notifyDataSetChanged(); listView.setSelection(data.getIntExtra("position", adapter.getCount()) - 1); break; /*case RESULT_CODE_FORWARD: // 转发消息 EMMessage forwardMsg = (EMMessage) adapter.getItem(data.getIntExtra("position", 0)); Intent intent = new Intent(this, ForwardMessageActivity.class); intent.putExtra("forward_msg_id", forwardMsg.getMsgId()); startActivity(intent); break;*/ default: break; } } if (resultCode == RESULT_OK) { // 清空消息 if (requestCode == REQUEST_CODE_EMPTY_HISTORY) { // 清空会话 EMChatManager.getInstance().clearConversation(toChatUsername); adapter.notifyDataSetChanged(); } else if (requestCode == REQUEST_CODE_CAMERA) { // 发送照片 if (cameraFile != null && cameraFile.exists()) sendPicture(cameraFile.getAbsolutePath()); } else if (requestCode == REQUEST_CODE_LOCAL) { // 发送本地图片 if (data != null) { Uri selectedImage = data.getData(); if (selectedImage != null) sendPicByUri(selectedImage); } } else if (requestCode == REQUEST_CODE_MAP) { // 地图 double latitude = data.getDoubleExtra("latitude", 0); double longitude = data.getDoubleExtra("longitude", 0); String locationAddress = data.getStringExtra("address"); if (locationAddress != null && !locationAddress.equals("")) { more(more); sendLocationMsg(latitude, longitude, "", locationAddress); } else { Toast.makeText(this, "无法获取到您的位置信息!", 0).show(); } // 重发消息 } else if (requestCode == REQUEST_CODE_TEXT) { resendMessage(); } else if (requestCode == REQUEST_CODE_VOICE) { resendMessage(); } else if (requestCode == REQUEST_CODE_PICTURE) { resendMessage(); } else if (requestCode == REQUEST_CODE_LOCATION) { resendMessage(); } else if (requestCode == REQUEST_CODE_COPY_AND_PASTE) { // 粘贴 if (!TextUtils.isEmpty(clipboard.getText())) { String pasteText = clipboard.getText().toString(); if (pasteText.startsWith(COPY_IMAGE)) { // 把图片前缀去掉,还原成正常的path sendPicture(pasteText.replace(COPY_IMAGE, "")); } } } else if (conversation.getMsgCount() > 0) { adapter.notifyDataSetChanged(); setResult(RESULT_OK); } else if (requestCode == REQUEST_CODE_GROUP_DETAIL) { EMChatManager.getInstance().getConversation(toChatUsername); adapter.notifyDataSetChanged(); } } } /** * 点击事件 * * @param view */ @Override public void onClick(View view) { int id = view.getId(); if (id == R.id.btn_send) {// 点击发送按钮(发文字和表情) String s = mEditTextContent.getText().toString(); sendText(s); } else if (id == R.id.btn_take_picture) { selectPicFromCamera();// 点击照相图标 } else if (id == R.id.btn_picture) { selectPicFromLocal(); // 点击图片图标 } else if (id == R.id.btn_location) { // 位置 startActivityForResult(new Intent(this, BaiduMapActivity.class), REQUEST_CODE_MAP); } else if (id == R.id.btn_smile) { // 点击表情图标 onSendSmile(); } else if (id == R.id.iv_emoticons_normal) // 点击显示表情框 { // 显示表情对话框 showFace(mParent); /*more.setVisibility(View.VISIBLE); iv_emoticons_normal.setVisibility(View.INVISIBLE); iv_emoticons_checked.setVisibility(View.VISIBLE); btnContainer.setVisibility(View.GONE); expressionContainer.setVisibility(View.VISIBLE);*/ hideKeyboard(); } else if (id == R.id.iv_emoticons_checked) // 点击隐藏表情框 { // 关闭表情对话框 dismissFace(); /*iv_emoticons_normal.setVisibility(View.VISIBLE); iv_emoticons_checked.setVisibility(View.INVISIBLE); btnContainer.setVisibility(View.VISIBLE); expressionContainer.setVisibility(View.GONE);*/ more.setVisibility(View.GONE); } } /** * 照相获取图片 */ public void selectPicFromCamera() { /*if(!CommonUtils.isExitsSdcard()){ Toast.makeText(getApplicationContext(), "SD卡不存在,不能拍照", 0).show(); return; }*/ cameraFile = new File(PathUtil.getInstance().getImagePath(), StorageUtil.getString(this, "username") + System.currentTimeMillis() + ".jpg"); cameraFile.getParentFile().mkdirs(); startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE).putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraFile)), REQUEST_CODE_CAMERA); } /** * 从图库获取图片 */ public 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 onSendSmile() { btnContainer.setVisibility(View.GONE); expressionContainer.setVisibility(View.VISIBLE); } /** * 发送文本消息 * * @param content * message content * @param isResend * boolean resend */ private void sendText(String content) { mKXApplication.mSaveConversationDao.saveConversation(new ConversationResult(mName, mEmail, mAvatar)); if (content.length() > 0) { EMMessage message = EMMessage.createSendMessage(EMMessage.Type.TXT); // 如果是群聊,设置chattype,默认是单聊 // if (chatType == CHATTYPE_GROUP) // message.setChatType(ChatType.GroupChat); TextMessageBody txtBody = new TextMessageBody(content); // 设置消息body message.addBody(txtBody); // System.out.println(toChatUsername + "============toChatUsername"); // 设置要发给谁,用户username或者群聊groupid message.setReceipt(toChatUsername); message.setAttribute("mName", StorageUtil.getString(this, "nickname")); message.setAttribute("mAvatar", StorageUtil.getString(this, "mAvatar")); // 把messgage加到conversation中 conversation.addMessage(message); // 通知adapter有消息变动,adapter会根据加入的这条message显示消息和调用sdk的发送方法 adapter.notifyDataSetChanged(); listView.setSelection(listView.getCount() - 1); mEditTextContent.setText(""); setResult(RESULT_OK); } } /** * 发送语音 * * @param filePath * @param fileName * @param length * @param isResend */ private void sendVoice(String filePath, String fileName, String length, boolean isResend) { if (!(new File(filePath).exists())) { return; } mKXApplication.mSaveConversationDao.saveConversation(new ConversationResult(mName, mEmail, mAvatar)); try { final EMMessage message = EMMessage.createSendMessage(EMMessage.Type.VOICE); // 如果是群聊,设置chattype,默认是单聊 if (chatType == CHATTYPE_GROUP) message.setChatType(ChatType.GroupChat); String to = toChatUsername; message.setReceipt(to); int len = Integer.parseInt(length); VoiceMessageBody body = new VoiceMessageBody(new File(filePath), len); message.addBody(body); message.setAttribute("mName", StorageUtil.getString(this, "nickname")); message.setAttribute("mAvatar", StorageUtil.getString(this, "mAvatar")); conversation.addMessage(message); adapter.notifyDataSetChanged(); listView.setSelection(listView.getCount() - 1); setResult(RESULT_OK); // send file // sendVoiceSub(filePath, fileName, message); } catch (Exception e) { e.printStackTrace(); } } /** * 发送图片 * * @param filePath */ private void sendPicture(final String filePath) { int rowId = 0; String to = toChatUsername; mKXApplication.mSaveConversationDao.saveConversation(new ConversationResult(mName, mEmail, mAvatar)); // create and add image message in view final EMMessage message = EMMessage.createSendMessage(EMMessage.Type.IMAGE); // 如果是群聊,设置chattype,默认是单聊 if (chatType == CHATTYPE_GROUP) message.setChatType(ChatType.GroupChat); message.setReceipt(to); message.setAttribute("mName", StorageUtil.getString(this, "nickname")); message.setAttribute("mAvatar", StorageUtil.getString(this, "mAvatar")); ImageMessageBody body = new ImageMessageBody(new File(filePath)); // 默认超过100k的图片会压缩后发给对方,可以设置成发送原图 // body.setSendOriginalImage(true); message.addBody(body); conversation.addMessage(message); listView.setAdapter(adapter); adapter.notifyDataSetChanged(); listView.setSelection(listView.getCount() - 1); setResult(RESULT_OK); // more(more); } /** * 根据图库图片uri发送图片 * * @param selectedImage */ private void sendPicByUri(Uri selectedImage) { // String[] filePathColumn = { MediaStore.Images.Media.DATA }; Cursor cursor = getContentResolver().query(selectedImage, null, null, null, null); cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex("_data"); String picturePath = cursor.getString(columnIndex); cursor.close(); if (picturePath == null || picturePath.equals("null")) { Toast toast = Toast.makeText(this, "找不到图片", Toast.LENGTH_SHORT); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); return; } sendPicture(picturePath); } /** * 发送位置信息 * * @param latitude * @param longitude * @param imagePath * @param locationAddress */ private void sendLocationMsg(double latitude, double longitude, String imagePath, String locationAddress) { mKXApplication.mSaveConversationDao.saveConversation(new ConversationResult(mName, mEmail, mAvatar)); EMMessage message = EMMessage.createSendMessage(EMMessage.Type.LOCATION); // 如果是群聊,设置chattype,默认是单聊 if (chatType == CHATTYPE_GROUP) message.setChatType(ChatType.GroupChat); LocationMessageBody locBody = new LocationMessageBody(locationAddress, latitude, longitude); message.addBody(locBody); message.setAttribute("mName", StorageUtil.getString(this, "nickname")); message.setAttribute("mAvatar", StorageUtil.getString(this, "mAvatar")); message.setReceipt(toChatUsername); conversation.addMessage(message); listView.setAdapter(adapter); adapter.notifyDataSetChanged(); listView.setSelection(listView.getCount() - 1); setResult(RESULT_OK); } /** * 重发消息 */ private void resendMessage() { EMMessage msg = null; msg = conversation.getMessage(resendPos); // msg.setBackSend(true); msg.status = EMMessage.Status.CREATE; adapter.notifyDataSetChanged(); listView.setSelection(resendPos); } /** * 显示语音图标按钮 * * @param view */ public void setModeVoice(View view) { edittext_layout.setVisibility(View.GONE); hideKeyboard(); more.setVisibility(View.GONE); view.setVisibility(View.GONE); buttonSetModeKeyboard.setVisibility(View.VISIBLE); // mEditTextContent.setVisibility(View.GONE); // buttonSend.setVisibility(View.GONE); // buttonSetModeVoice.setVisibility(View.GONE); buttonPressToSpeak.setVisibility(View.VISIBLE); iv_emoticons_normal.setVisibility(View.VISIBLE); iv_emoticons_checked.setVisibility(View.INVISIBLE); btnContainer.setVisibility(View.VISIBLE); expressionContainer.setVisibility(View.GONE); } /** * 显示键盘图标 * * @param view */ public void setModeKeyboard(View view) { edittext_layout.setVisibility(View.VISIBLE); more.setVisibility(View.GONE); view.setVisibility(View.GONE); buttonSetModeVoice.setVisibility(View.VISIBLE); // mEditTextContent.setVisibility(View.VISIBLE); mEditTextContent.requestFocus(); // buttonSend.setVisibility(View.VISIBLE); buttonPressToSpeak.setVisibility(View.GONE); } /** * 点击清空聊天记录 * * @param view */ public void emptyHistory(View view) { startActivityForResult( new Intent(this, AlertDialog.class).putExtra("titleIsCancel", true).putExtra("msg", "是否清空所有聊天记录").putExtra("cancel", true), REQUEST_CODE_EMPTY_HISTORY); } /** * 显示或隐藏图标按钮页 * * @param view */ public void more(View view) { if (more.getVisibility() == View.GONE) { System.out.println("more gone"); hideKeyboard(); more.setVisibility(View.VISIBLE); btnContainer.setVisibility(View.VISIBLE); expressionContainer.setVisibility(View.GONE); } else { if (expressionContainer.getVisibility() == View.VISIBLE) { expressionContainer.setVisibility(View.GONE); btnContainer.setVisibility(View.VISIBLE); iv_emoticons_normal.setVisibility(View.VISIBLE); iv_emoticons_checked.setVisibility(View.INVISIBLE); } else { more.setVisibility(View.GONE); } } } /** * 点击文字输入框 * * @param v */ public void editClick(View v) { listView.setSelection(listView.getCount() - 1); if (more.getVisibility() == View.VISIBLE) { more.setVisibility(View.GONE); iv_emoticons_normal.setVisibility(View.VISIBLE); iv_emoticons_checked.setVisibility(View.INVISIBLE); } } /** * 消息广播接收者 * */ private class NewMessageBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String username = intent.getStringExtra("from"); String msgid = intent.getStringExtra("msgid"); // 收到这个广播的时候,message已经在db和内存里了,可以通过id获取mesage对象 EMMessage message = EMChatManager.getInstance().getMessage(msgid); // 如果是群聊消息,获取到group id if (message.getChatType() == ChatType.GroupChat) { username = message.getTo(); } if (!username.equals(toChatUsername)) { // 消息不是发给当前会话,return return; } mKXApplication.mSaveConversationDao.saveConversation(new ConversationResult(mName, mEmail, mAvatar)); // conversation = EMChatManager.getInstance().getConversation(toChatUsername); conversation.addMessage(message); // 通知adapter有新消息,更新ui adapter.notifyDataSetChanged(); listView.setSelection(listView.getCount() - 1); // 记得把广播给终结掉 abortBroadcast(); } } /** * 消息回执BroadcastReceiver */ private BroadcastReceiver ackMessageReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String msgid = intent.getStringExtra("msgid"); String from = intent.getStringExtra("from"); EMConversation conversation = EMChatManager.getInstance().getConversation(from); if (conversation != null) { // 把message设为已读 EMMessage msg = conversation.getMessage(msgid); if (msg != null) { msg.isAcked = true; } } abortBroadcast(); adapter.notifyDataSetChanged(); } }; private PowerManager.WakeLock wakeLock; /** * 按住说话listener * */ class PressToSpeakListen implements View.OnTouchListener { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (!CommonUtils.isExitsSdcard()) { Toast.makeText(ChatActivity.this, "发送语音需要sdcard支持!", Toast.LENGTH_SHORT).show(); return false; } try { v.setPressed(true); wakeLock.acquire(); if(VoicePlayClickListener.isPlaying) VoicePlayClickListener.currentPlayListener.stopPlayVoice(); recordingContainer.setVisibility(View.VISIBLE); recordingHint.setText(getString(R.string.move_up_to_cancel)); recordingHint.setBackgroundColor(Color.TRANSPARENT); voiceRecorder.startRecording(null, toChatUsername, getApplicationContext()); } catch (Exception e) { v.setPressed(false); if(wakeLock.isHeld()) wakeLock.release(); recordingContainer.setVisibility(View.INVISIBLE); Toast.makeText(ChatActivity.this, R.string.recoding_fail, Toast.LENGTH_SHORT).show(); return false; } return true; case MotionEvent.ACTION_MOVE: { if (event.getY() < 0) { recordingHint.setText(getString(R.string.release_to_cancel)); recordingHint.setBackgroundResource(R.drawable.recording_text_hint_bg); } else { recordingHint.setText(getString(R.string.move_up_to_cancel)); recordingHint.setBackgroundColor(Color.TRANSPARENT); } return true; } case MotionEvent.ACTION_UP: v.setPressed(false); recordingContainer.setVisibility(View.INVISIBLE); if(wakeLock.isHeld()) wakeLock.release(); if (event.getY() < 0) { // discard the recorded audio. voiceRecorder.discardRecording(); } else { // stop recording and send voice file try { int length = voiceRecorder.stopRecoding(); if (length > 0) { sendVoice(voiceRecorder.getVoiceFilePath(), voiceRecorder.getVoiceFileName(toChatUsername), Integer.toString(length), false); }else{ Toast.makeText(getApplicationContext(), "录音时间太短", 0).show(); } } catch (Exception e) { Toast.makeText(ChatActivity.this, "发送失败,请检测服务器是否连接", Toast.LENGTH_SHORT).show(); } } return true; default: return false; } } } /** * 获取表情的gridview的子view * * @param i * @return */ private View getGridChildView(int i) { View view = View.inflate(this, R.layout.expression_gridview, null); ExpandGridView gv = (ExpandGridView) view.findViewById(R.id.gridview); List<String> list = new ArrayList<String>(); if (i == 1) { List<String> list1 = reslist.subList(0, 20); list.addAll(list1); } else if (i == 2) { list.addAll(reslist.subList(20, reslist.size())); } list.add("delete_expression"); final ExpressionAdapter expressionAdapter = new ExpressionAdapter(this, 1, list); gv.setAdapter(expressionAdapter); gv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { String filename = expressionAdapter.getItem(position); try { // 文字输入框可见时,才可输入表情 // 按住说话可见,不让输入表情 if (buttonSetModeKeyboard.getVisibility() != View.VISIBLE) { if (filename != "delete_expression") { // 不是删除键,显示表情 Class clz = Class.forName("com.easemob.chatuidemo.utils.SmileUtils"); Field field = clz.getField(filename); mEditTextContent.append(SmileUtils.getSmiledText(ChatActivity.this, (String) field.get(null))); } else { // 删除文字或者表情 if (!TextUtils.isEmpty(mEditTextContent.getText())) { int selectionStart = mEditTextContent.getSelectionStart();// 获取光标的位置 if (selectionStart > 0) { String body = mEditTextContent.getText().toString(); String tempStr = body.substring(0, selectionStart); int i = tempStr.lastIndexOf("[");// 获取最后一个表情的位置 if (i != -1) { CharSequence cs = tempStr.substring(i, selectionStart); if (SmileUtils.containsKey(cs.toString())) mEditTextContent.getEditableText().delete(i, selectionStart); else mEditTextContent.getEditableText().delete(selectionStart - 1, selectionStart); } else { mEditTextContent.getEditableText().delete(selectionStart - 1, selectionStart); } } } } } } catch (Exception e) { } } }); return view; } public List<String> getExpressionRes(int getSum) { List<String> reslist = new ArrayList<String>(); for (int x = 1; x <= getSum; x++) { String filename = "ee_" + x; reslist.add(filename); } return reslist; } @Override protected void onDestroy() { super.onDestroy(); activityInstance = null; // 注销广播 try { unregisterReceiver(receiver); receiver = null; } catch (Exception e) { } try { unregisterReceiver(ackMessageReceiver); ackMessageReceiver = null; } catch (Exception e) { } } @Override protected void onResume() { super.onResume(); adapter.notifyDataSetChanged(); } @Override protected void onPause() { super.onPause(); if(wakeLock.isHeld()) wakeLock.release(); if (VoicePlayClickListener.isPlaying && VoicePlayClickListener.currentPlayListener != null) { //停止语音播放 VoicePlayClickListener.currentPlayListener.stopPlayVoice(); } //停止录音 if(voiceRecorder.isRecording()){ voiceRecorder.discardRecording(); recordingContainer.setVisibility(View.INVISIBLE); } Intent intent = new Intent(this, MessagePushService.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startService(intent); } /** * 隐藏软键盘 */ private void hideKeyboard() { if (getWindow().getAttributes().softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) { if (getCurrentFocus() != null) manager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } } /** * 返回 * * @param view */ public void back(View view) { finish(); } /** * 覆盖手机返回键 */ @Override public void onBackPressed() { if (more.getVisibility() == View.VISIBLE) { more.setVisibility(View.GONE); iv_emoticons_normal.setVisibility(View.VISIBLE); iv_emoticons_checked.setVisibility(View.INVISIBLE); } else { super.onBackPressed(); } } /** * listview滑动监听listener * */ private class ListScrollListener implements OnScrollListener { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { switch (scrollState) { case OnScrollListener.SCROLL_STATE_IDLE: if (view.getFirstVisiblePosition() == 0 && !isloading && haveMoreData) { loadmorePB.setVisibility(View.VISIBLE); // sdk初始化加载的聊天记录为20条,到顶时去db里获取更多 List<EMMessage> messages = null; try { // ChatResult chat = (ChatResult) adapter.getItem(0); // 获取更多messges,调用此方法的时候从db获取的messages // sdk会自动存入到此conversation中 messages = conversation.loadMoreMsgFromDB(adapter.getItem(0).getMsgId(), pagesize); } catch (Exception e1) { loadmorePB.setVisibility(View.GONE); return; } try { Thread.sleep(300); } catch (InterruptedException e) { } if (messages.size() != 0) { // 刷新ui adapter.notifyDataSetChanged(); listView.setSelection(messages.size() - 1); if (messages.size() != pagesize) haveMoreData = false; } else { haveMoreData = false; } loadmorePB.setVisibility(View.GONE); isloading = false; } break; } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { } } @Override protected void onNewIntent(Intent intent) { //点击notification bar进入聊天页面,保证只有一个聊天页面 String username = intent.getStringExtra("email"); mEmail = getIntent().getStringExtra("email"); mName = getIntent().getStringExtra("name"); mAvatar = getIntent().getStringExtra("avatar"); ((TextView) findViewById(R.id.chat_title)).setText(mName); mKXApplication.mSaveConversationDao.saveConversation(new ConversationResult(mName, mEmail, mAvatar)); if(toChatUsername.equals(username)) super.onNewIntent(intent); else{ finish(); startActivity(intent); } } /*public class ChatAdapter extends BaseAdapter { public int getCount() { return mKXApplication.mChatResults.size(); } public Object getItem(int position) { return mKXApplication.mChatResults.get(position); } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { convertView = LayoutInflater.from(ChatActivity.this).inflate( R.layout.chat_activity_item, null); holder = new ViewHolder(); holder.in = (RelativeLayout) convertView .findViewById(R.id.chat_item_in_layout); holder.out = (RelativeLayout) convertView .findViewById(R.id.chat_item_out_layout); holder.inAvatar = (ImageView) convertView .findViewById(R.id.chat_item_in_avatar); holder.outAvatar = (ImageView) convertView .findViewById(R.id.chat_item_out_avatar); holder.inName = (TextView) convertView .findViewById(R.id.chat_item_in_name); holder.outName = (TextView) convertView .findViewById(R.id.chat_item_out_name); holder.inTime = (TextView) convertView .findViewById(R.id.chat_item_in_time); holder.outTime = (TextView) convertView .findViewById(R.id.chat_item_out_time); holder.inContent = (TextView) convertView .findViewById(R.id.chat_item_in_content); holder.outContent = (TextView) convertView .findViewById(R.id.chat_item_out_content); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } ChatResult result = mKXApplication.mChatResults.get(position); // 根据消息的类型,显示不同的界面效果,1为用户自己发出的消息,2为用户收到的消息 switch (result.getType()) { case 1: holder.in.setVisibility(View.GONE); holder.out.setVisibility(View.VISIBLE); holder.outAvatar.setImageBitmap(PhotoUtil.toRoundCorner( BitmapFactory.decodeResource(getResources(), R.drawable.head), 15)); ImageLoader.getInstance().displayImage(Constants.getImageUrl() + StorageUtil.getString(ChatActivity.this, "mAvatar"), holder.outAvatar, ImageUtil.getOption()); holder.outName.setText("我"); holder.outTime.setText(result.getTime()); holder.outContent.setText(new TextUtil(mKXApplication) .replace(result.getContent())); break; case 2: holder.out.setVisibility(View.GONE); holder.in.setVisibility(View.VISIBLE); // holder.inAvatar.setImageBitmap(mKXApplication // .getAvatar(mAvatar)); ImageLoader.getInstance().displayImage(Constants.getImageUrl() + mAvatar, holder.inAvatar, ImageUtil.getOption()); holder.inName.setText(mName); holder.inTime.setText(result.getTime()); holder.inContent.setText(new TextUtil(mKXApplication) .replace(result.getContent())); break; } return convertView; } class ViewHolder { RelativeLayout in; RelativeLayout out; ImageView inAvatar; ImageView outAvatar; TextView inName; TextView outName; TextView inTime; TextView outTime; TextView inContent; TextView outContent; } } */ }