版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/qq_29542611/article/details/87736734
前言
直接使用gloox库源码中examples下面的示例,采用开源的openfire搭建的xmpp的服务器,是可以直接进行连接、注册和消息推送。 使用AndroidPN作为xmpp服务器可以可以直接使用 gloox的示例进行注册,但是连接 和 消息推送不行。连接的问题咋们就不说了,咋们直接说 消息推送的问题。
因为AndroidPN作为服务器 给客户端推送的消息是扩展了协议,所以直接使用示例代码是不行。笔者也是看官方文档查看 gloox源代码,将这个问题调通了。其实就是Protocol Extensions 协议扩展问题,如果你仔细去看stanzaextension.h也能解决。自己在网上没有找到一个完整的示例,所以在这里本着奉献自我的精神,写一个使用 gloox 进行协议扩展的案例。
下面是AndroidPN服务器给的消息推送报文结构
<iq type='set' id='193-0' to='[email protected]/gloox'>
<notification xmlns='androidpn:iq:notification'>
<id>65d24038</id><apiKey>1234567890</apiKey>
<title>Dokdo Island</title>
<message>Dokdo is a Korean island, the far east of the Korean territory. No doubt! No question! Don't mention it any more!</message>
<uri>www.baidu.com</uri>
</notification>
</iq>
我们需要的title、message和uri,我们通过协议扩展来获取到我们想要的信息。
这里额外说下gloox使用的是1.0.22版本,AndroidPN服务器使用的是androidpn-server-0.5.0-bin 。
代码
定义我们自己的扩展类
myextension.h
#pragma once
#include "stanzaextension.h"
#include <string>
using namespace gloox;
class MyExtension :public StanzaExtension
{
public:
MyExtension();
MyExtension( const Tag* tag );
//MyExtension( const MyExtension& one );
virtual ~MyExtension();
/**
* This function returns the embedded Stanza, if any.
* You only have to reimplement it if your protocol flow contains embedded Stanzas.
*
* @return The embedded Stanza. May be 0.
*/
virtual Stanza* embeddedStanza() const { return 0; }
/**
* This function returns the embedded Tag that the embedded Stanza is based on, if any.
* You only have to reimplement it if your protocol flow contains embedded Stanzas.
*
* @return The embedded Tag. May be 0.
*/
virtual Tag* embeddedTag() const { return 0; }
/**
* Returns an XPath expression that describes a path to child elements of a
* stanza that an extension handles.
*
* @return The extension's filter string.
*/
virtual const std::string& filterString() const;
/**
* Returns a new Instance of the derived type. Usually, for a derived class FooExtension,
* the implementation of this function looks like:
* @code
* StanzaExtension* FooExtension::newInstance( const Tag* tag ) const
* {
* return new FooExtension( tag );
* }
* @endcode
* @return The derived extension's new instance.
*/
virtual StanzaExtension* newInstance( const Tag* tag ) const;
/**
* Returns a Tag representation of the extension.
* @return A Tag representation of the extension.
*/
virtual Tag* tag() const;
/**
* Returns an identical copy of the current StanzaExtension.
* @return An identical copy of the current StanzaExtension.
*/
virtual StanzaExtension* clone() const;
std::string getTitle();
std::string getMsg();
std::string getUrl();
private:
std::string m_title;
std::string m_msg;
std::string m_url;
};
myextension.cpp
#include "myextension.h"
#include "tag.h"
#include "gloox.h"
#include <stdlib.h>
using namespace gloox;
#define OPEN_TEST 0
MyExtension::MyExtension():StanzaExtension(ExtUser)
{
#if OPEN_TEST
printf("MyExtension() \n");
#endif
}
MyExtension::MyExtension( const Tag* tag ):StanzaExtension(ExtUser)
{
/*
<notification xmlns='androidpn:iq:notification'>
<id>65d24038</id>
<apiKey>1234567890</apiKey>
<title>Dokdo Island</title>
<message>Dokdo is a Korean island, the far east of the Korean territory.</message>
<url>www.baidu.com</url>
</notification>
*/
#if OPEN_TEST
printf("MyExtension( const Tag* tag ) enter \n");
#endif
Tag* titleTag = tag->findChild("title");
if( NULL != titleTag )
{
m_title = titleTag->cdata();
}
Tag* msgTag = tag->findChild("message");
if( NULL != titleTag )
{
m_msg = msgTag->cdata();
}
Tag* urlTag = tag->findChild("uri");
if( NULL != urlTag )
{
m_url = urlTag->cdata();
}
}
MyExtension::~MyExtension()
{
#if OPEN_TEST
printf("~MyExtension() \n");
#endif
}
// 返回自定义协议的xmlns进行过滤匹配
const std::string& MyExtension::filterString() const
{
#if OPEN_TEST
printf("filterString() enter \n");
#endif
static const std::string filter = "/iq/notification[\@xmlns='androidpn:iq:notification']";
return filter;
}
StanzaExtension* MyExtension::newInstance( const Tag* tag ) const
{
#if OPEN_TEST
printf("newInstance( const Tag* tag ) enter \n");
#endif
StanzaExtension* ret = new MyExtension( tag );
return ret;
}
Tag* MyExtension::tag() const
{
/*
<notification xmlns='androidpn:iq:notification'>
<id>65d24038</id>
<apiKey>1234567890</apiKey>
<title>Dokdo Island</title>
<message>Dokdo is a Korean island, the far east of the Korean territory.</message>
<url>www.baidu.com</url>
</notification>
*/
#if OPEN_TEST
printf("MyExtension::tag() enter \n");
#endif
Tag* root = new Tag("notification");
root->addAttribute("xmlns","androidpn:iq:notification");
Tag* titleTag = new Tag("title");
Tag* msgTag = new Tag("message");
Tag* urlTag = new Tag("uri");
titleTag->setCData(m_title);
msgTag->setCData(m_msg);
urlTag->setCData(m_url);
root->addChild(titleTag);
root->addChild(msgTag);
root->addChild(urlTag);
return root;
}
StanzaExtension* MyExtension::clone() const
{
StanzaExtension* ret = new MyExtension(*this);
return ret;
}
std::string MyExtension::getTitle()
{
return m_title;
}
std::string MyExtension::getMsg()
{
return m_msg;
}
std::string MyExtension::getUrl()
{
return m_url;
}
在使用的地方进行注册,并且继承 IqHandler并重写对应的纯虚函数。
MyExtension* ex = new MyExtension(); // 自定义xmpp协议扩展
j->registerIqHandler(this,ExtUser);
j->registerStanzaExtension(ex);
重写
virtual bool handleIq( const IQ& iq )
{
MyExtension* ex = (MyExtension*)iq.findExtension(ExtUser);
if( NULL == ex )
{
return false;
}
std::cout <<"title:" << ex->getTitle() << std::endl;
std::cout << "msg:" << ex->getMsg() << std::endl;
std::cout << "url:" << ex->getUrl() << std::endl;
return true;
}
virtual void handleIqID( const IQ& iq, int context )
{
return;
}