前面说过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";//服务器的实际IP2: 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。
ConnectTask1: 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 block17: 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相关的代码即可。
LoginTask1: private class LoginTask implements Runnable{2:
3: @Override
4: public void run() {5: try {6: //客户端登陆,当登陆成功后,服务器端就有一个Session7: 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 block13: e.printStackTrace();
14: }
15: }
16:
17: }
3.其余的执行代码和AndroidPN Client的代码基本一致,不再赘述。
转载于:https://blog.51cto.com/youngcold/1107796