关于XMPP 本地环境搭建、登录、好友列表,好友状态、发送接收多媒体消息、增删好友、群聊等功能点,大家可以跟我一起来学习,最后章节会将整个完整Demo放到我的github。
因为很早就开始用swift来做项目,所以本文以swift进行示例。Xcode版本为7.3.1。
一、了解XMPP常用对象
XMPPStream:xmpp基础服务类
XMPPRoster:好友列表类
XMPPRosterCoreDataStorage:好友列表(用户账号)在core data中的操作类
XMPPvCardCoreDataStorage:好友名片(昵称,签名,性别,年龄等信息)在core data中的操作类
XMPPvCardTemp:好友名片实体类,从数据库里取出来的都是它
xmppvCardAvatarModule:好友头像
XMPPReconnect:如果失去链接,自动重连
XMPPRoom:提供多用户聊天支持
XMPPPubSub:发布订阅
二、引入头文件
根据基于XMPP实现即时通讯(一、环境搭建)的集成方式,cocapods引入的XMPP为OC版本,所以要在工程的桥接文件中引入基础服务类:#import “XMPP.h"
三、登陆
登陆之前我们得先在openfire上建个用户(也可以直接用管理员帐号),然后再进行以下步骤:初始化核心类、建立socket链接、链接成功后通过密码进行身份校验、更新上线状态。
1. 新建用户
用管理员帐号登录openfire,在用户/组中新建用户。(实际业务流程中,此建立过程也是后台服务器实现,只是需要客户端传递相关注册信息)
2. 初始化基础类
可以新建一个XMPPManager类,以下方法均在此类实现。(用来管理所有XMPP核心业务服务):1
2
3
4
5func xmppInit()
{
_xmppStream = XMPPStream()
_xmppStream?.addDelegate(self, delegateQueue: dispatch_get_main_queue())
}
3. 建立socket链接
3.1 先在文件头申明常量:
因为是在个人MAC搭建Openfire服务器调试,所以此hostname为个人MAC共享访问地址,在mac的系统偏好设置->共享里可以查看到完整地址,在实际调试过程中,真机登录必须用此host,但聊天可能为localhost,也可能为此host,模拟器也存在同样的情况,当消息发送不成功时,可以尝试修改这些host1
let vHostName = "JamieiMac.local"
3.2 建立socket链接:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32func xmppConnect(userId: String, password: String) {
let userName = "\(userId)@\(vHostName)"
let jid = XMPPJID.jidWithString(userName)
_xmppStream.myJID = jid
_xmppStream.hostName = vHostName
_pwd = password
do {
try _xmppStream.connectWithTimeout(10)
} catch let error {
DPrintln("发送链接请求失败 \(error),请检查网络或服务器配置")
}
}
// MARK: -------------------------------- 链接回调 -------------------------------
func xmppStream(sender: XMPPStream!, socketDidConnect socket: GCDAsyncSocket!) {
DPrintln("建立socket链接")
}
func xmppStreamDidConnect(sender: XMPPStream!) {
DPrintln("链接成功")
//进行身份校验
self.authenticateUser()
}
func xmppStreamConnectDidTimeout(sender: XMPPStream!){
DPrintln("链接超时")
Tools.shared.showAlertViewAndDismissDefault(nil, message: "链接超时,请重试")
}
3.3 校验身份1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33func authenticateUser() {
if _xmppStream.isAuthenticated(){
return
}
do {
try _xmppStream.authenticateWithPassword(_pwd)
} catch let error {
Tools.dissmissLoadingInWindow()
DPrintln("发送验证请求失败 \(error)")
_xmppStream.disconnect()
}
}
// MARK: -------------------------------- 身份验证回调 -------------------------------
func xmppStreamDidAuthenticate(sender: XMPPStream!){
DPrintln("身份验证成功")
// Tools.shared.showAlertViewAndDismissDefault(nil, message: "登录成功!")
self.onLine()
Tools.dissmissLoadingInWindow()
NSNotificationCenter.defaultCenter().postNotificationName("loginSuccess", object: nil, userInfo: nil)
}
func xmppStream(sender: XMPPStream!, didNotAuthenticate error: DDXMLElement!) {
DPrintln("身份验证失败")
Tools.dissmissLoadingInWindow()
NSNotificationCenter.defaultCenter().postNotificationName("loginError", object: nil, userInfo: nil)
_xmppStream.disconnect()
}
四、上下线
用户默认状态有:
1 | available 上线 |
默认身份验证成功后,用户还是灰色(下线状态)的,因此通常登陆成功后直接发送上线状态。上线成功后在openfire的用户摘要中可看到在线状态变绿。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17func onLine(){
DPrintln("发送上线状态")
let presence = XMPPPresence(type: "available")
_xmppStream.sendElement(presence)
}
//用户主动下线(同时断开链接)
func outLine(){
DPrintln("发送下线状态")
let presence = XMPPPresence(type: "unavailable")
_xmppStream.sendElement(presence)
//断开链接
_xmppStream.disconnect()
}
五、接收信息
当接收到< message /> 标签时,XMPP会回调didReceiveMessage的方法。根据 XMPP 协议,消息体的内容存储在标签 < body /> 内
1
2
3
4
5
6
7
8
9
10
11
12
13func xmppStream(sender: XMPPStream!, didReceiveMessage message: XMPPMessage!) {
DPrintln("收到消息 \(message)")
//stringValue默认解析body内字符
let messageString = message.stringValue()
if !NSString.isNilOrEmpty(messageString){
let messageBody = message.elementForName("body").stringValue
let fromeUser = (message.attributeForName("from")).stringValue
UIView.showAlertView(fromeUser(), andMessage: messageBody())
} else{
DPrintln("收到其它类型消息/非正常消息")
}
}测试接收消息: 登录及上线成功后,在openfire控制界面中,打开“会话”-》“工具”,即可向所有用户发送消息,赶紧验证下你的代码吧!
作者 @代码书生
2016 年 06月 16日