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里轮询下是否已经有登录的,有的话就把登录的退出。不难解决,关键还是要理清服务端的流程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值