图文无关一起娱乐:

这一篇我们开始写Android端的Smack版主类,后面Android的IM功能都是通过这个帮助类实现的

引用类库:

因为我用的是IDE是Android Studio,所以我通过gradle进行jar包管理了,非常方便,jar包如下:

  1. compile 'org.igniterealtime.smack:smack-core:4.1.4'
  2. compile 'org.igniterealtime.smack:smack-tcp:4.1.4'
  3. compile 'org.igniterealtime.smack:smack-extensions:4.1.4'
  4. compile 'org.igniterealtime.smack:smack-android:4.1.4'
  5. compile 'org.igniterealtime.smack:smack-android-extensions:4.1.4'
  6. compile 'org.igniterealtime.smack:smack-experimental:4.1.4'
  7. compile 'org.igniterealtime.smack:smack-bosh:4.1.4'
  8. compile 'org.igniterealtime.smack:smack-resolver-dnsjava:4.1.4'
  9. compile 'org.igniterealtime.smack:smack-legacy:4.1.4'

加上这些jar包后我们就可以使用Smack库了,大家很容易看到,我这个是4.1.4的包。它的最新包是4.2.0不过是alpha版本,所以我就用这个4.1.4最新正式包了。它和它的一些老版本差别还是比较大的。所以如果你是第一次使用还是和我一样,防止出现一些问题。更新gradle后就可以使用了。

写Smack帮助类:

我这里先定义一个ISmack接口,这种命名方式是我从C#那边带过来的,别纠结。本人很久之前是.NET平台的,.NET平台还是有很多东西是非常不错的。这个接口就是一些约束协议。然后再写了一个Smack 类,它继承并且实现了ISmack接口。

ISmack接口代码如下:

  1. /**
  2. *
  3. * @备注:samck操作接口协议
  4. * @作者:高露
  5. * @时间:2015-10-24
  6. * @QQ:408365330
  7. *
  8. */
  9. public interface ISmack {
  10.  
  11. /**
  12. * 登录
  13. * @param name 账号
  14. * @param pwd 密码
  15. * @return
  16. */
  17. public boolean login(String name,String pwd);
  18.  
  19. /**
  20. * 消息发送
  21. * @param from 谁发送
  22. * @param to 发送给谁
  23. * @param content 发送内容
  24. */
  25. public void sendMessage(String from,String to,String content) throws SmackException.NotConnectedException;
  26.  
  27. /**
  28. *添加好友
  29. * @param user 用户jid
  30. * @param name 添加好友备注名称
  31. * @param groups 好友添加到的分组,可以过个组
  32. */
  33. public void addRosterItem(String user,String name,String[] groups) throws Exception;
  34.  
  35. /**
  36. * 删除好友
  37. * @param user 好友jid
  38. */
  39. public void removeRoster(String user);
  40.  
  41. }

可以通过这份协议知道我这里定义了 登录,消息发送,添加好友,删除好友 这些方法,后面还是会添加的,每个方法备注还是比较详细的,看看就知道是什么意思了。

然后我们再看看和分析Smack代码

Smack代码分析:

静态构造函数:

首先定义了一个java静态构造函数

  1. static {
  2. if (connection == null) {
  3. XMPPTCPConnectionConfiguration configuration = XMPPTCPConnectionConfiguration.builder()
  4. .setConnectTimeout(Constant.IM_TIMEOUT)
  5. .setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
  6. .setHost(Constant.IM_SERVER)//ip
  7. .setPort(Constant.IM_SERVER_PORT)//端口号设置一般式5222
  8. .setServiceName(Constant.IM_SERVER_DOMAIN)//服务器名称
  9. .setDebuggerEnabled(true)//设置开启调试
  10. .setSendPresence(true)//设置是否发送Presece信息
  11. .build();
  12. connection = new XMPPTCPConnection(configuration);
  13.  
  14. connection.addConnectionListener(new ConnectionListener() {
  15. @Override
  16. public void connected(XMPPConnection connection) {
  17. LogHelper.i(TAG, "connected");
  18. }
  19.  
  20. @Override
  21. public void authenticated(XMPPConnection connection, boolean resumed) {
  22. LogHelper.i(TAG, "authenticated");
  23. }
  24.  
  25. @Override
  26. public void connectionClosed() {
  27. LogHelper.i(TAG, "connectionClosed");
  28. }
  29.  
  30. @Override
  31. public void connectionClosedOnError(Exception e) {
  32. LogHelper.i(TAG, "connectionClosedOnError");
  33. }
  34.  
  35. @Override
  36. public void reconnectionSuccessful() {
  37. LogHelper.i(TAG, "reconnectionSuccessful");
  38. }
  39.  
  40. @Override
  41. public void reconnectingIn(int seconds) {
  42. LogHelper.i(TAG, "reconnectingIn");
  43. }
  44.  
  45. @Override
  46. public void reconnectionFailed(Exception e) {
  47. LogHelper.i(TAG, "reconnectionFailed");
  48. }
  49. });
  50.  
  51. ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(connection);
  52. reconnectionManager.setFixedDelay(Constant.IM_RE_CONNET_TIME);//重联间隔
  53. reconnectionManager.enableAutomaticReconnection();//开启重联机制
  54. try {
  55. connection.connect();
  56. } catch (SmackException | IOException | XMPPException ex) {
  57. ex.printStackTrace();
  58. }
  59.  
  60. }
  61. }
  1. XMPPTCPConnectionConfiguration类是连接的配置,连接相关配置都是通过这个类传递给XMPPTCPConnection对象的。配置信息的设置请看上面的代码注释,connection.addConnectionListener是给连接添加监听,这里面我们可以监听连接的各种状态。然后做相应的处理。
    ReconnectionManager这个类是重联管理设置连接断开后是否允许重新连接。这样实现自动重联
    最后通过connection.connect()连接XMPP服务器
    登录:
  1. /**
  2. * 登录
  3. * @param name 账号
  4. * @param pwd 密码
  5. * @return
  6. */
  7. @Override
  8. public boolean login(String name, String pwd) {
  9. try {
  10. if (connection.isConnected()) {
  11. connection.login(name, pwd);
  12.  
  13. } else {
  14. connection.connect();
  15. connection.login(name, pwd);
  16. }
  17.  
  18. } catch (XMPPException | SmackException | IOException ex) {
  19. ex.printStackTrace();
  20. }
  21.  
  22. /**
  23. * 消息监听
  24. */
  25. registerMessageListener();
  26. /**
  27. * 通讯录监听
  28. */
  29. registerRosterListener();
  30. return false;
  31. }

通过用户名和密码进行登录。登录之前判断是否连接了XMPP服务器。登录后添加消息监听处理消息,通讯录监听处理通讯录。下面再看看这两个监听方法

通讯录监听:

  1. /**
  2. * 通讯录监听
  3. */
  4. private void registerRosterListener() {
  5. Roster roster = Roster.getInstanceFor(connection);
  6. roster.setSubscriptionMode(Roster.SubscriptionMode.manual);//设置添加好友,需要对方确认
  7. roster.addRosterListener(new RosterListener() {
  8. @Override
  9. public void entriesAdded(Collection<String> collection) {
  10. LogHelper.i(TAG, "通讯录用户添加");
  11. }
  12.  
  13. @Override
  14. public void entriesUpdated(Collection<String> collection) {
  15. LogHelper.i(TAG, "通讯录用户变更");
  16. }
  17.  
  18. @Override
  19. public void entriesDeleted(Collection<String> collection) {
  20. LogHelper.i(TAG, "通讯录用户删除");
  21. }
  22.  
  23. @Override
  24. public void presenceChanged(Presence presence) {
  25. LogHelper.i(TAG, "通讯录用户presence变化");
  26. }
  27. });
  28. }
  1. Roster类管理这通讯录。给通讯录添加了监听这样可以处理通讯里,请看上面的代码。这里重点讲解roster.setSubscriptionMode(Roster.SubscriptionMode.manual);这个设置通讯里添加好友的模式。这里设置了添加好友需要确认,而不是直接成为好友,一般都是这样,但是这里也支持直接成为好友。我们通过源码来看看SubscriptionMode这个枚举。
  1. /**
  2. * 好友请求订阅的模式枚举.
  3. */
  4. public enum SubscriptionMode {
  5.  
  6. /**
  7. * 自动接收所有好友请求. This is
  8. * 这是默认的模式,适合简单的客户端. 更复杂的客户端希望手动处理好友添加请求.
  9. */
  10. accept_all,
  11.  
  12. /**
  13. * 自动拒绝所有请求
  14. */
  15. reject_all,
  16.  
  17. /**
  18. * 好友请求被忽略,意味着必须手动注册和处理presence监听,然后处理类型是
  19. * Presence.Type.SUBSCRIBE类型或者是Presence.Type.UNSUBSCRIBE类型的 presence包
  20. */
  21. manual
  22. }

以上是我通过源码中的英文转译的,鄙人英文就这水平见谅,见谅。这里说的presence包不懂的话看看第一篇XMPP协议简析,这样就懂了。我的原则是任何东西先懂原理(先修炼好《易筋经》然后再学招式,否则累也记不住,不懂硬记很累,有些学编程,语言没学好然后直接上平台性的东西,发现容易出问题,同样一个道理)。

消息监听:

  1. /**
  2. * 各种消息包监听
  3. */
  4. private void registerMessageListener() {
  5. connection.addSyncStanzaListener(new StanzaListener() {
  6. @Override
  7. public void processPacket(Stanza stanza) throws SmackException.NotConnectedException {
  8. if (stanza instanceof Message) {//表示接收到是消息包
  9. Message message = (Message) stanza;
  10. if (message.getType() == Message.Type.chat) {//表示单聊
  11.  
  12. }
  13. if (message.getType() == Message.Type.groupchat) {//表示群聊
  14.  
  15. }
  16. if (message.getType() == Message.Type.error) {//表示错误信息
  17.  
  18. }
  19. }
  20.  
  21. if (stanza instanceof Presence) {//表示接收到的是Presence包
  22.  
  23. }
  24.  
  25. if (stanza instanceof IQ) {//表示接收到的是IQ包
  26.  
  27. }
  28. }
  29. }, new StanzaFilter() {
  30. @Override
  31. public boolean accept(Stanza stanza) {
  32. return true;
  33. }
  34. });

虽然还有其它监听消息的方法,但是我选择这种了,因为这种可以监听所有各种消息包,看上面注释能理解。如果不懂这些包神马意思还是推荐你看前面第一篇XMPP协议简析。那么久知道神马是IQ,神马是Message,什么是Presence包了

  1. new StanzaFilter() {
  2. @Override
  3. public boolean accept(Stanza stanza) {
  4. return true;
  5. }
  6. }

这个是过滤包,我这里返回ture就是不过滤直接接受所有XMPP包。你还可以过滤特定的包比如IQ包  StanzaFilter filter=new StanzaTypeFilter(IQ.class) ,然后把这个作为 addSyncStanzaListener方法的第二个参数这样就只能接受IQ消息了。

消息发送

  1. /**
  2. * 消息发送
  3. *
  4. * @param from 谁发送
  5. * @param to 发送给谁
  6. * @param content 发送内容
  7. */
  8. @Override
  9. public void sendMessage(String from, String to, String content) throws SmackException.NotConnectedException {
  10.  
  11. Message msg = new Message(to, content);
  12. msg.setFrom(from);
  13. connection.sendStanza(msg);
  14.  
  15. // ChatManager chatmanager = ChatManager.getInstanceFor(connection);
  16. // Chat newChat = chatmanager.createChat(to, new ChatMessageListener() {
  17. // @Override
  18. // public void processMessage(Chat chat, Message message) {
  19. // LogHelper.i(TAG, "接收到消息:" + message);
  20. //
  21. // }
  22. // });
  23. // newChat.sendMessage(content);
  24.  
  25. }

我这里可以看到有两种方式,一种直接原始的发送Message包,另一种就是被我注释的代码段,通过ChatManager来发送消息

添加好友:

  1. /**
  2. * 添加好友
  3. * @param user 用户jid
  4. * @param name 添加好友备注名称
  5. * @param groups 好友添加到的分组,可以过个组
  6. * @throws Exception
  7. */
  8. @Override
  9. public void addRosterItem(String user, String name, String[] groups) throws Exception{
  10. Roster roster=Roster.getInstanceFor(connection);
  11. roster.createEntry(user,name,null);
  12. }

这里没神马好讲的,因为上面设置了 roster.setSubscriptionMode(Roster.SubscriptionMode.manual);//设置添加好友,需要对方确认  这种模式,添加好友需要对方确认

最后:

今天就此结束,虽然只有这些方法,如果你结合前面第一篇XMPP协议简介弄懂原理,我们就共同进步了:)。希望我们一起每天进步一点。

合肥程序员群:49313181。    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入)
Q  Q:408365330     E-Mail:egojit@qq.com
 

即时聊天IM之四 Android客户端IM帮助类编写的更多相关文章

  1. android 客户端支付宝 php服务器端编写

    生成私钥 输入“genrsa -out rsa_private_key.pem 1024”命令,回车后,在当前 bin 文件目 录中会新增一个 rsa_private_key.pem 文件,其文件为原 ...

  2. [PHP]AES加密----PHP服务端和Android客户端

    本文采取128位AES-CBC模式加密和解密 1.首先对服务端安装mcrypt: sudo apt-get install php5-mcrypt php5-dev sudo php5enmod mc ...

  3. 即时聊天IM之三 XMPP协议客户端库的和Android端框架概述

    合肥程序员群:49313181.    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入) Q  Q:408365330     E-Mail:egojit@qq.com smack ...

  4. 【原创】轻量级即时通讯技术MobileIMSDK:Android客户端开发指南

    申明:MobileIMSDK 目前为个人维护的原创开源工程,现陆续整理了一些资料,希望对需要的人有用.如需与作者交流,见文章底签名处,互相学习. MobileIMSDK开源工程的代码托管地址请进入 G ...

  5. 看完这篇包你进大厂,实战即时聊天,一文说明白:聊天服务器+聊天客户端+Web管理控制台。

    一.前言 说实话,写这个玩意儿是我上周刚刚产生的想法,本想写完后把代码挂上来赚点积分也不错.写完后发现这东西值得写一篇文章,授人予鱼不如授人以渔嘛(这句话是这么说的吧),顺便赚点应届学生MM的膜拜那就 ...

  6. Android客户端消息推送原理简介

    首先简单介绍一下Android消息推送的主要三种方式,如果你已经看过类似的文章,请直接忽略三种介绍.    1.使用SMS服务,即服务器端发送短信,然后手机客户端监听短信的广播,然后对数据进行一定的处 ...

  7. 即时聊天 / XMPP

    MQTT是第二个即时聊天协议(了解) 5.即时通讯 即时通讯网上有第三方的解决方案,比如环信,融云等.我们是自己搭的xmpp服务器,服务器使用的tigase,之前写过相关的博客,自己去年也做了对应的w ...

  8. 7.xmpp版即时聊天

    即时聊天的解决方案 socket: xmpp:xmpp+openfire+asmack 环信 常见协议 比较安全,tcp上还加了俩层 简单聊一下socket socket:套接字,连接需要ip和端口, ...

  9. Mina框架的学习笔记——Android客户端的实现

    Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络 ...

随机推荐

  1. Linq对XML的简单操作

    前两章介绍了关于Linq创建.解析SOAP格式的XML,在实际运用中,可能会对xml进行一些其它的操作,比如基础的增删该查,而操作对象首先需要获取对象,针对于DOM操作来说,Linq确实方便了不少,如 ...

  2. PL/SQL Developer连接Oracle 11g在Win8 64位系统下乱码

    PL/SQL Developer在64位系统上连接Oracle,需要安装32位Oracle client客户端,使用后,发现操作数据库出现乱码的情况.经过查找资料,解决此问题,方法如下: 需要在系统的 ...

  3. PHP 微信分享

    share.php <?php //公众号设置一下 JS接口安全域名,不要http,www的一级域名,比如http://www.baidu.com域名下的某个路径要分享,js安全域名中只需填上 ...

  4. oracle wrapped 代码解密工具 unwraper

    Oracle中的Wrap 功能是为了不让别人看到函数/存储过程的SQL源码的明文, 作为技术宅,有的时候想看源码但是看不到的那种心情是可以理解的, 发一个简单易用的 Oracle wrapped 解码 ...

  5. MVC简单分层思想(连接数据库)

    图片内容是所有的包名,文件名. 1.创建(M)模型 package oa.bean; public class User { private String userName; private Stri ...

  6. 微信支付:curl出错,错误码:60

    如下是运行微信支付测试代码时出错代码: Fatal error: Uncaught exception ‘WxPayException‘ with message ‘curl出错,错误码:60‘ in ...

  7. iOS中如何隐藏启动图片的状态栏

    只隐藏启动图片顶部的状态栏,而不影响程序运行起来控制器的状态栏显示?在info.plist文件中添加一个Statis bar is...... 默认是NO改为YES即可

  8. python学习之函数

    1.函数名可以被赋值 比如: def aaa(): pass b = aaa//将函数名字赋值给b b()//跟aaa()效果一样 2.return 2.1.如果函数不写return的话,会默认返回N ...

  9. Evacuation Plan-POJ2175最小费用消圈算法

    Time Limit: 1000MS Memory Limit: 65536K Special Judge Description The City has a number of municipal ...

  10. python之SQLAlchemy

    ORM介绍 orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的,为 ...