androidpn+tomcat推送消息源码流程分析

下载整合了tomcat的androidpn源码
在myeclipse中用tomcat启动androidpn server项目,然后在eclipse中启动androidpnclient项目。

在客户端中,我们在AndroidManifest.xml文件中找到程序入口,即如下的 DemoAppActivity类
   
   
在此类中主要代码如下
  ServiceManager serviceManager = newServiceManager(this);
  serviceManager.setNotificationIcon(R.drawable.notification);
  serviceManager.startService();
一路跟进,NotificationService中有个XmppManager类的调用(xmppManager.connect();),而XmppManager类就是客户端比较重要的类,有这几个方法
public void connect() {
        Log.d(LOGTAG, "connect()...");
        submitLoginTask();
    }

private void submitConnectTask() {
        Log.d(LOGTAG, "submitConnectTask()...");
        addTask(new ConnectTask());
    }

    private voidsubmitRegisterTask() {
        Log.d(LOGTAG, "submitRegisterTask()...");
        submitConnectTask();
        addTask(new RegisterTask());
    }

    private voidsubmitLoginTask() {
        Log.d(LOGTAG, "submitLoginTask()...");
        submitRegisterTask();
        addTask(new LoginTask());
    }

addTask方法中有一个线程队列,依次添加连接,注册和登陆任务。用runTask方法执行这些任务
在XmppManager类中有三个内部类,即连接(ConnectTask),注册(RegisterTask),登陆(LoginTask)三个线程类。
连接类负责与服务端的连接,这个可以不用了解
注册类中,即用UUID生成唯一的username和password,然后把它们保存到SharedPreferences中
final String newUsername = newRandomUUID();
final String newPassword = newRandomUUID();
.....
  Editor editor = sharedPrefs.edit();
  editor.putString(Constants.XMPP_USERNAME,  newUsername);
  editor.putString(Constants.XMPP_PASSWORD,  newPassword);
  editor.commit();
而在登陆类中,首先进行连接登陆,把客户端的信息更新到服务端,即
xmppManager.getConnection().login(
                  xmppManager.getUsername(),
                  xmppManager.getPassword(),XMPP_RESOURCE_NAME);
这个操作可能执行多次,直到真正更新到服务器。
执行连接登陆时,服务端就会收到信息。

在服务端,接受消息的类是router包(org.androidpn.server.xmpp.router)下的PacketRouter类,在这里分析消息的类型是什么类型,然后在调用具体的Router,如响应登陆的IQRouter。
如果是登陆(即通过唯一的客户端标识获取的session就是为null的),那么就要对这个包进行处理。处理消息包的操作是在org.androidpn.server.xmpp.handler包下进行的。把消息包处理完后就在维护连接的org.androidpn.server.xmpp.net包下的Connection类中传递消息包到客户端
XMLWriter xmlSerializer = new XMLWriter(newIoBufferWriter(
            buffer,(CharsetEncoder) encoder.get()),
            newOutputFormat());
xmlSerializer.write(packet.getElement());
xmlSerializer.flush();
buffer.flip();
ioSession.write(buffer);

如果登陆失败,就获取这个异常,重新进行登陆连接直到登陆成功。


注册登录的流程就如下所述,下面再讲一下,在服务端怎么发送消息到客户端,客户端怎么发消息到服务端,客户端怎么接收来自服务端的消息(服务端接收来自客户端的消息在如下登陆时已经讲了)

在服务端的推送消息的页面中(form.jsp),是通过notification.do?action=send来跳转后台的,那么这个后台是哪个类呢,在web.xml中,我们可以看到,拦截器都是spring的类,即这些都通过spring来托管了,那么我们再打开dispatcher-servlet.xml的spring的配置文件,可以看到
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
/index.do=filenameController
/user.do=userController
/session.do=sessionController
/notification.do=notificationController

notification.do跳转的页面就是 notificationController即 org.androidpn.server.console.controller.NotificationController这个类
class="org.androidpn.server.console.controller.NotificationController">

打开 NotificationController类发现它是调用了NotificationManager
  if (broadcast.equalsIgnoreCase("Y")) {
            notificationManager.sendBroadcast(apiKey, title, message,uri);
        } else {
            notificationManager.sendNotifcationToUser(apiKey, username,title,
                    message, uri);
    }

一路跟进,可以发现最终发送消息的类还是Connection的deliver方法。而中间的过程就是解析和生成消息的操作

那么客户端怎么接受消息呢,这个类应该是一个监听器,从类名和在客户端一路跟进的过程中,我们大概可以知道是NotificationPacketListen er类,在这个类中获取各个节点的值,然后在客户端上发送一个通知

那么客户端发送消息的类又是在哪个类中呢,我们可以参考服务端的发送消息的类是在哪里,没错,是在Connection类中,那么我们在客户端的连接类中寻找一下是否有发送消息的类。果然,在org.jivesoftware.smack包下的XMPPConection这个类中有个发送消息的方法sendPacket。我们可以通过xmppManager.getConnection()来获取连接。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值