1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > smack+openfire实现Android实时通信(实现大部分基本功能)

smack+openfire实现Android实时通信(实现大部分基本功能)

时间:2023-08-31 01:17:55

相关推荐

smack+openfire实现Android实时通信(实现大部分基本功能)

1. 开发环境

smack-4.3.4openfire-4.6.3开发工具:AndroidStudio

openfire下载及安装:

官网:/projects/openfire/CSDN:/download/JieZhongBa/20015330安装教程:<>

本文项目地址:/JieZhongBa/article/details/118460210

2. 依赖

// UI 可选implementation 'com.github.stfalcon-studio:Chatkit:0.4.1'// Smackimplementation "org.igniterealtime.smack:smack-tcp:4.3.4"// 下面两个二选一,带extensions的包大一点,顾名思义。// implementation "org.igniterealtime.smack:smack-android:4.3.4"implementation "org.igniterealtime.smack:smack-android-extensions:4.3.4"

其中UI是github的一个开源框架,用起来还行,有兴趣的可以试试,就是文档比较少,官方是纯英文的。

官方地址:/stfalcon-studio/ChatKit

教程博客:/JieZhongBa/article/details/118459924

3. 连接服务

Config,供全局使用,注意服务器名称和主机名不要混淆了,其实就是初始化时的域名,避免错误就直接设成一样的就好了。

//Configpublic static final String C_HOST = "IP";//可访问到openfire服务的IP地址public static final int C_PORT = 5222;//端口,默认5222public static final String C_DOMAIN = "up55";//服务器名称public static final String C_SOURCE = "YunShang";//源,自己随便写,也可以不加这个

连接服务器

try {System.out.println("正在连接Chat服务。。。");XMPPTCPConnectionConfiguration configuration = XMPPTCPConnectionConfiguration.builder().setResource(Resourcepart.from(C_SOURCE))//固定源.setHostAddress(InetAddress.getByName(C_HOST))//IP.setPort(C_PORT)//端口.setXmppDomain(C_DOMAIN)//服务器名称.setSendPresence(false)//以离线方式登录,以便获取离线消息.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled).build();connection = new XMPPTCPConnection(configuration);connection.connect();System.out.println("Chat服务连接成功");} catch (Exception e) {System.out.println("Chat服务连接失败" + e.getLocalizedMessage());e.printStackTrace();}

4. 登录

connection.login(user, pass);

5. 登出

connection.sendStanza(new Presence(Presence.Type.unavailable));//设为下线connection.disconnect();//断开连接

6. 注册

其中map里的信息是选填,key对应openfire的用户属性,account和password为必填项。

HashMap<String, String> map = new HashMap<>();map.put("name", "张三");//可选map.put("email", "zs@");//可选AccountManager instance = AccountManager.getInstance(connection);instance.sensitiveOperationOverInsecureConnection(true);instance.createAccount(Localpart.from(account), password, map);//map为可选

7. 注销(慎用)

删除当前用户的所有信息,慎用!

AccountManager.getInstance(connection).deleteAccount();

8. 搜索用户

之前网上找的,注释也比较多,原文不知道在哪了

try {UserSearchManager usm = new UserSearchManager(connection);//本例用的smack:4.3.4版本,getSearchForm方法传的是DomainBareJid类型,而之前的版本是String类型,大家在使用的时候需要特别注意//而转换DomainBareJid的方式如下面的例子所示:JidCreate.domainBareFrom("search." + getConnection().getXMPPServiceDomain())Form searchForm = usm.getSearchForm(JidCreate.domainBareFrom("search." + connection.getXMPPServiceDomain()));if (searchForm == null) {return;}//这里设置了Username为true代码是根据用户名查询用户,search代表查询字段//smack:4.3.4版本是下面的字段,但之前的版本会有些不一样,所以在用的时候最好看下xmpp交互的log,里面有相应的字段值Form answerForm = searchForm.createAnswerForm();answerForm.setAnswer("Username", true);answerForm.setAnswer("Name", true);answerForm.setAnswer("search", "张三");ReportedData data = usm.getSearchResults(answerForm, JidCreate.domainBareFrom("search." + connection.getXMPPServiceDomain()));List<ReportedData.Row> rowList = data.getRows();//此处返回的字段名如下所示,之前的版本可能有所变化,使用的时候需要注意for (ReportedData.Row row : rowList) {String jid = row.getValues("jid").toString();String username = row.getValues("Username").toString();String name = row.getValues("Name").toString();String email = row.getValues("Email").toString();System.out.println(jid + "," + username + "," + name + "," + email);// 若存在,则有返回,UserName一定非空,其他两个若是有设,一定非空}} catch (Exception e) {e.printStackTrace();}

9. 连接状态

主要是供外部调用,获取连接状态。

//是否连接服务器public boolean isConnected() {return connection.isConnected();}//是否登录public boolean isLogin() {return connection.isAuthenticated();}

10. 接收离线消息

try {OfflineMessageManager offlineMessageManager = new OfflineMessageManager(connection);List<Message> messageList = offlineMessageManager.getMessages();System.out.println("离线消息:" + messageList.size()+"条");for (Message message : messageList) {System.out.println(message.getFrom() + ",," + message + ":" + message.getBody());}offlineMessageManager.deleteMessages();//通知服务器删除离线消息,否则下次还在connection.sendStanza(new Presence(Presence.Type.available));//上线} catch (Exception e) {e.printStackTrace();}

11. 发送消息

为了方便其实是用idea写的,Android的话测试比较麻烦,后面会吧我写的Android项目发出来。

简单的从控制台输入。

ChatManager chatManager = ChatManager.getInstanceFor(connection);try {EntityBareJid jid = JidCreate.entityBareFrom("540@up55");//对方的jid(账号+@+服务器名称)Chat chat = chatManager.chatWith(jid);Scanner sc = new Scanner(System.in);if (chat != null) {while (true) {String mes = sc.next();chat.send(mes);if ("exit".equals(mes))break;}}} catch (Exception e) {e.printStackTrace();}

12. 消息收发监听

ChatManager chatManager = ChatManager.getInstanceFor(connection);//消息发送监听chatManager.addOutgoingListener((entityBareJid, message, chat1) -> {System.out.println("发送成功:" + message.getBody());});//接收消息监听chatManager.addIncomingListener((entityBareJid, message, chat) -> {System.out.println(message.getFrom().getLocalpartOrThrow() + ":" + message.getBody());});

13. Android实现的思路

我是用一个service保持和服务器的通信,然后自定义了回调接口,在activity中实现,service监听到消息则调用回调,activity刷新页面,同时service提供了发送消息功能,具体实现当然会比这个复杂点,而且要规范也不能这样写,有兴趣可以去看看我的项目,不过写的比较乱,写完也觉得很多地方写的不太好,比如应该继承AppCompatActivity写一个自己的,方便activity和service的通信和即时通讯功能的管理,另外也不一定要用回调的形式,也可以用广播之类的实现消息传递。

14. 踩坑记录

连局域网的时候不加端口号也行,因为默认5222,后来部署到远程,一直连接超时,用idea测试也没问题(不知道为什么idea不加端口号也行),Android里一直不行,后来加上端口号就好了。。。smack版本变化不少,而且网上教程比较少,很多是老版本的,只能稍微参考,得找相近版本的。openfire的搜索服务有时候会出毛病,把服务器缓存清掉就好了,再不行重启服务器,千万不要在插件里重新启动,会出问题,之后就只能删掉这个插件在重新安装了。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。