发送文本消息
点击按钮 —> 构造文本消息对象—> 设置@的人员 —> base64编码—> 保存消息到本地数据库—> 发送消息—>发送完毕后修改消息发送状态
点击发送按钮后,页面(ChatFragment.java)响应发送事件
// 发送按钮点击事件
ekBar.getBtnSend().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String text = ekBar.getEtChat().getText().toString();
if (!TextUtils.isEmpty(text)) {
onSendBtnClick(text); //发送
ekBar.getEtChat().setText("");
}
}
});
/**
* 当点击了发送按钮,发送文本消息
* @param sendText
*/
private void onSendBtnClick(String sendText) {
if (TextUtils.isEmpty(sendText) || TextUtils.isEmpty(sendText.trim())) {
return;
}
long groupId = mGroupBean.getGroupId();
long userId = AuthManager.getUid(getContext());
String nickname = AuthManager.getName(getContext());
String avatar = AuthManager.getAvatar(getContext());
QXGroupTextMessage qxMessage = QXMessageCreator.createQXGroupTextMessage(groupId, userId, nickname, avatar, sendText, mGroupBean.getGroupType());
//设置@了哪些人
if(atUserInfoList != null){
List<String> asList = new ArrayList<>();
for(AtUserInfo userInfo : atUserInfoList){
asList.add(userInfo.getUserId());
}
qxMessage.setAtList(asList);
}
sendQXGroupMessage(qxMessage);//发送消息
ChatBean chatBean = new ChatBean(qxMessage);
chatBean.setSendStatus(ChatBean.SEND_STATUS_PROCESS);
dataList.add(chatBean);
//Utils.hideSoftInput(mActivity);
}
private void sendQXGroupMessage(QXGroupMessage message) {
try {
QXIMClient.sendMessage(message);
//给首页->企信界面发送事件,让其更新其界面
MessageSendEvent messageSendEvent = new MessageSendEvent(MessageSendEvent.SEND_MESSAGE_PROCESS, projectId, message.toDisplayMessage());
RxBus.get().post(messageSendEvent);
} catch (Exception e) {
e.printStackTrace();
if (BuildConfig.LOG_DEBUG) {
Log.w(TAG, "call sendMessage but send fail : " + e);
}
}
}
最后会调用如下代码发送消息,如下所示,先设置一个唯一的ID(clientMessageId),以便区分消息。将消息加入到发送消息的集合(processGroupMessageList)中,当消息发送成功\失败后,再从集合中移除。
如果是文本消息,需要先进行base64编码。
private void sendMessage(QXGroupMessage qxmsg, boolean isFirstSend){
Log.v("sendMessage : "+qxmsg);
if(qxmsg == null){
return;
}
//如果clientMessageId等于空,代表是不是重发消息,是第一次发送消息
if(qxmsg.getClientMessageId() == null || "".equals(qxmsg.getClientMessageId())){
String uuid = UUID.randomUUID().toString();
qxmsg.setClientMessageId(uuid);
sendQXMessageToByStoreHandler(qxmsg, WHAT_MESSAGE_SEND);
}else{
qxmsg.setSendTime(System.currentTimeMillis());
}
if(isFirstSend){
if(!processGroupMessageList.contains(qxmsg)){
processGroupMessageList.add(qxmsg);
}
}
//如果需要base64编码
if(isNeedBase64Encode){
if(qxmsg instanceof QXGroupTextMessage){//只有文本消息才需要base64编码
QXGroupTextMessage groupTextMessage = (QXGroupTextMessage)qxmsg;
String data = groupTextMessage.getData();
String base64 = Base64.encodeToString(data.getBytes(), Base64.NO_WRAP);
QXGroupTextMessage message= QXMessageCreator.createQXGroupTextMessage(groupTextMessage.getGroupId(), groupTextMessage.getUserId(), groupTextMessage.getName(), null, base64, groupTextMessage.getGroupType());
message.setId(groupTextMessage.getId());
message.setClientMessageId(groupTextMessage.getClientMessageId());
message.setAtList(groupTextMessage.getAtList());
sendMessage(message.toTransactString());
}else{
sendMessage(qxmsg.toTransactString());
}
}else{
sendMessage(qxmsg.toTransactString());
}
}
发送图片消息
发送图片有两种方式,一种是从相册选择图片,另一种是拍照。
选择图片 —> 压缩图片—> 上传图片—> 构造图片消息对象 —>保存消息到本地数据库—> 发送消息—>发送完毕后修改消息发送状态
发送图片的逻辑是先将图片压缩,然后上传图片到服务器,然后发送图片消息,代码如下:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.v("requestCode " + requestCode + ", resultCode = " + resultCode);
if (resultCode == RESULT_OK) {
if (requestCode == CAMERA_REQUEST) {
if (mCameraFile != null && mCameraFile.exists()) {
//拍照后回调
cameraPictureActivityResult(mCameraFile.getPath());
}
} else if (requestCode == IMAGE_REQUEST) {
List<String> paths = data.getStringArrayListExtra(MultiImageSelectorActivity.EXTRA_RESULT);
if (paths != null && paths.size() > 0) {
//从相处选择后回调
imagesSelectActivityResult(paths);
}
} else if (requestCode == LOCATION_REQUEST) {
if (data != null) {
double lat = data.getDoubleExtra("latitude", 0.0);
double lot = data.getDoubleExtra("longitude", 0.0);
String address = data.getStringExtra("address");
String imagePath = data.getStringExtra("imagepath");
scrollToBottom();
locationActivityResult(lat, lot, address, imagePath);
Log.v("位置:" + address + ":" + lat + ":" + lot + ":" + imagePath);
}
} else if (requestCode == FilePickerConst.REQUEST_CODE_DOC) {
if (data != null) {
ArrayList<String> documentPaths = data.getStringArrayListExtra(FilePickerConst.KEY_SELECTED_DOCS);
documentActivityResult(documentPaths);
}
}
}
}
/**
* 图片选择后添加图片路径
* @param paths
*/
private void imagesSelectActivityResult(List<String> paths) {
Log.v(TAG, "imagesSelectActivityResult : " + paths);
//Toaster.showShort(mContext, "imagesSelectActivityResult : " + paths);
uploadSendImageMessage(paths);
}
/**
* 上传并且发送图片消息(先压缩图片,然后上次压缩图片到服务器,拿到服务器返回的图片url,在发送这个url。其他设备获取到url后就可以显示图片了)
* @param imagePaths(图片路径集合)
*/
private void uploadSendImageMessage(List<String> imagePaths) {
Log.v(TAG, "uploadSendImageMessage : " + imagePaths);
//Toaster.showShort(mContext, "sendImageMessage : " + imagePaths);
//step 1, 在界面上显示图片消息
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
List<ChatBean> uploadImageList = new ArrayList<>();
for (String string : imagePaths) {
QXGroupImageMessage message = new QXGroupImageMessage();
message.setGroupId(mGroupBean.getGroupId());
message.setSendTime(System.currentTimeMillis());
message.setGroupName(mGroupBean.getGroupName());
//message.setGroupType();
message.setUserId(AuthManager.getUid(mContext));
message.setName(AuthManager.getName(mContext));
message.setAvatar(AuthManager.getAvatar(mContext));
message.setLocalPath(string);
BitmapFactory.decodeFile(string, options);
message.setWidth(options.outWidth);
message.setHeight(options.outHeight);
ChatBean chatBean = new ChatBean(message);
chatBean.setShowProcess(true);
chatBean.setPosition(dataList.size());
dataList.add(chatBean);
uploadImageList.add(chatBean);
}
//step 2, 上传并发送图片消息
sendImageMessage(uploadImageList);
}
发送语音消息
流程 录音—>上传录音文件 —>保存消息到本地数据库—> 发送消息—>发送完毕后修改消息发送状态
/**
* 按住按钮说话逻辑处理
* @param event
* @return
*/
@OnTouch(R.id.btn_voice)
boolean onVoiceBtnTouch(MotionEvent event){
Log.v(TAG, "call onVoiceBtnTouch " +event);
int action = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
switch (action)
{
case MotionEvent.ACTION_DOWN:
.......
//发送语音消息
final ChatBean chatBean = new ChatBean(message);
chatBean.setSendStatus(ChatBean.SEND_STATUS_PROCESS);
message.setLocalUrl(fileName);
sendVoiceMessage(chatBean, true);
.......
break;
case MotionEvent.ACTION_MOVE:
......
break;
case MotionEvent.ACTION_UP:
......
break;
}
return false;
}
发送文件消息
流程 选择文件 —> 上传文件—> 构造文件消息对象 —>保存消息到本地数据库—> 发送消息—>发送完毕后修改消息发送状态
/**
* 选择文档后的处理,发送文档消息(先上传文件到服务器,拿到url然后上传)
* @param documentPaths
*/
private void documentActivityResult(ArrayList<String> documentPaths) {
if (BuildConfig.LOG_DEBUG) {
Log.v(TAG, "documentActivityResult : " + documentPaths);
//Toaster.showShort(mContext, "documentActivityResult : " + documentPaths);
}
//step 1, 在界面上显示文档消息
File file = null;
List<ChatBean> uploadDocList = new ArrayList<>();
for (String string : documentPaths) {
file = new File(string);
QXGroupDocumentMessage message = new QXGroupDocumentMessage();
message.setGroupId(mGroupBean.getGroupId());
message.setSendTime(System.currentTimeMillis());
message.setLocalPath(string);
message.setGroupName(mGroupBean.getGroupName());
//message.setGroupType();
message.setUserId(AuthManager.getUid(mContext));
message.setName(AuthManager.getName(mContext));
message.setAvatar(AuthManager.getAvatar(mContext));
message.setFileName(file.getName());
try {
message.setSize(Utils.getFileSizes(file));
} catch (Exception e) {
e.printStackTrace();
}
ChatBean chatBean = new ChatBean(message);
chatBean.setShowProcess(true);
chatBean.setPosition(dataList.size());
dataList.add(chatBean);
uploadDocList.add(chatBean);
}
mChatAdapter.notifyDataSetChanged();
scrollToBottom();
//step 2, 上传并发送文档消息
sendDocumentMessage(uploadDocList);
}
发送位置消息
流程 定位—> 构造位置消息 —>保存消息到本地数据库—> 发送消息—>发送完毕后修改消息发送状态
/**
* 地图地位后的方法处理,发送经纬度,地址信息
* @param latitude
* @param longitude
* @param address
* @param imagePath
*/
private void locationActivityResult(double latitude, double longitude, String address, String imagePath) {
if (BuildConfig.LOG_DEBUG) {
Log.v(TAG, "locationActivityResult : " + latitude + ", " + longitude + "," + address);
}
//Toaster.showShort(mContext, "locationActivityResult : "+imagePath);
//step 1, 发送定位消息
long groupId = mGroupBean.getGroupId();
long userId = AuthManager.getUid(getContext());
String nickname = AuthManager.getName(getContext());
String avatar = AuthManager.getAvatar(getContext());
QXGroupLocationMessage qxMessage = QXMessageCreator.createQXGroupLocationMessage(
groupId, userId, nickname, avatar, latitude, longitude, address, mGroupBean.getGroupType());
sendQXGroupMessage(qxMessage);
//step 2, 更新界面
ChatBean chatBean = new ChatBean(qxMessage);
chatBean.setSendStatus(ChatBean.SEND_STATUS_PROCESS);
dataList.add(chatBean);
mChatAdapter.notifyDataSetChanged();
scrollToBottom();
}