最近在做个项目,需要用到即时通信的功能,选定了环信的IM云来实现,关于环信IM的SDK接口,自己研究了一天,基本的功能实现了一下,这里PO出来demo。

因为只是为了验证sdk的实现,所以界面设计的比较丑,还请谅解。还有,只用到了文本消息,所以选取的sdk版本是2.X。

具体的下载链接见文末。

先上图

首先是一张消息列表,列表中的项目包括用户头像、用户名和最后一条消息显示。

第二张是会话,简单点来写,每一个项的list view的adapter都没有设置,只是简单的显示消息。点击button向对方发送“呵呵呵”的消息。

下面来阐述详细的实现。

step 1: 在manifest文件中添加users-permission 和appkey的service

这里的permission内容可以从环信文档中获取,大致如下

   <!-- Required --><uses-permission android:name="android.permission.VIBRATE" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.GET_TASKS" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /><uses-permission android:name="android.permission.WAKE_LOCK" /><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /><uses-permission android:name="android.permission.READ_PHONE_STATE" />

另外的service需要的apply如下,这里选取的是环信提供的默认appkey

<!-- 设置环信应用的appkey --><meta-data android:name="EASEMOB_APPKEY"  android:value="easemob-demo#chatdemoui" /><!-- 声明sdk所需的service SDK核心功能--><service android:name="com.easemob.chat.EMChatService" />

然后将sdk文件复制到libs文件夹中即可。这样就完成了SDK的导入工作

step 2: 环信账号登录

在登录之前,要在主的application文件中加上一条语句:

EMChat.getInstance().init(this);

保证app在首次打开时就初始化EMChat实例

然后,登录环信账号,这里需要用到当前的appkey注册到的账号和密码,我自己注册的测试用例的登录过程如下:

package com.example.demo;import com.easemob.EMCallBack;
import com.easemob.chat.EMChatManager;import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;public class MainActivity extends Activity {public static final String UA = "blyang";public static final String PA = "bing";public static final String UB = "yangbingliang";public static final String PB = "bing";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);login(UA, PA);}private void login(String userName, String password){EMChatManager.getInstance().login(userName, password, new EMCallBack(){@Overridepublic void onError(int arg0, String arg1) {Toast.makeText(MainActivity.this, "error", Toast.LENGTH_LONG).show();}@Overridepublic void onProgress(int arg0, String arg1) {// TODO Auto-generated method stub}@Overridepublic void onSuccess() {// TODO Auto-generated method stubrunOnUiThread(new Runnable(){@Overridepublic void run() {Toast.makeText(MainActivity.this, "success", Toast.LENGTH_LONG).show();                        }});//从本地DB加载到程序中EMChatManager.getInstance().loadAllConversations();startActivity(new Intent(MainActivity.this, Container.class));finish();}});}}

登录的过程就是调用EMChatManager来实现,登录成功后,进行相关的操作。这里在登录成功后,加入了一句:

//从本地DB加载到程序中
EMChatManager.getInstance().loadAllConversations();

是为了保证从本地数据库中取出历史所有的conversation对象并加载出来

step 3: 将历史对话数据加载成消息列表的形式

首先创建一个conversationList 的List对象,然后将最近的所有会话添加到这个list中,最后,调用消息列表展示到adapter,将数据传入并展示出来。具体到代码和注释如下:

package com.example.demo;import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.List;import com.easemob.chat.EMChatManager;
import com.easemob.chat.EMConversation;import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;public class ChatHistoryFragment extends Fragment{//所有的会话列表private List<EMConversation> conversationList = new ArrayList<EMConversation>();ChatHistoryAdapter adapter ;ListView chatHistoryListView;View view;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {view = inflater.inflate(R.layout.fragment_conversation_history, container, false);return view;}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);conversationList.addAll(loadConversationWithRecentChat());chatHistoryListView = (ListView) view.findViewById(R.id.list);adapter = new ChatHistoryAdapter(getActivity(), conversationList);chatHistoryListView.setAdapter(adapter);chatHistoryListView.setOnItemClickListener(new OnItemClickListener(){@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {EMConversation conversation = (EMConversation) adapter.getItem(position);Intent intent = new Intent(getActivity(), Conversation.class);intent.putExtra("userName", conversation.getUserName());startActivity(intent);}});int count = 0;for(int i=0; i<conversationList.size(); i++){count += conversationList.get(i).getUnreadMsgCount();}Log.v("count total", count+"");}/*** 获取所有会话* @return*/private Collection<? extends EMConversation> loadConversationWithRecentChat() {Hashtable<String, EMConversation> conversations = EMChatManager.getInstance().getAllConversations();List<Pair<Long, EMConversation>> sortList = new ArrayList<Pair<Long, EMConversation>>();synchronized(conversations){for(EMConversation conversation : conversations.values()){if(conversation.getAllMessages().size() != 0){sortList.add(new Pair<Long, EMConversation>(conversation.getLastMessage().getMsgTime(), conversation));}}}try{sortConversationByLastChatTime(sortList);}catch(Exception e){e.printStackTrace();}List<EMConversation> list = new ArrayList<EMConversation>();for(Pair<Long, EMConversation> sortItem : sortList){list.add(sortItem.second);}return list;}/*** 根据最后一条消息的时间排序* @param sortList*/private void sortConversationByLastChatTime(List<Pair<Long, EMConversation>> sortList) {Collections.sort(sortList, new Comparator<Pair<Long, EMConversation>>(){@Overridepublic int compare(Pair<Long, EMConversation> con1,Pair<Long, EMConversation> con2) {if(con1.first == con2.first){return 0;}else if(con2.first > con1.first){return 1;}else{return -1;   }}});}public void refresh(){conversationList.clear();conversationList.addAll(loadConversationWithRecentChat());if(adapter != null){adapter.notifyDataSetChanged();}}@Overridepublic void onResume() {super.onResume();refresh();}}

这样就完成了消息列表的展示

step 4:进入会话列表

当消息列表展示之后,要在每一个listitem被点击之后进入具体的会话展示区,也就是上图二。

在会话区,首先要注册一个广播监听器,用于接收信息(注意,如果不注册,是无法实时接收信息的)。然后当接收到信息的时候,刷新页面。在离开会话页面的时候,销毁这个广播注册即可。具体的代码和注释如下:

package com.example.demo;import com.easemob.EMCallBack;
import com.easemob.chat.EMChat;
import com.easemob.chat.EMChatManager;
import com.easemob.chat.EMConversation;
import com.easemob.chat.EMMessage;
import com.easemob.chat.EMMessage.ChatType;
import com.easemob.chat.TextMessageBody;import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;public class Conversation extends Activity{ListView listView;Button button;private EMConversation conversation;private ConversationAdapter adapter;NewMessageBroadcastReceiver msgReceiver; //广播监听器,用于接收消息@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.conversation);listView = (ListView) findViewById(R.id.conversation_list);button = (Button) findViewById(R.id.conversation_btn);conversation = EMChatManager.getInstance().getConversation(getIntent().getExtras().get("userName").toString());adapter = new ConversationAdapter(Conversation.this, conversation);listView.setAdapter(adapter);listView.setSelection(listView.getCount() - 1 );registerBroadcast();  //注册广播接收消息EMChat.getInstance().setAppInited();  //注册完广播之后,一定要声明这一句sendMsg();  //发送文本消息}/*** 注册一个接收消息的广播*/private void registerBroadcast(){//只有注册了广播才能接收到新消息,目前离线消息,在线消息都是走接收消息的广播(离线消息目前无法监听,在登录以后,接收消息广播会执行一次拿到所有的离线消息)msgReceiver = new NewMessageBroadcastReceiver();IntentFilter intentFilter = new IntentFilter(EMChatManager.getInstance().getNewMessageBroadcastAction());intentFilter.setPriority(3);registerReceiver(msgReceiver, intentFilter);//     this.unregisterReceiver(msgReceiver);}private class NewMessageBroadcastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// 注销广播abortBroadcast();// 消息id(每条消息都会生成唯一的一个id,目前是SDK生成)String msgId = intent.getStringExtra("msgid");//发送方String username = intent.getStringExtra("from");// 收到这个广播的时候,message已经在db和内存里了,可以通过id获取mesage对象EMMessage message = EMChatManager.getInstance().getMessage(msgId);if (!username.equals(username)) {// 消息不是发给当前会话,returnreturn;}conversation.addMessage(message);adapter.notifyDataSetChanged();listView.setAdapter(adapter);listView.setSelection(listView.getCount() - 1);}}/*** 发送文本消息*/private void sendMsg(){button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {//获取到与聊天人的会话对象。参数username为聊天人的userid或者groupid,后文中的username皆是如此EMConversation conversation = EMChatManager.getInstance().getConversation(MainActivity.UB);//创建一条文本消息EMMessage message = EMMessage.createSendMessage(EMMessage.Type.TXT);//设置消息bodyTextMessageBody txtBody = new TextMessageBody("呵呵呵");message.addBody(txtBody);//设置接收人message.setReceipt(MainActivity.UB);//把消息加入到此会话对象中conversation.addMessage(message);adapter.notifyDataSetChanged();listView.setAdapter(adapter);listView.setSelection(listView.getCount() - 1);//发送消息EMChatManager.getInstance().sendMessage(message, new EMCallBack(){@Overridepublic void onError(int arg0, String arg1) {}@Overridepublic void onProgress(int arg0, String arg1) {}@Overridepublic void onSuccess() {}});}});}@Overrideprotected void onDestroy() {super.onDestroy();/*** 当前Activity销毁的时候,标记所有信息为已读* 销毁广播*/conversation.markAllMessagesAsRead();this.unregisterReceiver(msgReceiver);}}

当然,这里涉及到list view的adapter,就不详细阐述了,有需求的同学请自行看代码,这里给一个下载链接:

http://download.csdn.net/detail/sinat_22013331/9471469

环信SDK调用实现即时聊天功能相关推荐

  1. android 第三方 im,Android基于环信SDK开发IM即时聊天

    目前市面上我了解的做第三方即时聊天SDK的有两家:环信.融云,这里我使用环信SDK来完成即时聊天的初步开发工作. 下面先奉上1张效果图: 1.开发准备 首先要到环信官网注册开发者账号,目前只有企业账号 ...

  2. Android基于环信SDK开发IM即时聊天(一)

    2016-09-02更新:可以看一下最新的这篇文章和源码,Android基于环信SDK开发IM即时聊天(二) 目前市面上我了解的做第三方即时聊天SDK的有两家:环信.融云,这里我使用环信SDK来完成即 ...

  3. 环信sdk android 聊天,Android基于环信SDK开发IM即时聊天

    根据用户移动地图的位置,显示在视野范围内的建筑物,简单的思路是,添加地图监听,当地图移动结束之后,计算出当前屏幕四个角的GeoPoint,根据这4个点,通过mys 目前市面上我了解的做第三方即时聊天S ...

  4. Android基于环信SDK开发IM即时聊天(二)

    声明1:北京时间现在是2019/6/10,评论里的问题我看到了,这几天我找时间看看源代码问题出在哪,在此感谢大家的监督 声明2:此Demo我是在5.1测试机上测试通过,感谢WTQ_DOMIAN的评论, ...

  5. mob sdk vue 短信验证_基于环信SDK的IM即时通讯填坑之路(vue)

    1.这里如果注册异常的type==17则代表已注册,那就直接去登录 2.这里id是依据是否在应用内已登录(自己应用,非环信), 如果是未登录(游客状态)则随机一个 Math.ceil(Math.ran ...

  6. android-使用环信SDK开发即时通信功能及源码下载

    最近项目中集成即时聊天功能,挑来拣去,最终选择环信SDK来进行开发,选择环信的主要原因是接口方便.简洁,说明文档清晰易懂.文档有android.ios.和后台服务器端,还是非常全的. 环信官网:htt ...

  7. iOS 基于环信SDK实现即时通讯-文字聊天

    这里介绍集成环信SDK3.0自定义聊天页面,后面有练习项目地址 首先到环信官网下载环信SDK.由于后续会实现语音.视频,我这里使用的是带有语音的SDK 下载完成后把HyphenateFullSDK文件 ...

  8. 使用环信sdk做一个简单的聊天APP

    使用环信sdk做一个简单的即时聊天APP,实现简单的通讯 感悟 在很早以前就想做一个简单的即时聊天app.可能自己对即时聊天的三方SDK了解的不是特别深,在进行了一段时间的学习以后感觉自己的能力达到了 ...

  9. 即时通信---环信SDK(IOS)使用教程

    一. 提前准备 注册环信即时通讯云账号 下载iOS的环信SDK 登陆到管理后台 在我的应用中创建一个应用 在苹果的个人开发中心创建一个推送证书(当然不创建也没用关系,只是不能推送消息而已) 创建完证书 ...

最新文章

  1. 为什么你的应用程序需要崩溃
  2. sklearn自学指南(part41)--使用手册的目录
  3. [SpringBoot2]welcomefavicon
  4. 2018年5月5日论文阅读
  5. java 文件中查找指定的单词,查找指定文本文件中的单词数的Java程序
  6. RTP/RTCP/RTSP/SIP/SDP简介
  7. PHP设计模式——代理模式
  8. (day 001 - 进制转换) 405. 数字转换为十六进制数
  9. python动态创建对象属性_Python学习笔记——动态添加属性与方法
  10. LaTeX 注释一行的某一部分
  11. 2019免费微信营销软件排行榜
  12. matlab 回归 工具箱,matlab回归分析——回归分析MATLAB工具箱.doc
  13. 计算机 word 节是什么,Word中的分节符是什么,如何使用?
  14. 解决win10注册错误 错误代码0x8002801c
  15. java jws-_java JWS 应用及实践
  16. 供参考的the-gan-zoo,列出的GAN相关模型和论文
  17. logits and labels must be broadcastable: logits_size=[131072,9] labels_size=[131072,8]的错误
  18. 小型NAS搭建实例②——ubuntu server 的一些设置,包含NFS挂载,CIFS挂载,常用工具安装
  19. System Verilog约束块(constrain block)控制和随机变量的随机属性控制
  20. P2P直播与点播技术简介

热门文章

  1. Spark读取HDFS文件报错:java.net.ConnectException: Call From to localhost:9000 failed on connection
  2. 关于Camera的几个重要名词解释
  3. 已解决 vmware 虚拟机安装后没有虚拟网卡问题
  4. wse抓包_WSE和时间戳记-TimeZones和Tijuana
  5. 简报 | 俄罗斯版“石油币”或将面世,能源业将迎变革
  6. android应用怎样接入广告,android应用加入广告方法
  7. 基于微信小程序的便捷记账本小程序-计算机毕业设计
  8. 淘宝助理导出CSV文件特殊字段详解
  9. 模具设计师必看的模具设计评审和设计出错。
  10. x的x次幂(蓝桥杯)