最近帮朋友弄im即时通信,简单记录下整个过程,以便以后用到:
一、Timsdk的集成
直接上腾讯云官网看文档就可以集成了;
https://www.qcloud.com/document/product/269/9227
二、初始化
1、登录TimSdk(登录前就要注册消息回调的接口):
public class Tecent_LogIn_Utils {
private String tag = "---->Tecent_LogIn_Utils";
private Context context;
private String identifier;
private String userSig;
private String groupId;
private int sdkAppId = 1400030792;
private TIMConversation conversation;
private int type;
private Message message;
private MyHandler myHandler;
private LogInImSdkCallBack resultCallBack;
public void logInImSdk(final Context context, String groupId, LogInImSdkCallBack resultCallBack, int type) {
this.type=type;
this.groupId=groupId;
this.context = context;
this.resultCallBack=resultCallBack;
this.userSig = SharedUtils.getSharedUtils().getData(context, "usersig");
this.identifier = SharedUtils.getSharedUtils().getData(context, "uid");
init();
logIn();
}
private void init() {
//初始化SDK基本配置
TIMSdkConfig config = new TIMSdkConfig(sdkAppId)
.enableCrashReport(false)
.enableLogPrint(true)
.setLogLevel(TIMLogLevel.DEBUG)
.setLogPath(Environment.getExternalStorageDirectory().getPath() + "/justfortest/");
//初始化SDK
TIMManager.getInstance().init(context, config);
TIMUserConfig userConfig = new TIMUserConfig()
.setUserStatusListener(new TIMUserStatusListener() {
@Override
public void onForceOffline() {
//被其他终端踢下线
Log.i(tag, "onForceOffline");
}
@Override
public void onUserSigExpired() {
//用户签名过期了,需要刷新userSig重新登录SDK
Log.i(tag, "onUserSigExpired");
}
})
//设置连接状态事件监听器
.setConnectionListener(new TIMConnListener() {
@Override
public void onConnected() {
Log.i(tag, "onConnected");
}
@Override
public void onDisconnected(int code, String desc) {
Log.i(tag, "onDisconnected");
}
@Override
public void onWifiNeedAuth(String name) {
Log.i(tag, "onWifiNeedAuth");
}
})
//设置群组事件监听器
.setGroupEventListener(new TIMGroupEventListener() {
@Override
public void onGroupTipsEvent(TIMGroupTipsElem elem) {
Log.i(tag, "onGroupTipsEvent, type: " + elem.getTipsType());
}
})
//设置会话刷新监听器
.setRefreshListener(new TIMRefreshListener() {
@Override
public void onRefresh() {
Log.i(tag, "onRefresh");
}
@Override
public void onRefreshConversation(List<TIMConversation> conversations) {
Log.e(tag, "onRefreshConversation, Send_RecMsg_Utils size: " + conversations.size());
}
});
//设置消息监听器,收到新消息时,通过此监听器回调
TIMManager.getInstance().addMessageListener(new TIMMessageListener() {
@Override
public boolean onNewMessages(List<TIMMessage> list) {
resultCallBack.onNewMessages(list,type);//新消息的回调,做了简单的实现;
return false;
}//消息监听器
});
TIMManager.getInstance().setUserConfig(userConfig);
}
private void logIn() {
message=new Message();
myHandler=new MyHandler(context,resultCallBack);
// identifier为用户名,userSig 为用户登录凭证
TIMManager.getInstance().login(identifier, userSig, new TIMCallBack() {
@Override
public void onError(int code, String desc) {
//错误码code和错误描述desc,可用于定位请求失败原因
Log.e(tag, "login failed. code: " + code + " errmsg: " + desc);
message.what=2;
message.obj = null;
message.arg1=Tecent_LogIn_Utils.this.type;
myHandler.sendMessage(message);
}
@Override
public void onSuccess() {
//获取会话
conversation=getGroupConversation(groupId);
message.what=1;
message.obj = conversation;
message.arg1=Tecent_LogIn_Utils.this.type;
myHandler.sendMessage(message);
}
});
}
```
三、获取会话,该会话是用来发送消息的:
public TIMConversation getSingleConversation(String peer) {
return TIMManager.getInstance().getConversation(TIMConversationType.C2C, peer);
}
/*//获取群聊会话
* groupId 群组的id
* */
public TIMConversation getGroupConversation(String groupId) {
return TIMManager.getInstance().getConversation(TIMConversationType.Group, groupId);
}
}
四、发送消息
public static boolean sendMsg(TIMConversation conversation, String message) {
//构造一条消息
TIMMessage msg = new TIMMessage();
//添加文本内容
TIMTextElem elem = new TIMTextElem();
elem.setText(message);
//将elem添加到消息
if (msg.addElement(elem) != 0) {
Log.d(tag, "addElement failed");
return false;
}
//发送消息
conversation.sendMessage(msg, new TIMValueCallBack<TIMMessage>() {//发送消息回调
@Override
public void onError(int code, String desc) {//发送消息失败
//错误码code和错误描述desc,可用于定位请求失败原因
Log.e(tag, "send message failed. code: " + code + " errmsg: " + desc);
isSend = false;
}
@Override
public void onSuccess(TIMMessage msg) {//发送消息成功
Log.e(tag, "send message ok ");
isSend = true;
}
});
return isSend;
}
一个基本的流程就是这样了 ,另外需要注意的是:发送消息必须在拿到会话实例之后,本文用handler做了异步的处理;
下面贴一下聊天页面的布局:
一、适配器
public class Chat_ListView_Adapter extends BaseAdapter {
private String url_me;
private Activity context;
private List<RecMsgBean> list_rec;
private LayoutInflater mInflater;
public static final int MESSAGE_LEFT = 0;
public static final int MESSAGE_RIGHT = 1;
private static final int RETURN_TYPE_COUNT = 2;
private Map<Integer, TextView> map_text_me, map_text_other;
public Chat_ListView_Adapter(Activity context,List<RecMsgBean> list) {
this.context = context;
this.list_rec = list;
map_text_me = new HashMap<>();
map_text_other = new HashMap<>();
this.mInflater = LayoutInflater.from(context);
url_me = SharedUtils.getSharedUtils().getData(context, "headimg");
}
public void setList(List<RecMsgBean> list_rec) {
this.list_rec = list_rec;
url_me = SharedUtils.getSharedUtils().getData(context, "headimg");
}
@Override
public int getCount() {
return (list_rec != null) ? (list_rec.size()) : (0);
}
@Override
public int getViewTypeCount() {
return RETURN_TYPE_COUNT;
}
@Override
public int getItemViewType(int position) {
return list_rec.get(position).getType();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolderLeft viewHolderLeft = null;
ViewHolderRight viewHolderRight = null;
if (convertView == null) {
// 根据获得的type类型确定选择哪个layout
switch (getItemViewType(position)) {
case MESSAGE_LEFT:
viewHolderLeft = new ViewHolderLeft();
convertView = mInflater.inflate(R.layout.family_chat_list_item_rec, null);
viewHolderLeft.textView_other = (TextView) convertView.findViewById(R.id.chat_item_text_other);
viewHolderLeft.imageView_other = (RoundImagViewUtil) convertView.findViewById(R.id.chat_item_img_other);
convertView.setTag(viewHolderLeft);
break;
case MESSAGE_RIGHT:
viewHolderRight = new ViewHolderRight();
convertView = mInflater.inflate(R.layout.family_chat_list_item_me, null);
viewHolderRight.textView_me = (TextView) convertView.findViewById(R.id.chat_item_text_me);
viewHolderRight.imageView_me = (RoundImagViewUtil) convertView.findViewById(R.id.chat_item_img_me);
convertView.setTag(viewHolderRight);
break;
default:
break;
}
}else {
switch (getItemViewType(position)) {
case MESSAGE_LEFT:
viewHolderLeft= (ViewHolderLeft) convertView.getTag();
break;
case MESSAGE_RIGHT:
viewHolderRight= (ViewHolderRight) convertView.getTag();
break;
}
}
switch (getItemViewType(position)) {
case MESSAGE_LEFT:
viewHolderLeft.textView_other.setText(list_rec.get(position).getMsg());
viewHolderLeft.textView_other.setBackgroundResource(R.drawable.other_qipao);
BaseActivity.loadingImageLoader(context, list_rec.get(position).getHeadurl(), viewHolderLeft.imageView_other);
break;
case MESSAGE_RIGHT:
viewHolderRight.textView_me.setText(list_rec.get(position).getMsg());
viewHolderRight.textView_me.setBackgroundResource(R.drawable.wo_qipao);
BaseActivity.loadingImageLoader(context, url_me, viewHolderRight.imageView_me);
break;
default:
break;
}
return convertView;
}
private class ViewHolderLeft{
TextView textView_other;
RoundImagViewUtil imageView_other;
}
private class ViewHolderRight{
TextView textView_me;
RoundImagViewUtil imageView_me;
}
}
二、xml布局:主布局使用listview或者RecyclerView就好了 ,item布局需要两个:
别人发消息的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<LinearLayout
android:id="@+id/chat_linear_other"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.buji.shuzhekan.view.RoundImagViewUtil
android:layout_width="35dp"
android:layout_height="35dp"
android:id="@+id/chat_item_img_other"
android:layout_gravity="center_vertical"/>
<TextView
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:paddingLeft="10dp"
android:paddingRight="8dp"
android:textColor="@color/brite"
android:layout_marginLeft="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/chat_item_text_other"/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
自己发消息的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<LinearLayout
android:id="@+id/chat_linear_me"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentRight="true"
android:layout_below="@+id/chat_linear_other">
<TextView
android:paddingTop="8dp"
android:paddingLeft="8dp"
android:paddingBottom="8dp"
android:paddingRight="10dp"
android:layout_weight="1"
android:textColor="@color/brite"
android:layout_marginRight="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/chat_item_text_me"/>
<com.buji.shuzhekan.view.RoundImagViewUtil
android:layout_width="35dp"
android:layout_height="35dp"
android:id="@+id/chat_item_img_me"/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
这样一个简单的聊天功能就能够实现了 ,更多强大的功能也只需要看文档一步一步来就好了。