前言:

关于即时通讯,项目中要是需要一个收发消息的功能。从开始到写完即时通讯这块儿,花了大约3天时间。但真的想吐槽下bmobIM的服务器,有短板时间都在等待连接:disconnect或者java.util.concurrent.TimeoutException。问他们客服,他们说是IM的带宽满了。原话是这样:IM带宽满了。心里也是一万个无奈呀,但是也没办法,项目负责人点名了bmob,那就来吧:

集成:

bmob的文档这块儿写得算是不错了,我来整理一下:

  • IM SDK使用Data SDK的BmobFile用于图片、语音等文件消息的发送,即特定的IM SDK只能和特定版本的Data SDK匹配。
IM SDK 版本 Data SDK 版本
bmob-im:2.0.1 至 2.0.2 bmob-sdk:3.4.6-0304
bmob-im:2.0.3 至 2.0.4 bmob-sdk:3.4.6
bmob-im:2.0.5 bmob-sdk:3.4.7-aar
bmob-im:2.0.6 至 2.0.8 bmob-sdk:3.5.5
bmob-im:2.0.9 bmob-sdk:3.5.6
bmob-im:2.1.1 bmob-sdk:3.6.3
  • 在project下面的build.gradle文件中添加maven仓库地址:
buildscript {repositories {jcenter()}dependencies {classpath 'com.android.tools.build:gradle:1.3.0'}
}allprojects {repositories {jcenter()//TODO 集成:1.1、配置Bmob的maven仓库地址maven { url "https://raw.github.com/bmob/bmob-android-sdk/master" }}
}task clean(type: Delete) {delete rootProject.buildDir
}
  • 在app下的build.gradle文件中添加dependencies外部依赖:(此处注意Data和IM的SDK版本的对应关系)
 dependencies {compile fileTree(dir: 'libs', include: ['*.jar'])//TODO 集成:1.2、配置IM SDK(bmob-im)版本和Data SDK(bmob-sdk)版本:特定版本的bmob-im依赖特定版本的bmob-sdkcompile 'cn.bmob.android:bmob-im:2.1.1@aar'compile 'cn.bmob.android:bmob-sdk:3.6.3'}
  • 在AndroidManifest.xml下添加你的APP KEY:
<?xml version="1.0" encoding="utf-8"?>
<manifest ...//权限<application...<meta-dataandroid:name="Bmob_APP_KEY"android:value="fef642bee9678388a478d8b5b25bafa0" />...</application></manifest>
  • 权限:
 <!--TODO 1.4、配置IM SDK需要的权限--><!--网络权限 --><uses-permission android:name="android.permission.INTERNET" /><!-- 监听网络的变化 --><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /><!-- 设备休眠 --><uses-permission android:name="android.permission.WAKE_LOCK" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><!-- sd卡存储--><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><!--摄像头--><uses-permission android:name="android.permission.CAMERA" /><!--录音--><uses-permission android:name="android.permission.RECORD_AUDIO" /><!--通知震动--><uses-permission android:name="android.permission.VIBRATE" />
  • 在AndroidManifest.xml下添加service、receiver标签:
<?xml version="1.0" encoding="utf-8"?>
<manifest ...//权限<application...<!--TODO 集成:1.5、配置IM SDK需要的广播和服务--><receiver android:name="cn.bmob.newim.core.ConnectChangeReceiver" ><intent-filter><action android:name="cn.bmob.action.RECONNECT" /><action android:name="android.net.conn.CONNECTIVITY_CHANGE" /><action android:name="android.intent.action.BOOT_COMPLETED" /><action android:name="android.intent.action.USER_PRESENT" /></intent-filter></receiver><serviceandroid:name="cn.bmob.newim.core.service.BmobIMService"android:process=":bmobcore" /><serviceandroid:name="cn.bmob.newim.core.service.NotifyService"android:process=":bmobcore" /><service android:name="cn.bmob.newim.core.service.ReConnectService" /><service android:name="cn.bmob.newim.core.service.HeartBeatService" />...</application></manifest>

项目的集成到这儿就结束了,剩下的就是如何使用这些东西了,简单看下我的流程图。

创建会话列表和好友列表(RecycleView)

  • 首先说下个人认为官方文档中最难理解的一个名词:会话。会话分为暂态会话常态会话。我对会话的理解:就好比两个好友打电话时,要有一条连通的电话线一样,要实现IM,也要有连通双方的一根线,而这根线就相当于是会话。应用在本地都会有数据表,用来存储应用中的数据。暂态会话不会保存在本地数据库中;常态会话会被保存到本地数据库中(暂态会话可以用来加好友,常态会话用来聊天)。
  • 怪当时太年轻,以为即时通讯就只是聊天,在使用SDK完成加好友操作之后才看的IM文档,所以暂态会话这里就不说了,但是道理应该是相通的,相信看完常态会话之后,态会话都不是事儿。
  • 即时通讯Demo中有两个RecycleView,一个用来存储好友列表,一个用来存储会话列表。而会话列表在你搞完发消息之前肯定是空的

好友列表:(好友的添加就不说了,自行添加一些好友就行)

会话列表:(当然你的肯定是空的)

RecycleView点击事件-创建会话入口

首先看下官方的Demo:

adapter.setOnRecyclerViewListener(new OnRecyclerViewListener() {@Overridepublic void onItemClick(int position) {if (position == 0) {//跳转到新朋友页面startActivity(NewFriendActivity.class, null);} else {Friend friend = adapter.getItem(position);User user = friend.getFriendUser();BmobIMUserInfo info = new BmobIMUserInfo(user.getObjectId(), user.getUsername(), user.getAvatar());//TODO 会话:4.1、创建一个常态会话入口,好友聊天BmobIMConversation conversationEntrance = BmobIM.getInstance().startPrivateConversation(info, null);Bundle bundle = new Bundle();bundle.putSerializable("c", conversationEntrance);Intent intent = new Intent();intent.setClass(getActivity(), ChatActivity.class);if (bundle != null) {intent.putExtra(getActivity().getPackageName(), bundle);}getActivity().startActivity(intent);}}

由Demo可知,用BmobIMConversation来创建常态会话,传入参数(info,null)

  • info:会话肯定要知道会话双方的信息,方便服务器转发消息。一方是自己,由BmobUser.getCurrentUser()即可得到自己的信息,自己的信息应该默认已经传进去了,不需要我们管;而另一方,也就是通信对方的信息,就需要info传入会话人口了,info为BmobIMUserInfo类型,需传入(用户id,用户name,用户头像(Url)),其构造和函数:
    public BmobIMUserInfo(String var1, String var2, String var3) {this.userId = var1;this.name = var2;this.avatar = var3;}
  • startPrivateConversation(info, null)默认为创建常态会话,若要创建暂态会话,可BmobIMConversation conversationEntrance = BmobIM.getInstance().startPrivateConversation(info, true, null);
  • Demo中后面代码意思就是把创建好的conversationEntrance传给会话界面,我的方法是:
    BmobIMUserInfo info = new BmobIMUserInfo(list.get(i).getObjectId(), list.get(i).getNickName(), list.get(i).getPicture_head().getFileUrl());BmobIMConversation conversation = BmobIM.getInstance().startPrivateConversation(info, null);fragmentManager.beginTransaction().hide(fragmentManager.findFragmentByTag("text_button_wodeqiuyou")).remove(fragmentManager.findFragmentByTag("text_button_wodeqiuyou")).add(R.id.fragment_container, FragmentIM.newInstance(list.get(i).getNickName(), list.get(i).getObjectId(), conversation), "im_Layout").commit();

意思就是在构造方法中传个参数conversationEntrance即可,之后在发送消息时会用到。

  • 我的构造函数:
public static FragmentIM newInstance(String name, String id, BmobIMConversation conversation) {FragmentIM fragmentIM = new FragmentIM();fragmentIM.name = name;fragmentIM.id = id;fragmentIM.conversation = conversation;return fragmentIM;
}

发送消息

  • 在会话界面首先初始化会话管理员:
    private BmobIMConversation mConversationManager;...@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_im, container, false);mConversationManager = BmobIMConversation.obtain(BmobIMClient.getInstance(), conversation);...return view;}
  • 在这之后,就可以设置button的点击发送消息:
btn_chat_send.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String text = editText.getText().toString();//text即发送的消息if (BmobIM.getInstance().getCurrentStatus().getCode() != ConnectionStatus.CONNECTED.getCode()) {Toast.makeText(getContext(), "尚未连接IM服务器", Toast.LENGTH_SHORT).show();} else if (text.trim().equals("")) {Toast.makeText(getContext(), "请输入内容", Toast.LENGTH_SHORT).show();} else {final BmobIMTextMessage message = new BmobIMTextMessage();message.setContent(text);//可随意设置额外信息Map<String, Object> map = new HashMap<>();map.put("level", "1");message.setExtraMap(map);message.setExtra("OK");mConversationManager.sendMessage(message, listener);}}});
  • 我的消息发送器:(如果打出Toast,那么说明发送成功)
  /*** 消息发送监听器*/public MessageSendListener listener = new MessageSendListener() {@Overridepublic void onProgress(int value) {super.onProgress(value);//文件类型的消息才有进度值Log.e(TAG, "onProgress: " + value);}@Overridepublic void onStart(BmobIMMessage msg) {super.onStart(msg);chatAdapter.addMessage(msg);editText.setText("");scrollToBottom();}@Overridepublic void done(BmobIMMessage msg, BmobException e) {Toast.makeText(getContext(), "发送成功", Toast.LENGTH_SHORT).show();chatAdapter.notifyDataSetChanged();editText.setText("");scrollToBottom();if (e != null) {Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show();Log.e(TAG, "done: " + e.getMessage());}}};

接收消息

  • 按照官方文档所说,创建全局消息接收器(个人建议创建全局消息接收器)
//TODO 集成:1.6、自定义消息接收器处理在线消息和离线消息
public class DemoMessageHandler extends BmobIMMessageHandler {@SuppressLint("SimpleDateFormat")SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");private static final String TAG = "DemoMessageHandler";@Overridepublic void onMessageReceive(final MessageEvent event) {//在线消息Log.e(TAG, "bindView:  getFromId "+event.getMessage().getFromId() );Log.e(TAG, "bindView:  getContent "+event.getMessage().getContent() );Log.e(TAG, "bindView:  getExtra "+event.getMessage().getExtra() );Log.e(TAG, "bindView:  getToId "+event.getMessage().getToId() );Log.e(TAG, "bindView:  getCreateTime "+df.format(event.getMessage().getCreateTime()));Log.e(TAG, "bindView:  getReceiveStatus "+event.getMessage().getReceiveStatus() );FragmentIM.chatAdapter.addMessage(event.getMessage());}@Overridepublic void onOfflineReceive(final OfflineMessageEvent event) {//离线消息,每次connect的时候会查询离线消息,如果有,此方法会被调用Map<String, List<MessageEvent>> map = event.getEventMap();//挨个检测下离线消息所属的用户的信息是否需要更新Toast.makeText(MainActivity.context, "有" + map.size() + "个用户发来离线消息", Toast.LENGTH_SHORT).show();for (Map.Entry<String, List<MessageEvent>> entry : map.entrySet()) {List<MessageEvent> list = entry.getValue();int size = list.size();Log.e(TAG, "onOfflineReceive: "+"用户" + entry.getKey() + "发来" + size + "条消息" );for (int i = 0; i < size; i++) {Log.e(TAG, "bindView:  离线消息: "+i+ "  getFromId "+list.get(i).getMessage().getFromId() );Log.e(TAG, "bindView:  离线消息: "+i+ "  getContent "+list.get(i).getMessage().getContent() );Log.e(TAG, "bindView:  离线消息: "+i+ "  getExtra "+list.get(i).getMessage().getExtra() );Log.e(TAG, "bindView:  离线消息: "+i+ "  getToId "+list.get(i).getMessage().getToId() );Log.e(TAG, "bindView:  离线消息: "+i+ "  getCreateTime "+df.format(list.get(i).getMessage().getCreateTime()));Log.e(TAG, "bindView:  离线消息: "+i+ "  getReceiveStatus "+list.get(i).getMessage().getReceiveStatus() );}}}
}
  • 在消息界面也有个RecycleView:

  • 我的Adapter的addMessage和addMessages方法:
    public void addMessage(BmobIMMessage message) {messageList.addAll(Arrays.asList(message));notifyDataSetChanged();FragmentIM.scrollToBottom();//将RecycleView滑动到最低端}public void addMessages(List<BmobIMMessage> messages) {messageList.addAll(0, messages);notifyDataSetChanged();FragmentIM.scrollToBottom();//将RecycleView滑动到最低端}
  • FragmentIM.scrollToBottom()方法:
    public static void scrollToBottom() {layoutManager.scrollToPositionWithOffset(chatAdapter.getItemCount() - 1, 0);}

如此,一个简单的即时通讯Demo就完成了。

基于Bmob的简单即时通讯相关推荐

  1. bs模式Java web,基于BS模式的即时通讯系统的设计与实现(MyEclipse)

    基于BS模式的即时通讯系统的设计与实现(MyEclipse)(包含选题审批表,任务书,开题报告,中期检查表,毕业论文13000字,答辩记录,成绩评定册,源程序) 摘  要:即时通讯(Instant M ...

  2. java xmpp协议_GitHub - zhengzhi530/xmpp: 基于Xmpp协议的即时通讯社交软件(客户端+服务端)...

    yyquan 开源一个自己去年写的基于Xmpp协议的即时通讯社交软件 (客户端+服务端) 本项目仅供参考,对于正在学习Xmpp以及javaweb后台的同学,可以看一下. 做这个项目纯属个人兴趣爱好,所 ...

  3. 基于Linux下的即时通讯聊天室项目(全代码 有注释 可直接运行)

    基于Linux下的即时通讯聊天室项目 一.序言 二.具体功能 三.系统客户要求 四.具体代码 1.服务器代码 2.客户端代码 一.序言 最近在写一个基于Linux下的聊天工具 它适合于局域网内所有人进 ...

  4. 基于Android开发的即时通讯聊天app

    基于Android开发的即时通讯聊天app 前言 即时通讯(Instant Messaging,简称IM)在互联网中应用十分广泛,它可以和很多的领域结合,发挥十分重要的作用.比如金融行业的支付宝.各大 ...

  5. java 幻影_幻影(Phantom)消息平台,是一款基于Java实现的即时通讯(IM)系统

    Phantom-Platform 介绍 幻影(Phantom)消息平台,是一款基于Java实现的即时通讯(IM)系统. 提供支持单聊.群聊.SDK等通用的技术通讯组件,开箱即用. 软件架构 构建 项目 ...

  6. 基于socket的可发送表情简单即时通讯

    前言 这段时间做的东西比较杂,但是对学习来说还是很有帮助的,这次做的基于socket的即时通讯也是为了更加了解IM,本来是打算使用openfire或者apollo服务器来实现的,但是中途时间上的问题, ...

  7. 基于融云的即时通讯开发(一)

    一.概述 现在的应用中,即时通讯功能已经很普遍了,从这篇文章开始,我们以第三方平台融云的服务为基础,研究一下如何开发一个具有及时通信功能的软件. 首先,进入融云的官网,地址如下: http://ron ...

  8. 基于websocket协议的即时通讯webapp(摘自本人毕业论文)

    即时通讯实现 功能结构图 Spring WebSocket配置 本软件的即时通讯技术采用了WebSocket协议,因为从spring4.0的版本才开始支持WebSocket,所以本软件服务端的spri ...

  9. 基于B/S的即时通讯微博系统

    技术:Java.JSP等 摘要: 随着信息时代的发展,人们对于网络社交的需求愈发强烈,互联网上也涌现出如新浪微博,贴吧留言贴,聊天室等一些成熟的应用软件.本微博系统使用 Java 语言进行开发,采用了 ...

最新文章

  1. mysql七:视图、触发器、事务、存储过程、函数
  2. 小团队 vs 大团队
  3. 关于python变量_关于python变量练习题
  4. 1220.统计元音字母序列的数目-LeetCode
  5. js中变量名提升和函数名提升
  6. HDU1872 稳定排序【稳定排序】
  7. svn 服务器修改密码,用户自行修改svn密码的简单服务
  8. Verilog入门教程与实例分享
  9. pmp学习资料下载-pmp备考
  10. 「架构师必备」java程序员面试宝典百度云
  11. 一个汉字到底占几个字节
  12. ExecuteNonQuery()的用法
  13. 【机器人栅格地图】基于蚁群优化遗传算法求解机器人栅格地图最短路径规划问题附Matlab源码
  14. 设置了监视哨的顺序查找算法效率高?你确定吗?
  15. 识别表格变成电子版的软件有什么?这些识别软件分享给你
  16. 71页全域旅游综合整体解决方案2021 ppt
  17. 希尔伯特变换与单边带调制
  18. 结对编程----五子棋游戏
  19. php 使用apache中的ab进行页面压力测试
  20. SleepBetter Privacy Policy

热门文章

  1. 介绍一下三电平Boost变换器工作原理
  2. 4个优质产品帮助中心实例——教你如何提升用户体验和销售
  3. String字符串和ascii码互转
  4. Unity3d--改进飞碟游戏 作业6
  5. Chrome浏览器小号多开
  6. 北京人在北京租房是什么感受?
  7. 英文脏话大全(骂人专用)
  8. 可以删除电脑文件的c语言程序,Win7c盘哪些文件可以删除?高手教你完美清理Win7 C盘...
  9. 密码中用到的特殊字符有哪些?
  10. python是什么职业_Python是个什么鬼?为什么那么多工作“会Python优先”?