AndroidPN的学习研究(三)源码流程分析

在客户端中,我们在AndroidManifest.xml文件中找到程序入口,即如下的DemoAppActivity类

在此类中主要代码如下

 ServiceManager serviceManager = new ServiceManager(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 void submitRegisterTask() {

    Log.d(LOGTAG, "submitRegisterTask()...");

    submitConnectTask();

    addTask(new RegisterTask());

  }


  private void submitLoginTask() {

    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(new IoBufferWriter(

      buffer, (CharsetEncoder) encoder.get()),

      new OutputFormat());

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方法。而中间的过程就是解析和生成消息的操作


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


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


你可能感兴趣的:(服务器,客户端,androidpn流程)