源代码下载

转载请注明出处,谢谢!

最终版已上传。优化下拉刷新、增加来消息声音提示、主界面改成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. Docker使用Dockerfile创建Centos(tomcat+jdk)镜像

    原文链接:https://blog.csdn.net/qq_37936542/article/details/80824389 Docker构建镜像的方法主要有两种:    (1)使用docker c ...

  2. [D3] Make D3 v4 Charts Responsive with the viewBox attribute

    Making SVGs responsive is unfortunately not as simple as adding some media queries. This lesson intr ...

  3. TTS-零基础入门之语音模板化

    上篇介绍了TTS的一个简单样例http://blog.csdn.net/u010176014/article/details/47326413 本篇咱们进一步聊聊 语音怎样读模板. 比方 公交车上的模 ...

  4. POS 60域用法

    版权声明:本文为博主原创文章,未经博主允许不得转载. 自定义域(Reserved Private) 1.变量属性 N...17(LLLVAR),3个字节的长度值+最大17个字节的数字字符域. 压缩时用 ...

  5. [AngularFire 2 ] Hello World - How To Write your First Query using AngularFire 2 List Observables ?

    In this lesson we are going to use AngularFire 2 for the first time. We are going to configure the A ...

  6. [TypeStyle] Use fallback values in TypeStyle for better browser support

    You can increase the browser support of your CSS using fallback values and vendor prefixes. This les ...

  7. 【2006】求N!的精确值

    Time Limit: 3 second Memory Limit: 2 MB 对于阶乘函数,即使自变量较小,其函数值也会相当大.例如: 10!=3628800 25!=155112100433309 ...

  8. 学习金字塔 分类: T_TALENT 2014-05-21 09:25 331人阅读 评论(0) 收藏

    学习金字塔是美国缅因州的国家训练实验室研究成果,它用数字形式形象显示了:采用不同的学习方式,学习者在两周以后还能记住内容(平均学习保持率)的多少.它是一种现代学习方式的理论.最早它是由美国学者.著名的 ...

  9. 《大型网站技术架构》1:概述 分类: C_OHTERS 2014-05-07 20:40 664人阅读 评论(0) 收藏

    参考自<大型网站技术架构>第1~3章 1.大型网站架构演化发展历程 (1)初始阶段的网站架构:一台服务器分别作为应用.数据.文件服务器 (2)应用服务和数据服务分离:三台服务器分别承担上述 ...

  10. 使用SQLiteHelper创建数据库并插入数据 分类: H1_ANDROID 2013-11-05 22:44 1398人阅读 评论(0) 收藏

    参考<疯狂android讲义>8.4节P424 1.获取SQLiteDatabase实例有2种方法,一是直接new SQLiteDatabase(),另一种使用SQLiteHelper.一 ...