源代码下载

转载请注明出处,谢谢!

最终版已上传。优化下拉刷新、增加来消息声音提示、主界面改成ViewPager,实现左右滑动、新增群组、最近会话显示条数,开始上班了,不再修改了。谢谢!

国庆这几天,闲着无聊,仿照QQ2012,做了一个基于socket的聊天工具,由于代码比较多,今天就不在文章中贴出代码,需要的朋友可以点击上面下载,谢谢,后续会详细贴出各模块代码,并解释,敬请期待,O(∩_∩)O,有什么问题或者bug,欢迎给我留言。

首先说一下我的整体思路:整个聊天是通过服务器转发的,这样处理起来比较简单,但是服务器压力会特别大。建议在真正做项目的时候,服务器只处理用户注册、登录以及判断用户是否掉线等,至于聊天、传文件以及视频等就在用户之间单独建立连接,这样可以大大减少服务器的压力,我这里就没考虑这么多了。

第一:我们定义一个超级消息对象(记得要序列化),它包含:消息类型、具体的消息对象、发送给谁以及来自谁。服务器和客户端就是通过发送这个超级消息对象来进行通讯的。

第二:服务器,在接受用户连接之后,马上把socket丢入线程池中,这样可以支持多用户并发访问,然后根据用户的socket对象,分别建立一条读消息线程写消息线程(在这里,写消息线程要先建立,我们需要传递给读消息线程,因为我们在读完消息之后会给用户回复消息)。在读消息线程里面根据消息类型处理超级消息对象,分别是:注册、登录、下线、转发消息、文件、刷新好友列表等。后台数据库处理的话,我们通过dao模式,这样很方便,而且会使代码显得简洁、明了、有条理,总之是各种好,哈哈。最后要注意一点:因为我们是转发消息,所以在用户登录成功后,我们需要把该用户的写消息线程根据用户的ID存入一个Map中,以便在转发消息的时候,可以根据用户ID取出对应的写消息线程,从而实现转发消息。

第三:客户端,跟服务器类似,只是没有线程池,在用户连接上服务器之后,也是根据连接后的socket对象,分别建立一条读消息线程写消息线程然后在代码中哪里需要发消息,就通过get方法获取写消息线程,哪里需要读消息,就通过get方法获取读消息线程

第四:关于写消息线程处理,因为服务器或者客户端,不可能时时需要写消息,因此我们如果用一个死循环去处理写线程,明显的是不明智的,因此我做了一个简单的处理,在写消息的死循环中先wait(),当我们调用写消息线程的setMessage方法后,就notify唤醒写线程,发送完消息之后,继续wait(),这里我贴出核心代码:

[java] view
plain
copy

  1. <span style="font-size:14px;"> public void setMsg(TranObject msg) {
  2. this.msg = msg;
  3. synchronized (this) {
  4. notify();
  5. }
  6. }
  7. @Override
  8. public void run() {
  9. try {
  10. while (isStart) {
  11. if (msg != null) {
  12. oos.writeObject(msg);
  13. oos.flush();
  14. if (msg.getType() == TranObjectType.LOGOUT) {// 如果是发送下线的消息,就直接跳出循环
  15. break;
  16. }}
  17. synchronized (this) {
  18. wait();// 发送完消息后,线程进入等待状态
  19. }
  20. }
  21. oos.close();// 循环结束后,关闭输出流和socket
  22. if (socket != null)
  23. socket.close();
  24. } catch (InterruptedException e) {
  25. e.printStackTrace();
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }</span>

第五:具体手机客户端的处理,因为android有自己的特点,也有自己的优势,所以我们要充分利用它的优势,避开他的缺点来处理消息,我说一下我在这个小项目中处理消息的思路:我在用户启动程序的时候,开启一个获取消息的service,在该service中建立连接,然后通过一个接口去监听读消息线程收到的消息,在收到消息的同时,把该超级消息对象通过广播发送出去,然后自定义一个抽象的MyActivity继承Activity,在MyActivity里面通过一个广播接收者接收service中发送过来的消息,并通过一个抽象方法传递给子Activity,我们的其他activity如果要处理收消息,就可以继承我们自定义的MyActivity,然后实现那个抽象方法,就可以了,这样很好的处理了不同的activity接收消息的缺点,而且后台处理也很方便,我不知道腾讯QQ在这个方面是怎么处理的,这是我个人的想法而已。下面贴出MyActivity的代码:

[java] view
plain
copy

  1. <span style="font-size:14px;">/**
  2. * 自定义一个抽象的MyActivity类,每个Activity都继承他,实现消息的接收(优化性能,减少代码重复)
  3. *
  4. * @author way
  5. *
  6. */
  7. public abstract class MyActivity extends Activity {
  8. /**
  9. * 广播接收者,接收GetMsgService发送过来的消息
  10. */
  11. private BroadcastReceiver MsgReceiver = new BroadcastReceiver() {
  12. @Override
  13. public void onReceive(Context context, Intent intent) {
  14. TranObject msg = (TranObject) intent
  15. .getSerializableExtra(Constants.MSGKEY);
  16. if (msg != null) {//如果不是空,说明是消息广播
  17. // System.out.println("MyActivity:" + msg);
  18. getMessage(msg);// 把收到的消息传递给子类
  19. } else {//如果是空消息,说明是关闭应用的广播
  20. close();
  21. }
  22. }
  23. };
  24. /**
  25. * 抽象方法,用于子类处理消息,
  26. *
  27. * @param msg
  28. *            传递给子类的消息对象
  29. */
  30. public abstract void getMessage(TranObject msg);
  31. /**
  32. * 子类直接调用这个方法关闭应用
  33. */
  34. public void close() {
  35. Intent i = new Intent();
  36. i.setAction(Constants.ACTION);
  37. sendBroadcast(i);
  38. finish();
  39. }
  40. @Override
  41. public void onStart() {// 在start方法中注册广播接收者
  42. super.onStart();
  43. IntentFilter intentFilter = new IntentFilter();
  44. intentFilter.addAction(Constants.ACTION);
  45. registerReceiver(MsgReceiver, intentFilter);// 注册接受消息广播
  46. }
  47. @Override
  48. protected void onStop() {// 在stop方法中注销广播接收者
  49. super.onStop();
  50. unregisterReceiver(MsgReceiver);// 注销接受消息广播
  51. }
  52. }
  53. </span>

好了,大概思路就是这样的,下面根据具体的测试截图,说说我的思路:

1.桌面快捷方式                                                                         2.欢迎界面

        

3.正在登陆                                                                                 4.登陆成功后的好友列表,通过ViewPager实现

       

5.好友列表是自定义的ExpandableListView,可以下拉刷新        6.群组聊天功能暂未实现

    

7.聊天主界面,                                                                           8.ViewPager实现左右滑动

      

9.最近会话显示                                                                        10.未进入聊天界面时,来消息提醒,并保存数据库

       

11.后台运行来消息时提醒,有声音有振动,左图为收到新消息,右图为无新消息时状态,

  

12.后台数据库(上:user表,下:好友列表),密码通过MD5方式加密了,用户注册成功后,即生成一个以用户id命名的表,用来保存好友。

13.服务器运行提示

14.注册状态已经成功后的提示

 

最后来几张聊天截图,好了今天就到这里,后续会继续跟大家分享其他各个小模块的具体实现,先休息一下,玩两天,马上要上班了,吼吼....

 

Android之高仿手机QQ聊天的更多相关文章

  1. 高仿手机QQ音乐之——Android带进度条的开关

    最新版的手机QQ音乐体验确实不错,发现首页播放按钮能够显示歌曲当前进度条.认为挺有新意.效果例如以下: 自己琢磨了下.能够用自己定义组件来实现,试着做了一下.效果例如以下: 整理了下思路.大概设计流程 ...

  2. vue-miniQQ——基于Vue2实现的仿手机QQ单页面应用(接入了聊天机器人,能够进行正常对话)

    使用Vue2进行的仿手机QQ的webapp的制作,作品由个人独立开发,源码中进行了详细的注释. 由于自己也是初学Vue2,所以注释写的不够精简,请见谅. 项目地址 https://github.com ...

  3. Android高级控件(六)——自定义ListView高仿一个QQ可拖拽列表的实现

    Android高级控件(六)--自定义ListView高仿一个QQ可拖拽列表的实现 我们做一些好友列表或者商品列表的时候,居多的需求可能就是需要列表拖拽了,而我们选择了ListView,也是因为使用L ...

  4. HTML5仿手机微信聊天界面

    HTML5仿手机微信聊天界面 这篇文章主要为大家详细介绍了HTML5仿手机微信聊天界面的关键代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下     给大家带来的是HTML5仿手机微信聊天界面, ...

  5. android版高仿淘宝客户端源码V2.3

    android版高仿淘宝客户端源码V2.3,这个版本我已经更新到2.3了,源码也上传到源码天堂那里了,大家可以看一下吧,该应用实现了我们常用的购物功能了,也就是在手机上进行网购的流程的,如查看产品(浏 ...

  6. Android 高仿微信实时聊天 基于百度云推送

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38799363 ,本文出自:[张鸿洋的博客] 一直在仿微信界面,今天终于有幸利用百 ...

  7. Android 高仿微信即时聊天 百度云为基础的推

    转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/38799363 ,本文出自:[张鸿洋的博客] 一直在仿微信界面,今天最终有幸利用百 ...

  8. Android 高仿微信语音聊天页面高斯模糊效果

    目前的应用市场上,使用毛玻璃效果的APP随处可见,比如用过微信语音聊天的人可以发现,语音聊天页面就使用了高斯模糊效果. 先看下效果图: 仔细观察上图,我们可以发现,背景图以用户头像为模板,对其进行了高 ...

  9. Android实现高仿QQ附近的人搜索展示

    本文主要实现了高仿QQ附近的人搜索展示,用到了自定义控件的方法 最终效果如下 1.下面展示列表我们可以使用ViewPager来实现(当然如果你不觉得麻烦,你也可以用HorizontalScrollVi ...

随机推荐

  1. UVA 11039 - Building designing 水题哇~

    水题一题,按绝对值排序后扫描一片数组(判断是否异号,我是直接相乘注意中间值越界)即可. 感觉是让我练习sort自定义比较函数的. #include<cstdio> #include< ...

  2. 10.4 android输入系统_框架、编写一个万能模拟输入驱动程序、reader/dispatcher线程启动过程源码分析

    1. 输入系统框架 android输入系统官方文档 // 需FQhttp://source.android.com/devices/input/index.html <深入理解Android 卷 ...

  3. UIScrollView(滚动试图)

    UIScrollView(滚动试图) 1.简介 为什么有UISCrollView: 在iOS开发中,由于移动设备的屏幕大小有限,所以不能像PC一样显示很多内容,因此当手机屏幕需要展示的内容较多超出一个 ...

  4. 分析Net 内存对象

    .Net 内存对象分析   在生产环境中,通过运行日志我们会发现一些异常问题,此时,我们不能直接拿VS远程到服务器上调试,同时日志输出的信息无法百分百反映内存中对象的状态,比如说我们想查看进程中所有的 ...

  5. LibCurl HTTP部分详细介绍

    目录索引: 一.LibCurl基本编程框架 二.一些基本的函数 三.curl_easy_setopt函数部分选项介绍 四.curl_easy_perform 函数说明(error 状态码) 五.lib ...

  6. SpringMvc中两个Controller类之间传递参数的方法

    使用SpringMvc框架,在访问ControllerA的时候,将A里面的参数传递到ControllerB中.适用于同一框架下两个不同Controller或者由rpc(dubbo)连接的两个工程里的C ...

  7. android SQLite 使用实例

    Android作为眼下主流的移动操作系统,全然符合SQLite占用资源少的优势,故在Android平台上,集成了一个嵌入式关系型数据库-SQLite.假设想要开发 Android 应用程序,须要在 A ...

  8. java生成UUID通用唯一识别码 (Universally Unique Identifier) 分类: B1_JAVA 2014-08-22 16:09 331人阅读 评论(0) 收藏

    转自:http://blog.csdn.net/carefree31441/article/details/3998553 UUID含义是通用唯一识别码 (Universally Unique Ide ...

  9. QQ互联API接口失效,第三方网站的死穴

    最近2个月,用开源程序WeCenter搭建了一个社交问答网站. 为了方便用户注册,开通了QQ登录功能. 今天,突然发现QQ互联返回一直出现错误.     度娘了很久,发现大家都遇到这个问题了.Disc ...

  10. 【p091】多项式输出

    一元 n 次多项式可用如下的表达式表示: 其中,aixi 称为i次项,ai称为i次项的系数.给出一个一元多项式各项的次数和系数,请按照如下规定的格式要求输出该多项式: 多项式中自变量为x,从左到右按照 ...