Androidpn客户端和服务器的研究

Android推送通知指南:http://blog.csdn.net/joshua_yu/article/details/6563587

用androidpn来实现推送(Jclick):http://www.iteye.com/topic/1117043?page=13

Androidpn容易出问题的地方:

1,服务器端的监听器,看spring的配置文件就知道,服务器端用的监听器是org.apache.mina.transport.socket.nio.NioSocketAcceptor 也就是apache MINA;

2,客户端容易出问题的地方是在建立连接的时候。之前一直在建立连接的地方抛出异常,连接超时,显而易见是服务器端没有响应导致的,得检查服务器是否有问题。

解决问题的思路:客户端和服务器端建立连接,建立连接之后,服务器端会将客户端信息保存为一个用户,并把信息入库,所以,只需要找到保存user的地方,然后顺藤摸瓜,找到服务端和客户端进行数据交互的地方,最后找到服务端进行数据接收和发送的类大多在org.androidpn.server.xmpp.handle和org.androidpn.server.xmpp.net这个包中,客户端比较重要的地方应该是XmppManager,这个类有和服务器建立连接的地方,建立连接、注册、登录的操作都在这个类中,ConnectTask是XmppManager的内部类,主要作用是建立连接,XMPPConnection是一个connection,出现连接问题,可以打印出XMPPConnection的参数信息是否正确。

其他注意 

(一)请修改  XmppServer  的start方法 

屏蔽掉context = new ClassPathXmlApplicationContext("spring-config.xml"); 

改为ApplicationContextAware 接口中的 

public void setApplicationContext(ApplicationContext context) throws BeansException 

方法,获得ApplicationContext对象。 

否则会启动了2个名为ioAcceptor的NioSocketAcceptor实例,可以查看log日志,在tomcat的log目录下的androidpn.log日志,浪费资源 

而且在linux系统下会提示5552端口被占用 

(二) <bean id="ioAcceptor" class="org.apache.mina.transport.socket.nio.NioSocketAcceptor" 
init-method="bind" destroy-method="unbind"> 

修改成destroy-method="disponse">能快速关闭tomcat进程 

(三)把用户系统融合到自己的应用中去,请修改org.androidpn.server.service.impl.UserServiceImpl 
,使用自己系统的用户接口 

(四)客户端自动注册使用的随机串,如果要使用自己系统的用户,客户端请修改org.androidpn.client.XmppManager 中的username和password 

并用修改服务器端的用户身份验证类org.androidpn.server.xmpp.auth.AuthManager的public static AuthToken authenticate(String username, String token, 
            String digest) throws UnauthenticatedException 方法


开发中,大家的讨论很激烈:

zsg88 写道
在同一手机上运行2个客户端RESOURCE_NAME分别为AndroidpnClient和AndroidpnClient2 
session.do页面显示2个在线,user.do页面显示一个在线。 
打开UserController类,可以看到判断user是否在线的方法是presenceManager.isAvailable(user) 
最终调用的是SessionManager 
    public ClientSession getSession(String username) { 
        // return getSession(new JID(username, serverName, null, true)); 
        return getSession(new JID(username, serverName, RESOURCE_NAME, true)); 
    } 
注意:new JID(username, serverName, RESOURCE_NAME, true) 只指定了一个RESOURCE_NAME,表示只查找名称为RESOURCE_NAME所代表的应用用户,所以另外一个应用的用户就查找不到了。 
把当前这行注释掉 
把被注释的上一行打开,return getSession(new JID(username, serverName, null, true)) 
这里RESOURCE_NAME被设定为null,不指定具体应用名称 
修改 
public ClientSession getSession(JID from){ 
   ...... 
   //if (from.getResource() == null || from.getNode() == null) { 
   //      return null; 
   //} 
       
   if (from.getResource() == null) { 
      if (from.getNode() != null) { 
for (ClientSession session : clientSessions.values()) { 
   if (session.getAddress().getNode().equals(from.getNode())) { 
      return session; 
   } 

      } else { 
        return null; 
      } 
    } 
    return clientSessions.get(from.toString()); 



非常感谢,你说的我测试了,如果广播信息的话,两个都可以收到。但是如果指定username发送的话,只有一个可以收到。我看了一下代码,还应该修改NotificationManager里面的 
public void sendNotifcationToUser(String apiKey, String username, 
String title, String message, String uri, String time) { 
log.debug("sendNotifcationToUser()..."); 
IQ notificationIQ = createNotificationIQ(apiKey, title, message, uri, 
time); 
ClientSession session = sessionManager.getSession(username); 
if (session != null) { 
if (session.getPresence().isAvailable()) { 
notificationIQ.setTo(session.getAddress()); 
session.deliver(notificationIQ); 




把这个方法改成下面的就可以了。 
public void sendNotifcationToUser(String apiKey, String username, 
String title, String message, String uri, String time) 
throws UserNotFoundException { 
log.debug("sendNotifcationToUser()..."); 
IQ notificationIQ = createNotificationIQ(apiKey, title, message, uri, 
time); 
for (ClientSession session : sessionManager.getSessions()) { 
if (session.getUsername().equals(username) 
&& session.getPresence().isAvailable()) { 
notificationIQ.setTo(session.getAddress()); 
session.deliver(notificationIQ); 




zsg88 写道
在同一手机上运行2个客户端RESOURCE_NAME分别为AndroidpnClient和AndroidpnClient2 
session.do页面显示2个在线,user.do页面显示一个在线。 


还有两个问题。 
1、情景是这样的:一个手机里面有多个客户端需要push服务,但是只有一个用户名,现在已经可以实现了。但是这种方式应该客户有多少个,后台的service就有多少个吧?能不能多个客户端公用一个service,第一个客户端启动后,就启动service,最后一个客户端关闭后才关闭service,service收到信息后再根据resource来决定要推给那个客户端? 

2、如果手机1安装客户端1用username1登录后为session1,手机2安装客户端1用username1登录后为session2,这个session2只是session1的created time更新了,其他的不变,但是这个时候只有session2可以接收到信息,但是手机1没有收到任何提示信息,然而它永远也不能收到信息了。而且如果这个时候session1退出service的话,那么session2也关闭了,但是手机2的客户端还开着,然而它永远也连不上服务器了。我想当出现这种情况的时候给手机1一个提示信息,表示你的帐号在别处登录了。

cdztop 写道
zsg88 写道
在同一手机上运行2个客户端RESOURCE_NAME分别为AndroidpnClient和AndroidpnClient2 
session.do页面显示2个在线,user.do页面显示一个在线。 


还有一个问题。情景是这样的:一个手机里面有多个客户端需要push服务,但是只有一个用户名,现在已经可以实现了。但是这种方式应该客户有多少个,后台的service就有多少个吧?能不能多个客户端公用一个service,第一个客户端启动后,就启动service,最后一个客户端关闭后才关闭service,service收到信息后再根据resource来决定要推给那个客户端?
远程服务(Remote Sercie): 

cdztop 写道
zsg88 写道
在同一手机上运行2个客户端RESOURCE_NAME分别为AndroidpnClient和AndroidpnClient2 
session.do页面显示2个在线,user.do页面显示一个在线。 


还有两个问题。 
1、情景是这样的:一个手机里面有多个客户端需要push服务,但是只有一个用户名,现在已经可以实现了。但是这种方式应该客户有多少个,后台的service就有多少个吧?能不能多个客户端公用一个service,第一个客户端启动后,就启动service,最后一个客户端关闭后才关闭service,service收到信息后再根据resource来决定要推给那个客户端? 

2、如果手机1安装客户端1用username1登录后为session1,手机2安装客户端1用username1登录后为session2,这个session2只是session1的created time更新了,其他的不变,但是这个时候只有session2可以接收到信息,但是手机1没有收到任何提示信息,然而它永远也不能收到信息了。而且如果这个时候session1退出service的话,那么session2也关闭了,但是手机2的客户端还开着,然而它永远也连不上服务器了。我想当出现这种情况的时候给手机1一个提示信息,表示你的帐号在别处登录了。


1、先仔细看看MINA框架,本来就是多个客户端公用一个service,但是是有数量限制的。。 
2、这个也可以解决的,在用户登录的时候,去session里轮询下是否已经有登录的,有的话就把登录的退出。不难解决,关键还是要理清服务端的流程。

你可能感兴趣的:(String,session,服务器,service,null,手机)