`
handsomeliuyang
  • 浏览: 311875 次
  • 性别: Icon_minigender_1
  • 来自: 益阳
社区版块
存档分类
最新评论

Androidpn里的Xmpp的理解

 
阅读更多

  XMPP(可扩展通讯和表示协议)是基于可扩展标记语言(XML)的协议,它用于即时消息(IM)以及在线探测。这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息。用xmpp来实现android的push功能,感觉有点大材小用了,xmpp本身是一种即时通信协议。

  xmpp是一种用于即时通信的协议,使用过程有点类似于我们使用QQ的过程,其使用过程分为三步:

  1. 连接服务器,就好像打开QQ软件,看代码:

if(!mXmppManager.isConnected()) {
	ConnectionConfiguration config = new ConnectionConfiguration(mHost, mPort);
	config.setSecurityMode(SecurityMode.required);
	config.setSASLAuthenticationEnabled(false);
	config.setCompressionEnabled(false);
	
	XMPPConnection connection = new XMPPConnection(config);
	mXmppManager.setConnection(connection);
	try {
		connection.connect();
		Log.i(LOGTAG, "XMPP connected successfully");
		/**
		 * 这个就是对于通信的xml文本进行解析的解析器,再把信息转换成IQ,这个相当于QQ的聊天信息
		 * 如果要用这个协议,其IQ的子类和IQProvider要进行重写
		 */
		ProviderManager.getInstance().addIQProvider("notification",
				"androidpn:iq:notification",
				new NotificationIQProvider());
		
	} catch (XMPPException e) {
		Log.d(LOGTAG, "the connection is error ... ");
	}
	mXmppManager.runTask();
} else {
	Log.i(LOGTAG, "XMPP connected already");
	mXmppManager.runTask();
}

 

这一步主要是连接服务器,还有设置一些连接的参数,还有设置连接的解析器。

  2. 如果没有用户,注册新的帐号和密码

if(!mXmppManager.isRegistered()){
	final String newUsername = newRandomUUID();
	final String newPassword = newRandomUUID();
	Registration registration = new Registration();
	
	PacketFilter packetFilter = new AndFilter(new PacketIDFilter(
			registration.getPacketID()), new PacketTypeFilter(
			IQ.class));
	PacketListener packetListener = new PacketListener() {
		@Override
		public void processPacket(Packet packet) {
			// 服务器回复客户端
            if(packet instanceof IQ) {
            	IQ response = (IQ) packet;
            	if(response.getType() == IQ.Type.ERROR) { // 注册失败
            		if (!response.getError().toString().contains(
                            "409")) {
                        Log.e(LOGTAG,"Unknown error while registering XMPP account! " + response.getError().getCondition());
                    }
            	} else if(response.getType() == IQ.Type.RESULT) { // 注册成功
            		mXmppManager.setUsername(newUsername);
            		mXmppManager.setPassword(newPassword);
            		// 把用户名和密码都保存到磁盘
            		Editor editor = mSharedPrefs.edit();
            		editor.putString(Contants.XMPP_USERNAME, newUsername);
            		editor.putString(Contants.XMPP_PASSWORD, newPassword);
            		editor.commit();
            		
            		mXmppManager.runTask();
            	}
            }
		}
	};
	// 给注册的Packet设置Listener,因为只有等到正真注册成功后,我们才可以交流
	mConnection.addPacketListener(packetListener, packetFilter);
	
	registration.setType(IQ.Type.SET);
	registration.addAttribute("username", newUsername);
    registration.addAttribute("password", newPassword);
	
	// 向服务器端,发送注册Packet包,注意其中Registration是Packet的子类
	mConnection.sendPacket(registration);
	
} else { // 已经注册过了
	mXmppManager.runTask();
}

 

 只要连接了服务器了,客户端就可以向服务器端发送消息,发送是以Packet(数据包)来进行发送的,这个类有很多的子类,注册的子类为Registration。

 

 

 

 

 还有要注意的是,上面的addPacketListener方法不是给所有发送的数据包设置listener,而只是针对这次的注册Packet。

  3. 用注册的帐号和密码进行登陆(像用QQ号帐进行登陆一样)

// 判断是否已经登陆过了,是否是在登陆状态
if(!mXmppManager.isAuthenticated()) {
	try {
		mConnection.login(mUsername, mPassword, "AndroidpnClient");
		// 设置XmppConnection的监听器
		if(mXmppManager.getConnectionListener() != null) {
			mConnection.addConnectionListener(mXmppManager.getConnectionListener());
		}
		// 设置服务器端推送的监听器
		PacketFilter packetFilter = new PacketTypeFilter(NotificationIQ.class);
		PacketListener packetListener = mXmppManager.getNotificationPacketListener();
		mConnection.addPacketListener(packetListener, packetFilter);
		
		mXmppManager.runTask();
	} catch (XMPPException e) {
		// 登陆失败,应该重试 
        String INVALID_CREDENTIALS_ERROR_CODE = "401";
        String errorMessage = e.getMessage();
        // 如果只是因为没有注册,则进行重新注册
        if (errorMessage != null && errorMessage.contains(INVALID_CREDENTIALS_ERROR_CODE)) {
        	mXmppManager.reregisterAccount(); 
            return;
        }
        mXmppManager.startReconnectionThread();
	} catch (Exception e) { // 有可能mConnection都为空
		Log.e(LOGTAG, "LoginTask.run()... other error");
		Log.e(LOGTAG, "Failed to login to xmpp server. Caused by: " + e.getMessage());
		mXmppManager.startReconnectionThread(); // 启动重连线程
	}
} else {
	mXmppManager.runTask();
}

  

  这里设置了连接的监听器mConnection.addConnectionListener(),连接过程中有可以连接突然中断,连接出错等等问题,要进行监听。

  设置服务器推送信息的Listener,接收到信息后,显示给用户。
  如果出错的原因是401(无效的用户名和密码,则应该进行重新注册,再连接)

 

对于服务器push过来的信息进行处理,是在PacketListener类里面,这个接口里,只要实现一个方法processPacket(Packet packet),从传过来的Packet(数据包)里获取自己需要的数据:

public void processPacket(Packet packet) {
    if(packet instanceof NotificationIQ) {
    	NotificationIQ notification = (NotificationIQ) packet;
    	if(notification.getChildElementXML().contains("androidpn:iq:notification")) {
    		String notificationId = notification.getId();
            String notificationApiKey = notification.getApiKey();
            String notificationTitle = notification.getTitle();
            String notificationMessage = notification.getMessage();
            String notificationUri = notification.getUri();

            Intent intent = new Intent(Contants.ACTION_SHOW_NOTIFICATION);
            intent.putExtra(Contants.NOTIFICATION_ID, notificationId);
            intent.putExtra(Contants.NOTIFICATION_API_KEY,notificationApiKey);
            intent.putExtra(Contants.NOTIFICATION_TITLE,notificationTitle);
            intent.putExtra(Contants.NOTIFICATION_MESSAGE, notificationMessage);
            intent.putExtra(Contants.NOTIFICATION_URI, notificationUri);

            mXmppManager.getContext().sendBroadcast(intent);
    	}
    }
}

 

 

对于Androidpn项目的整体代码分析,看下一遍文章。

 

 

 

 

5
0
分享到:
评论
6 楼 天涯海角262253 2015-05-28  
5 楼 u012398365 2014-10-14  
眼拙呀,直接new一个XmppManager对象,connect就可以了。
4 楼 u012398365 2014-10-14  
服务端启动了,客户端安装成功后,在哪注册设备呢?
3 楼 wenjiefeng 2012-10-14  
请问一下,在andrioidpn-client客户端源码里,NotificationDetailsActivity这个类里,下面的参数都是什么意思呢
Intent intent = getIntent();
        String notificationId = intent
                .getStringExtra(Constants.NOTIFICATION_ID);
        String notificationApiKey = intent
                .getStringExtra(Constants.NOTIFICATION_API_KEY);
        String notificationTitle = intent
                .getStringExtra(Constants.NOTIFICATION_TITLE);
        String notificationMessage = intent
                .getStringExtra(Constants.NOTIFICATION_MESSAGE);
        String notificationUri = intent
                .getStringExtra(Constants.NOTIFICATION_URI);
      Log.i("test", "notificationId===============" + notificationId);
       Log.i("test", "notificationApiKey============" + notificationApiKey);
       Log.i("test", "notificationTitle============" + notificationTitle);
       Log.i("test", "notificationMessage=================" + notificationMessage);
       Log.i("test", "notificationDistance========distance=====111====" + notificationDistance);
       Log.i("test", "notificationUri===============" + notificationUri);
    疑惑1、   这几个参数代表什么意思呢,  notificationId;  notificationApiKey; notificationTitle;     notificationMessage;   notificationUri;
我看源码里好几处都用到这几个参数 ,
  疑惑2、  现在服务端已经能将消息推送到服务端了并增加了一些参数,推送的消息里增加了距离distance等参数,应该在客户端的哪个类里获取这些值呢?
如何处理呢?
谢谢了
2 楼 .荭蓦紡 2012-05-20  
NotificationIQ   这里IQ是啥意思?
1 楼 flytosea 2012-03-14  
哥们写的不错 ,能聊聊吗

相关推荐

Global site tag (gtag.js) - Google Analytics