環信官方Demo源碼分析及SDK簡單應用-EaseUI

環信官方Demo源碼分析及SDK簡單應用

環信官方Demo源碼分析及SDK簡單應用-ChatDemoUI3.0

環信官方Demo源碼分析及SDK簡單應用-LoginActivity

環信官方Demo源碼分析及SDK簡單應用-主界面的三個fragment-會話界面

環信官方Demo源碼分析及SDK簡單應用-主界面的三個fragment-通訊錄界面

環信官方Demo源碼分析及SDK簡單應用-主界面的三個fragment-設置界面

環信官方Demo源碼分析及SDK簡單應用-EaseUI

環信官方Demo源碼分析及SDK簡單應用-IM集成開發詳案及具體代碼實現

EaseUI

實際工作過程中,我們是用不了太多東西的,如果只是集成個im最多用到的就是聊天列表和聊天頁面。

我們來看重頭戲EaseUI這個庫。

官方文檔

其實官方的WiKi已經介紹的特別詳細了。官方EaseUI文檔

我們來看Demo

// start chat acitivity

Intent intent = new Intent(getActivity(), ChatActivity.class);

if(conversation.isGroup()){

if(conversation.getType() == EMConversationType.ChatRoom){

// it's group chat

intent.putExtra(Constant.EXTRA_CHAT_TYPE, Constant.CHATTYPE_CHATROOM);

}else{

intent.putExtra(Constant.EXTRA_CHAT_TYPE, Constant.CHATTYPE_GROUP);

}

}

// it's single chat

intent.putExtra(Constant.EXTRA_USER_ID, username);

startActivity(intent);

ChatActivity

我們來看看ChatActivity

package com.hyphenate.chatuidemo.ui;

?

import android.content.Intent;

import android.os.Bundle;

import android.support.annotation.NonNull;

import com.hyphenate.chatuidemo.R;

import com.hyphenate.chatuidemo.runtimepermissions.PermissionsManager;

import com.hyphenate.easeui.ui.EaseChatFragment;

import com.hyphenate.util.EasyUtils;

?

/**

* chat activity,EaseChatFragment was used {@link #EaseChatFragment}

*

*/

public class ChatActivity extends BaseActivity{

public static ChatActivity activityInstance;

private EaseChatFragment chatFragment;

String toChatUsername;

?

@Override

protected void onCreate(Bundle arg0) {

super.onCreate(arg0);

setContentView(R.layout.em_activity_chat);

activityInstance = this;

//get user id or group id

toChatUsername = getIntent().getExtras().getString("userId");

//use EaseChatFratFragment

chatFragment = new ChatFragment();

//pass parameters to chat fragment

chatFragment.setArguments(getIntent().getExtras());

getSupportFragmentManager().beginTransaction().add(R.id.container, chatFragment).commit();

}

@Override

protected void onDestroy() {

super.onDestroy();

activityInstance = null;

}

@Override

protected void onNewIntent(Intent intent) {

// make sure only one chat activity is opened

String username = intent.getStringExtra("userId");

if (toChatUsername.equals(username))

super.onNewIntent(intent);

else {

finish();

startActivity(intent);

}

?

}

@Override

public void onBackPressed() {

chatFragment.onBackPressed();

if (EasyUtils.isSingleActivity(this)) {

Intent intent = new Intent(this, MainActivity.class);

startActivity(intent);

}

}

public String getToChatUsername(){

return toChatUsername;

}

?

@Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions,

@NonNull int grantResults) {

PermissionsManager.getInstance().notifyPermissionsChange(permissions, grantResults);

}

}

官方文檔是這么說的

封裝EaseChatFragment的ChatFragment

那么Demo中是做了一層封裝的。

package com.hyphenate.chatuidemo.ui;

?

import android.app.Activity;

import android.content.ClipData;

import android.content.Intent;

import android.graphics.Bitmap;

import android.graphics.Bitmap.CompressFormat;

import android.media.ThumbnailUtils;

import android.net.Uri;

import android.os.Build;

import android.os.Bundle;

import android.text.Editable;

import android.text.TextWatcher;

import android.view.LayoutInflater;

import android.view.View;

import android.view.View.OnClickListener;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.Toast;

?

import com.easemob.redpacketsdk.constant.RPConstant;

import com.easemob.redpacketui.utils.RPRedPacketUtil;

import com.easemob.redpacketui.utils.RedPacketUtil;

import com.easemob.redpacketui.widget.ChatRowRandomPacket;

import com.easemob.redpacketui.widget.ChatRowRedPacket;

import com.easemob.redpacketui.widget.ChatRowRedPacketAck;

import com.easemob.redpacketui.widget.ChatRowTransfer;

import com.hyphenate.chat.EMClient;

import com.hyphenate.chat.EMCmdMessageBody;

import com.hyphenate.chat.EMGroup;

import com.hyphenate.chat.EMMessage;

import com.hyphenate.chat.EMTextMessageBody;

import com.hyphenate.chatuidemo.Constant;

import com.hyphenate.chatuidemo.DemoHelper;

import com.hyphenate.chatuidemo.R;

import com.hyphenate.chatuidemo.domain.EmojiconExampleGroupData;

import com.hyphenate.chatuidemo.domain.RobotUser;

import com.hyphenate.chatuidemo.widget.ChatRowVoiceCall;

import com.hyphenate.easeui.EaseConstant;

import com.hyphenate.easeui.ui.EaseChatFragment;

import com.hyphenate.easeui.ui.EaseChatFragment.EaseChatFragmentHelper;

import com.hyphenate.easeui.widget.chatrow.EaseChatRow;

import com.hyphenate.easeui.widget.chatrow.EaseCustomChatRowProvider;

import com.hyphenate.easeui.widget.emojicon.EaseEmojiconMenu;

import com.hyphenate.util.EasyUtils;

import com.hyphenate.util.PathUtil;

?

import java.io.File;

import java.io.FileOutputStream;

import java.util.List;

import java.util.Map;

?

public class ChatFragment extends EaseChatFragment implements EaseChatFragmentHelper{

?

// constant start from 11 to avoid conflict with constant in base class

private static final int ITEM_VIDEO = 11;

private static final int ITEM_FILE = 12;

private static final int ITEM_VOICE_CALL = 13;

private static final int ITEM_VIDEO_CALL = 14;

?

private static final int REQUEST_CODE_SELECT_VIDEO = 11;

private static final int REQUEST_CODE_SELECT_FILE = 12;

private static final int REQUEST_CODE_GROUP_DETAIL = 13;

private static final int REQUEST_CODE_CONTEXT_MENU = 14;

private static final int REQUEST_CODE_SELECT_AT_USER = 15;

?

private static final int MESSAGE_TYPE_SENT_VOICE_CALL = 1;

private static final int MESSAGE_TYPE_RECV_VOICE_CALL = 2;

private static final int MESSAGE_TYPE_SENT_VIDEO_CALL = 3;

private static final int MESSAGE_TYPE_RECV_VIDEO_CALL = 4;

?

//red packet code : 紅包功能使用的常量

private static final int MESSAGE_TYPE_RECV_RED_PACKET = 5;

private static final int MESSAGE_TYPE_SEND_RED_PACKET = 6;

private static final int MESSAGE_TYPE_SEND_RED_PACKET_ACK = 7;

private static final int MESSAGE_TYPE_RECV_RED_PACKET_ACK = 8;

private static final int MESSAGE_TYPE_RECV_TRANSFER_PACKET = 9;

private static final int MESSAGE_TYPE_SEND_TRANSFER_PACKET = 10;

private static final int MESSAGE_TYPE_RECV_RANDOM = 11;

private static final int MESSAGE_TYPE_SEND_RANDOM = 12;

private static final int REQUEST_CODE_SEND_RED_PACKET = 16;

private static final int ITEM_RED_PACKET = 16;

private static final int REQUEST_CODE_SEND_TRANSFER_PACKET = 17;

private static final int ITEM_TRANSFER_PACKET = 17;

//end of red packet code

?

/**

* if it is chatBot

*/

private boolean isRobot;

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

return super.onCreateView(inflater, container, savedInstanceState);

}

?

@Override

protected void setUpView() {

setChatFragmentListener(this);

if (chatType == Constant.CHATTYPE_SINGLE) {

Map robotMap = DemoHelper.getInstance().getRobotList();

if(robotMap!=null && robotMap.containsKey(toChatUsername)){

isRobot = true;

}

}

super.setUpView();

// set click listener

titleBar.setLeftLayoutClickListener(new OnClickListener() {

?

@Override

public void onClick(View v) {

if (EasyUtils.isSingleActivity(getActivity())) {

Intent intent = new Intent(getActivity(), MainActivity.class);

startActivity(intent);

}

onBackPressed();

}

});

((EaseEmojiconMenu)inputMenu.getEmojiconMenu()).addEmojiconGroup(EmojiconExampleGroupData.getData());

if(chatType == EaseConstant.CHATTYPE_GROUP){

inputMenu.getPrimaryMenu().getEditText().addTextChangedListener(new TextWatcher() {

@Override

public void onTextChanged(CharSequence s, int start, int before, int count) {

if(count == 1 && "@".equals(String.valueOf(s.charAt(start)))){

startActivityForResult(new Intent(getActivity(), PickAtUserActivity.class).

putExtra("groupId", toChatUsername), REQUEST_CODE_SELECT_AT_USER);

}

}

@Override

public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

@Override

public void afterTextChanged(Editable s) {

}

});

}

}

@Override

protected void registerExtendMenuItem() {

//use the menu in base class

super.registerExtendMenuItem();

//extend menu items

inputMenu.registerExtendMenuItem(R.string.attach_video, R.drawable.em_chat_video_selector, ITEM_VIDEO, extendMenuItemClickListener);

inputMenu.registerExtendMenuItem(R.string.attach_file, R.drawable.em_chat_file_selector, ITEM_FILE, extendMenuItemClickListener);

if(chatType == Constant.CHATTYPE_SINGLE){

inputMenu.registerExtendMenuItem(R.string.attach_voice_call, R.drawable.em_chat_voice_call_selector, ITEM_VOICE_CALL, extendMenuItemClickListener);

inputMenu.registerExtendMenuItem(R.string.attach_video_call, R.drawable.em_chat_video_call_selector, ITEM_VIDEO_CALL, extendMenuItemClickListener);

}

//聊天室暫時不支持紅包功能

//red packet code : 注冊紅包菜單選項

if (chatType != Constant.CHATTYPE_CHATROOM) {

inputMenu.registerExtendMenuItem(R.string.attach_red_packet, R.drawable.em_chat_red_packet_selector, ITEM_RED_PACKET, extendMenuItemClickListener);

}

//red packet code : 注冊轉賬菜單選項

if (chatType == Constant.CHATTYPE_SINGLE) {

inputMenu.registerExtendMenuItem(R.string.attach_transfer_money, R.drawable.em_chat_transfer_selector, ITEM_TRANSFER_PACKET, extendMenuItemClickListener);

}

//end of red packet code

}

@Override

public void onActivityResult(int requestCode, int resultCode, Intent data) {

super.onActivityResult(requestCode, resultCode, data);

if (requestCode == REQUEST_CODE_CONTEXT_MENU) {

switch (resultCode) {

case ContextMenuActivity.RESULT_CODE_COPY: // copy

clipboard.setPrimaryClip(ClipData.newPlainText(null,

((EMTextMessageBody) contextMenuMessage.getBody()).getMessage()));

break;

case ContextMenuActivity.RESULT_CODE_DELETE: // delete

conversation.removeMessage(contextMenuMessage.getMsgId());

messageList.refresh();

break;

?

case ContextMenuActivity.RESULT_CODE_FORWARD: // forward

Intent intent = new Intent(getActivity(), ForwardMessageActivity.class);

intent.putExtra("forward_msg_id", contextMenuMessage.getMsgId());

startActivity(intent);

break;

?

default:

break;

}

}

if(resultCode == Activity.RESULT_OK){

switch (requestCode) {

case REQUEST_CODE_SELECT_VIDEO: //send the video

if (data != null) {

int duration = data.getIntExtra("dur", 0);

String videoPath = data.getStringExtra("path");

File file = new File(PathUtil.getInstance().getImagePath(), "thvideo" + System.currentTimeMillis());

try {

FileOutputStream fos = new FileOutputStream(file);

Bitmap ThumbBitmap = ThumbnailUtils.createVideoThumbnail(videoPath, 3);

ThumbBitmap.compress(CompressFormat.JPEG, 100, fos);

fos.close();

sendVideoMessage(videoPath, file.getAbsolutePath(), duration);

} catch (Exception e) {

e.printStackTrace();

}

}

break;

case REQUEST_CODE_SELECT_FILE: //send the file

if (data != null) {

Uri uri = data.getData();

if (uri != null) {

sendFileByUri(uri);

}

}

break;

case REQUEST_CODE_SELECT_AT_USER:

if(data != null){

String username = data.getStringExtra("username");

inputAtUsername(username, false);

}

break;

//red packet code : 發送紅包消息到聊天界面

case REQUEST_CODE_SEND_RED_PACKET:

if (data != null){

sendMessage(RedPacketUtil.createRPMessage(getActivity(), data, toChatUsername));

}

break;

case REQUEST_CODE_SEND_TRANSFER_PACKET://發送轉賬消息

if (data != null) {

sendMessage(RedPacketUtil.createTRMessage(getActivity(), data, toChatUsername));

}

break;

//end of red packet code

default:

break;

}

}

}

@Override

public void onSetMessageAttributes(EMMessage message) {

if(isRobot){

//set message extension

message.setAttribute("em_robot_message", isRobot);

}

}

@Override

public EaseCustomChatRowProvider onSetCustomChatRowProvider() {

return new CustomChatRowProvider();

}

?

@Override

public void onEnterToChatDetails() {

if (chatType == Constant.CHATTYPE_GROUP) {

EMGroup group = EMClient.getInstance().groupManager().getGroup(toChatUsername);

if (group == null) {

Toast.makeText(getActivity(), R.string.gorup_not_found, Toast.LENGTH_SHORT).show();

return;

}

startActivityForResult(

(new Intent(getActivity(), GroupDetailsActivity.class).putExtra("groupId", toChatUsername)),

REQUEST_CODE_GROUP_DETAIL);

}else if(chatType == Constant.CHATTYPE_CHATROOM){

startActivityForResult(new Intent(getActivity(), ChatRoomDetailsActivity.class).putExtra("roomId", toChatUsername), REQUEST_CODE_GROUP_DETAIL);

}

}

?

@Override

public void onAvatarClick(String username) {

//handling when user click avatar

Intent intent = new Intent(getActivity(), UserProfileActivity.class);

intent.putExtra("username", username);

startActivity(intent);

}

@Override

public void onAvatarLongClick(String username) {

inputAtUsername(username);

}

@Override

public boolean onMessageBubbleClick(EMMessage message) {

//消息框點擊事件,demo這里不做覆蓋,如需覆蓋,return true

//red packet code : 拆紅包頁面

if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_MESSAGE, false)){

if (RedPacketUtil.isRandomRedPacket(message)){

RedPacketUtil.openRandomPacket(getActivity(),message);

} else {

RedPacketUtil.openRedPacket(getActivity(), chatType, message, toChatUsername, messageList);

}

return true;

} else if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_TRANSFER_PACKET_MESSAGE, false)) {

RedPacketUtil.openTransferPacket(getActivity(), message);

return true;

}

//end of red packet code

return false;

}

@Override

public void onCmdMessageReceived(List messages) {

//red packet code : 處理紅包回執透傳消息

for (EMMessage message : messages) {

EMCmdMessageBody cmdMsgBody = (EMCmdMessageBody) message.getBody();

String action = cmdMsgBody.action();//獲取自定義action

if (action.equals(RPConstant.REFRESH_GROUP_RED_PACKET_ACTION)){

RedPacketUtil.receiveRedPacketAckMessage(message);

messageList.refresh();

}

}

//end of red packet code

super.onCmdMessageReceived(messages);

}

?

@Override

public void onMessageBubbleLongClick(EMMessage message) {

// no message forward when in chat room

startActivityForResult((new Intent(getActivity(), ContextMenuActivity.class)).putExtra("message",message)

.putExtra("ischatroom", chatType == EaseConstant.CHATTYPE_CHATROOM),

REQUEST_CODE_CONTEXT_MENU);

}

?

@Override

public boolean onExtendMenuItemClick(int itemId, View view) {

switch (itemId) {

case ITEM_VIDEO:

Intent intent = new Intent(getActivity(), ImageGridActivity.class);

startActivityForResult(intent, REQUEST_CODE_SELECT_VIDEO);

break;

case ITEM_FILE: //file

selectFileFromLocal();

break;

case ITEM_VOICE_CALL:

startVoiceCall();

break;

case ITEM_VIDEO_CALL:

startVideoCall();

break;

//red packet code : 進入發紅包頁面

case ITEM_RED_PACKET:

if (chatType == Constant.CHATTYPE_SINGLE) {

//單聊紅包修改進入紅包的方法,可以在小額隨機紅包和普通單聊紅包之間切換

RedPacketUtil.startRandomPacket(new RPRedPacketUtil.RPRandomCallback() {

@Override

public void onSendPacketSuccess(Intent data) {

sendMessage(RedPacketUtil.createRPMessage(getActivity(), data, toChatUsername));

}

?

@Override

public void switchToNormalPacket() {

RedPacketUtil.startRedPacketActivityForResult(ChatFragment.this, chatType, toChatUsername, REQUEST_CODE_SEND_RED_PACKET);

}

},getActivity(),toChatUsername);

} else {

RedPacketUtil.startRedPacketActivityForResult(this, chatType, toChatUsername, REQUEST_CODE_SEND_RED_PACKET);

}

break;

case ITEM_TRANSFER_PACKET://進入轉賬頁面

RedPacketUtil.startTransferActivityForResult(this, toChatUsername, REQUEST_CODE_SEND_TRANSFER_PACKET);

break;

//end of red packet code

default:

break;

}

//keep exist extend menu

return false;

}

/**

* select file

*/

protected void selectFileFromLocal() {

Intent intent = null;

if (Build.VERSION.SDK_INT < 19) { //api 19 and later, we can't use this way, demo just select from images

intent = new Intent(Intent.ACTION_GET_CONTENT);

intent.setType("*/*");

intent.addCategory(Intent.CATEGORY_OPENABLE);

?

} else {

intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

}

startActivityForResult(intent, REQUEST_CODE_SELECT_FILE);

}

/**

* make a voice call

*/

protected void startVoiceCall() {

if (!EMClient.getInstance().isConnected()) {

Toast.makeText(getActivity(), R.string.not_connect_to_server, Toast.LENGTH_SHORT).show();

} else {

startActivity(new Intent(getActivity(), VoiceCallActivity.class).putExtra("username", toChatUsername)

.putExtra("isComingCall", false));

// voiceCallBtn.setEnabled(false);

inputMenu.hideExtendMenuContainer();

}

}

/**

* make a video call

*/

protected void startVideoCall() {

if (!EMClient.getInstance().isConnected())

Toast.makeText(getActivity(), R.string.not_connect_to_server, Toast.LENGTH_SHORT).show();

else {

startActivity(new Intent(getActivity(), VideoCallActivity.class).putExtra("username", toChatUsername)

.putExtra("isComingCall", false));

// videoCallBtn.setEnabled(false);

inputMenu.hideExtendMenuContainer();

}

}

/**

* chat row provider

*

*/

private final class CustomChatRowProvider implements EaseCustomChatRowProvider {

@Override

public int getCustomChatRowTypeCount() {

//here the number is the message type in EMMessage::Type

//which is used to count the number of different chat row

return 12;

}

?

@Override

public int getCustomChatRowType(EMMessage message) {

if(message.getType() == EMMessage.Type.TXT){

//voice call

if (message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VOICE_CALL, false)){

return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_VOICE_CALL : MESSAGE_TYPE_SENT_VOICE_CALL;

}else if (message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VIDEO_CALL, false)){

//video call

return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_VIDEO_CALL : MESSAGE_TYPE_SENT_VIDEO_CALL;

}

//red packet code : 紅包消息、紅包回執消息以及轉賬消息的chatrow type

else if (RedPacketUtil.isRandomRedPacket(message)) {

//小額隨機紅包

return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_RANDOM : MESSAGE_TYPE_SEND_RANDOM;

} else if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_MESSAGE, false)) {

//發送紅包消息

return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_RED_PACKET : MESSAGE_TYPE_SEND_RED_PACKET;

} else if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_ACK_MESSAGE, false)) {

//領取紅包消息

return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_RED_PACKET_ACK : MESSAGE_TYPE_SEND_RED_PACKET_ACK;

} else if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_TRANSFER_PACKET_MESSAGE, false)) {

//轉賬消息

return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_TRANSFER_PACKET : MESSAGE_TYPE_SEND_TRANSFER_PACKET;

}

//end of red packet code

}

return 0;

}

?

@Override

public EaseChatRow getCustomChatRow(EMMessage message, int position, BaseAdapter adapter) {

if(message.getType() == EMMessage.Type.TXT){

// voice call or video call

if (message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VOICE_CALL, false) ||

message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VIDEO_CALL, false)){

return new ChatRowVoiceCall(getActivity(), message, position, adapter);

}

//red packet code : 紅包消息、紅包回執消息以及轉賬消息的chat row

else if (RedPacketUtil.isRandomRedPacket(message)) {//小額隨機紅包

return new ChatRowRandomPacket(getActivity(), message, position, adapter);

} else if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_MESSAGE, false)) {//紅包消息

return new ChatRowRedPacket(getActivity(), message, position, adapter);

} else if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_ACK_MESSAGE, false)) {//紅包回執消息

return new ChatRowRedPacketAck(getActivity(), message, position, adapter);

} else if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_TRANSFER_PACKET_MESSAGE, false)) {//轉賬消息

return new ChatRowTransfer(getActivity(), message, position, adapter);

}

//end of red packet code

}

return null;

}

?

}

?

}

判斷是不是機器人及添加監聽

setChatFragmentListener(this);

if (chatType == Constant.CHATTYPE_SINGLE) {

Map robotMap = DemoHelper.getInstance().getRobotList();

if(robotMap!=null && robotMap.containsKey(toChatUsername)){

isRobot = true;

}

}

點擊標題返回及群聊@別人的功能?

// set click listener

titleBar.setLeftLayoutClickListener(new OnClickListener() {

?

@Override

public void onClick(View v) {

if (EasyUtils.isSingleActivity(getActivity())) {

Intent intent = new Intent(getActivity(), MainActivity.class);

startActivity(intent);

}

onBackPressed();

}

});

((EaseEmojiconMenu)inputMenu.getEmojiconMenu()).addEmojiconGroup(EmojiconExampleGroupData.getData());

if(chatType == EaseConstant.CHATTYPE_GROUP){

inputMenu.getPrimaryMenu().getEditText().addTextChangedListener(new TextWatcher() {

@Override

public void onTextChanged(CharSequence s, int start, int before, int count) {

if(count == 1 && "@".equals(String.valueOf(s.charAt(start)))){

startActivityForResult(new Intent(getActivity(), PickAtUserActivity.class).

putExtra("groupId", toChatUsername), REQUEST_CODE_SELECT_AT_USER);

}

}

@Override

public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

@Override

public void afterTextChanged(Editable s) {

}

});

}

菜單的操作?

super.registerExtendMenuItem();

//extend menu items

inputMenu.registerExtendMenuItem(R.string.attach_video, R.drawable.em_chat_video_selector, ITEM_VIDEO, extendMenuItemClickListener);

inputMenu.registerExtendMenuItem(R.string.attach_file, R.drawable.em_chat_file_selector, ITEM_FILE, extendMenuItemClickListener);

if(chatType == Constant.CHATTYPE_SINGLE){

inputMenu.registerExtendMenuItem(R.string.attach_voice_call, R.drawable.em_chat_voice_call_selector, ITEM_VOICE_CALL, extendMenuItemClickListener);

inputMenu.registerExtendMenuItem(R.string.attach_video_call, R.drawable.em_chat_video_call_selector, ITEM_VIDEO_CALL, extendMenuItemClickListener);

}

//聊天室暫時不支持紅包功能

//red packet code : 注冊紅包菜單選項

if (chatType != Constant.CHATTYPE_CHATROOM) {

inputMenu.registerExtendMenuItem(R.string.attach_red_packet, R.drawable.em_chat_red_packet_selector, ITEM_RED_PACKET, extendMenuItemClickListener);

}

//red packet code : 注冊轉賬菜單選項

if (chatType == Constant.CHATTYPE_SINGLE) {

inputMenu.registerExtendMenuItem(R.string.attach_transfer_money, R.drawable.em_chat_transfer_selector, ITEM_TRANSFER_PACKET, extendMenuItemClickListener);

}

//end of red packet code

一些功能操作?

if (requestCode == REQUEST_CODE_CONTEXT_MENU) {

switch (resultCode) {

case ContextMenuActivity.RESULT_CODE_COPY: // copy

clipboard.setPrimaryClip(ClipData.newPlainText(null,

((EMTextMessageBody) contextMenuMessage.getBody()).getMessage()));

break;

case ContextMenuActivity.RESULT_CODE_DELETE: // delete

conversation.removeMessage(contextMenuMessage.getMsgId());

messageList.refresh();

break;

?

case ContextMenuActivity.RESULT_CODE_FORWARD: // forward

Intent intent = new Intent(getActivity(), ForwardMessageActivity.class);

intent.putExtra("forward_msg_id", contextMenuMessage.getMsgId());

startActivity(intent);

break;

?

default:

break;

}

}

if(resultCode == Activity.RESULT_OK){

switch (requestCode) {

case REQUEST_CODE_SELECT_VIDEO: //send the video

if (data != null) {

int duration = data.getIntExtra("dur", 0);

String videoPath = data.getStringExtra("path");

File file = new File(PathUtil.getInstance().getImagePath(), "thvideo" + System.currentTimeMillis());

try {

FileOutputStream fos = new FileOutputStream(file);

Bitmap ThumbBitmap = ThumbnailUtils.createVideoThumbnail(videoPath, 3);

ThumbBitmap.compress(CompressFormat.JPEG, 100, fos);

fos.close();

sendVideoMessage(videoPath, file.getAbsolutePath(), duration);

} catch (Exception e) {

e.printStackTrace();

}

}

break;

case REQUEST_CODE_SELECT_FILE: //send the file

if (data != null) {

Uri uri = data.getData();

if (uri != null) {

sendFileByUri(uri);

}

}

break;

case REQUEST_CODE_SELECT_AT_USER:

if(data != null){

String username = data.getStringExtra("username");

inputAtUsername(username, false);

}

break;

//red packet code : 發送紅包消息到聊天界面

case REQUEST_CODE_SEND_RED_PACKET:

if (data != null){

sendMessage(RedPacketUtil.createRPMessage(getActivity(), data, toChatUsername));

}

break;

case REQUEST_CODE_SEND_TRANSFER_PACKET://發送轉賬消息

if (data != null) {

sendMessage(RedPacketUtil.createTRMessage(getActivity(), data, toChatUsername));

}

break;

//end of red packet code

default:

break;

}

}

進入聊天詳情?

@Override

public void onEnterToChatDetails() {

if (chatType == Constant.CHATTYPE_GROUP) {

EMGroup group = EMClient.getInstance().groupManager().getGroup(toChatUsername);

if (group == null) {

Toast.makeText(getActivity(), R.string.gorup_not_found, Toast.LENGTH_SHORT).show();

return;

}

startActivityForResult(

(new Intent(getActivity(), GroupDetailsActivity.class).putExtra("groupId", toChatUsername)),

REQUEST_CODE_GROUP_DETAIL);

}else if(chatType == Constant.CHATTYPE_CHATROOM){

startActivityForResult(new Intent(getActivity(), ChatRoomDetailsActivity.class).putExtra("roomId", toChatUsername), REQUEST_CODE_GROUP_DETAIL);

}

}

點擊頭像?

@Override

public void onAvatarClick(String username) {

//handling when user click avatar

Intent intent = new Intent(getActivity(), UserProfileActivity.class);

intent.putExtra("username", username);

startActivity(intent);

}

消息框點擊事件、拆紅包

@Override

public boolean onMessageBubbleClick(EMMessage message) {

//消息框點擊事件,demo這里不做覆蓋,如需覆蓋,return true

//red packet code : 拆紅包頁面

if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_MESSAGE, false)){

if (RedPacketUtil.isRandomRedPacket(message)){

RedPacketUtil.openRandomPacket(getActivity(),message);

} else {

RedPacketUtil.openRedPacket(getActivity(), chatType, message, toChatUsername, messageList);

}

return true;

} else if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_TRANSFER_PACKET_MESSAGE, false)) {

RedPacketUtil.openTransferPacket(getActivity(), message);

return true;

}

//end of red packet code

return false;

}

紅包回執及消息框長按?

@Override

public void onCmdMessageReceived(List messages) {

//red packet code : 處理紅包回執透傳消息

for (EMMessage message : messages) {

EMCmdMessageBody cmdMsgBody = (EMCmdMessageBody) message.getBody();

String action = cmdMsgBody.action();//獲取自定義action

if (action.equals(RPConstant.REFRESH_GROUP_RED_PACKET_ACTION)){

RedPacketUtil.receiveRedPacketAckMessage(message);

messageList.refresh();

}

}

//end of red packet code

super.onCmdMessageReceived(messages);

}

?

@Override

public void onMessageBubbleLongClick(EMMessage message) {

// no message forward when in chat room

startActivityForResult((new Intent(getActivity(), ContextMenuActivity.class)).putExtra("message",message)

.putExtra("ischatroom", chatType == EaseConstant.CHATTYPE_CHATROOM),

REQUEST_CODE_CONTEXT_MENU);

}

擴展按鈕?

@Override

public boolean onExtendMenuItemClick(int itemId, View view) {

switch (itemId) {

case ITEM_VIDEO:

Intent intent = new Intent(getActivity(), ImageGridActivity.class);

startActivityForResult(intent, REQUEST_CODE_SELECT_VIDEO);

break;

case ITEM_FILE: //file

selectFileFromLocal();

break;

case ITEM_VOICE_CALL:

startVoiceCall();

break;

case ITEM_VIDEO_CALL:

startVideoCall();

break;

//red packet code : 進入發紅包頁面

case ITEM_RED_PACKET:

if (chatType == Constant.CHATTYPE_SINGLE) {

//單聊紅包修改進入紅包的方法,可以在小額隨機紅包和普通單聊紅包之間切換

RedPacketUtil.startRandomPacket(new RPRedPacketUtil.RPRandomCallback() {

@Override

public void onSendPacketSuccess(Intent data) {

sendMessage(RedPacketUtil.createRPMessage(getActivity(), data, toChatUsername));

}

?

@Override

public void switchToNormalPacket() {

RedPacketUtil.startRedPacketActivityForResult(ChatFragment.this, chatType, toChatUsername, REQUEST_CODE_SEND_RED_PACKET);

}

},getActivity(),toChatUsername);

} else {

RedPacketUtil.startRedPacketActivityForResult(this, chatType, toChatUsername, REQUEST_CODE_SEND_RED_PACKET);

}

break;

case ITEM_TRANSFER_PACKET://進入轉賬頁面

RedPacketUtil.startTransferActivityForResult(this, toChatUsername, REQUEST_CODE_SEND_TRANSFER_PACKET);

break;

//end of red packet code

default:

break;

}

//keep exist extend menu

return false;

}

本地文件選擇、語音通話、視頻通話、及自定義chatrow類型?

/**

* select file

*/

protected void selectFileFromLocal() {

Intent intent = null;

if (Build.VERSION.SDK_INT < 19) { //api 19 and later, we can't use this way, demo just select from images

intent = new Intent(Intent.ACTION_GET_CONTENT);

intent.setType("*/*");

intent.addCategory(Intent.CATEGORY_OPENABLE);

?

} else {

intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

}

startActivityForResult(intent, REQUEST_CODE_SELECT_FILE);

}

?

/**

* make a voice call

*/

protected void startVoiceCall() {

if (!EMClient.getInstance().isConnected()) {

Toast.makeText(getActivity(), R.string.not_connect_to_server, Toast.LENGTH_SHORT).show();

} else {

startActivity(new Intent(getActivity(), VoiceCallActivity.class).putExtra("username", toChatUsername)

.putExtra("isComingCall", false));

// voiceCallBtn.setEnabled(false);

inputMenu.hideExtendMenuContainer();

}

}

?

/**

* make a video call

*/

protected void startVideoCall() {

if (!EMClient.getInstance().isConnected())

Toast.makeText(getActivity(), R.string.not_connect_to_server, Toast.LENGTH_SHORT).show();

else {

startActivity(new Intent(getActivity(), VideoCallActivity.class).putExtra("username", toChatUsername)

.putExtra("isComingCall", false));

// videoCallBtn.setEnabled(false);

inputMenu.hideExtendMenuContainer();

}

}

?

/**

* chat row provider

*

*/

private final class CustomChatRowProvider implements EaseCustomChatRowProvider {

@Override

public int getCustomChatRowTypeCount() {

//here the number is the message type in EMMessage::Type

//which is used to count the number of different chat row

return 12;

}

?

@Override

public int getCustomChatRowType(EMMessage message) {

if(message.getType() == EMMessage.Type.TXT){

//voice call

if (message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VOICE_CALL, false)){

return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_VOICE_CALL : MESSAGE_TYPE_SENT_VOICE_CALL;

}else if (message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VIDEO_CALL, false)){

//video call

return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_VIDEO_CALL : MESSAGE_TYPE_SENT_VIDEO_CALL;

}

//red packet code : 紅包消息、紅包回執消息以及轉賬消息的chatrow type

else if (RedPacketUtil.isRandomRedPacket(message)) {

//小額隨機紅包

return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_RANDOM : MESSAGE_TYPE_SEND_RANDOM;

} else if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_MESSAGE, false)) {

//發送紅包消息

return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_RED_PACKET : MESSAGE_TYPE_SEND_RED_PACKET;

} else if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_ACK_MESSAGE, false)) {

//領取紅包消息

return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_RED_PACKET_ACK : MESSAGE_TYPE_SEND_RED_PACKET_ACK;

} else if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_TRANSFER_PACKET_MESSAGE, false)) {

//轉賬消息

return message.direct() == EMMessage.Direct.RECEIVE ? MESSAGE_TYPE_RECV_TRANSFER_PACKET : MESSAGE_TYPE_SEND_TRANSFER_PACKET;

}

//end of red packet code

}

return 0;

}

?

@Override

public EaseChatRow getCustomChatRow(EMMessage message, int position, BaseAdapter adapter) {

if(message.getType() == EMMessage.Type.TXT){

// voice call or video call

if (message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VOICE_CALL, false) ||

message.getBooleanAttribute(Constant.MESSAGE_ATTR_IS_VIDEO_CALL, false)){

return new ChatRowVoiceCall(getActivity(), message, position, adapter);

}

//red packet code : 紅包消息、紅包回執消息以及轉賬消息的chat row

else if (RedPacketUtil.isRandomRedPacket(message)) {//小額隨機紅包

return new ChatRowRandomPacket(getActivity(), message, position, adapter);

} else if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_MESSAGE, false)) {//紅包消息

return new ChatRowRedPacket(getActivity(), message, position, adapter);

} else if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_ACK_MESSAGE, false)) {//紅包回執消息

return new ChatRowRedPacketAck(getActivity(), message, position, adapter);

} else if (message.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_TRANSFER_PACKET_MESSAGE, false)) {//轉賬消息

return new ChatRowTransfer(getActivity(), message, position, adapter);

}

//end of red packet code

}

return null;

}

?

}

Redpacketlibrary

由于業務未涉及,暫不作分析。

總結及其他

其實正常集成,按照于海同學所說也就半天時間,這是因為的確環信的SDK使用起來比較方便。

通過大致的閱讀代碼,環信的Demo代碼寫的還是很不錯的,功能齊全,注釋完整。值得學習和研究。

寫在最后

多學習,多積累,多輸出。!

附:最近兩天實際工作采用環信SDK的開發詳案

環信官方Demo源碼分析及SDK簡單應用-IM集成開發詳案及具體代碼實現

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容