前面说过XmppManager(位于AndroidPn Client的org.androidpn.client包内)是主控制器,通过调用其他的提供的某些方法,来实现客户端的连接(Connect)、注册(Register)和登陆(Login)。在模拟AndroidPn Client,实际上就是将该类以及该类所用的对象移植到PC端去。

1.首先先看XmppManager的实例变量(这里只列出我们在模拟Client时,用到的实例变量)

   1: //用来提交线程任务(ConnnectTask,RegisterTask,LoginTask)
   2: private NotificationService.TaskSubmitter taskSubmitter;
   3:  
   4: //服务器的主机名
   5: private String xmppHost;
   6: //服务器的端口号
   7: private int xmppPort;
   8:  
   9: //客户端与服务器的连接
  10: private XMPPConnection connection;
  11:  
  12: //客户端的用户名
  13: private String username;
  14: //密码
  15: private String password;
  16:  
  17: //Xmpp节的监听器,当客户端接受xmpp节时,会调用PacketListener的方法处理收到的xmpp节
  18: private PacketListener notificationPacketListener;
  19:  
  20: //任务列表
  21: private List<Runnable> taskList;
  22:  
  23: //当前是否有任务正在执行
  24: private boolean running = false;
  25:  
  26: //任务返回结果
  27: private Future<?> futureTask;
其中NotificationService.TaskSubmitter的实现代码如下
   1: public class TaskSubmitter {
   2:  
   3:         final NotificationService notificationService;
   4:  
   5:         public TaskSubmitter(NotificationService notificationService) {
   6:             this.notificationService = notificationService;
   7:         }
   8:  
   9:         @SuppressWarnings("unchecked")
  10:         public Future submit(Runnable task) {
  11:             Future result = null;
  12:             if (!notificationService.getExecutorService().isTerminated()
  13:                     && !notificationService.getExecutorService().isShutdown()
  14:                     && task != null) {
  15:                 result = notificationService.getExecutorService().submit(task);
  16:             }
  17:             return result;
  18:         }
  19:  
  20:     }
12行notificationService.getExecutorService()返回一个 ExecutorService 对象,这是Java标准类。在模拟段,用该类替换NotificationService.TaskSubmitter
 
模拟端的实例变量如下
   1: private String xmppHost = "192.168.1.109";//服务器的实际IP
   2: private int xmppPort = 5222;//服务器的实际端口
   3: private List<Runnable> taskList;
   4: private boolean running = false;
   5: private String username;
   6: private String password;
   7: private XMPPConnection connection;
   8: private NotificationPacketListener notificationPacketListener;
2.模拟AndroidPN Client,只是模拟其最基本的功能,即模拟端和服务器连接之后,可以收到服务器推送的信息,再将消息打印出来(也可以对消息进行其他处理),因此像重连,下线之类的功能,暂不考虑。
 
AndroidPN Client通过连接(Connect),注册(Register),登陆(Login)三步,建立起和服务器之间的Session。服务器就是通过该Session向客户端推送信息。这三步正好对应XmppManager中的三个线程类ConnectTask,RegisterTask和LoginTask。
ConnectTask
   1: private class ConnectTask implements Runnable {
   2:     @Override
   3:     public void run() {
   4:         ConnectionConfiguration connConfig = new ConnectionConfiguration(xmppHost, xmppPort);
   5:         connConfig.setSecurityMode(SecurityMode.required);
   6:         connConfig.setSASLAuthenticationEnabled(false);
   7:         connConfig.setCompressionEnabled(false);
   8:         connection = new XMPPConnection(connConfig);
   9:         try {
  10:             connection.connect();
  11:             //这行代码,确保客户端能收到服务器推送来的消息!!!
  12:             ProviderManager.getInstance().addIQProvider("notification",
  13:                     "androidpn:iq:notification",
  14:                     new NotificationIQProvider());
  15:         } catch (XMPPException e) {
  16:             // TODO Auto-generated catch block
  17:             e.printStackTrace();
  18:         }
  19:         // 调用任务队列的下个方法
  20:         runTask();
  21:  
  22:     }
  23:  
  24: }

12~14: ProviderManager.getInstance().addIQProvider("notification","androidpn:iq:notification",new NotificationIQProvider());保证客户端能收到服务器推送的信息

RegisterTask

   1: private class RegisterTask implements Runnable {
   2:  
   3:     @Override
   4:     public void run() {
   5:         Registration registration = new Registration();
   6:         PacketFilter packetFilter = new AndFilter(new PacketIDFilter(
   7:                 registration.getPacketID()), new PacketTypeFilter(IQ.class));
   8:         PacketListener packetListener = new PacketListener() {
   9:  
  10:             @Override
  11:             public void processPacket(Packet packet) {
  12:                 if (packet instanceof IQ) {
  13:                     IQ response = (IQ) packet;
  14:                     // 如果出错
  15:                     if (response.getType() == IQ.Type.ERROR) {
  16:                         if (response.getError().toString().contains("409")) {
  17:                               System.out.println("注册XMPP账号时发生未知错误"
  18:                                       + response.getError().getCondition());
  19:                         }
  20:                         // 如果没出错 执行任务队列的下个任务
  21:                     } else if (response.getType() == IQ.Type.RESULT) {
  22:                           System.out.println("用户名:" + username);
  23:                           System.out.println("密码:" + password);
  24: //
  25:                           System.out.println("注册成功");
  26:                         runTask();
  27:                     }
  28:                 }
  29:             }
  30:         };
  31:  
  32:         connection.addPacketListener(packetListener, packetFilter);
  33:         registration.setType(IQ.Type.SET);
  34:         Map<String, String> attributes = new HashMap<String, String>();
  35:         //attributes.put("username", username);
  36:         //attributes.put("password", password);
  37:         //registration.setAttributes(attributes);
  38:         registration.addAttribute("username", username);
  39:         registration.addAttribute("password", password);
  40:  
  41:         connection.sendPacket(registration);
  42:     }
模拟端的RegisterTask和XmppManager的RegisterTask,只要去掉与Android SDK相关的代码即可。
LoginTask
   1: private class LoginTask implements Runnable{
   2:  
   3:     @Override
   4:     public void run() {
   5:     try {
   6:             //客户端登陆,当登陆成功后,服务器端就有一个Session
   7:             connection.login(username, password, "AndroidClient");
   8:             //Xmpp节过滤器,客户端只接受NotificationIQ的xmpp节
   9:             PacketFilter packetFilter = new PacketTypeFilter(NotificationIQ.class);
  10:             connection.addPacketListener(notificationPacketListener, packetFilter);
  11:         } catch (XMPPException e) {
  12:             // TODO Auto-generated catch block
  13:             e.printStackTrace();
  14:         }
  15:     }
  16:     
  17: }
 
3.其余的执行代码和AndroidPN Client的代码基本一致,不再赘述。