今天在做邮件的推送功能,即当邮件服务器接收到新邮件时,客户端这边可以立即接收到。
思路:利用 Java Mail IMAP IDLE 去实现此功能
刚开始利用 folder.idle()去实现,代码如下,但出现一个问题,接收到新邮件之后,会自动断开监听。
IMAPFolder folder = (IMAPFolder)store.getFolder("INBOX");
folder.open(Folder.READ_WRITE);
folder.addMessageCountListener(new MessageCountAdapter() {
@Override
public void messagesAdded(MessageCountEvent e) {
super.messagesAdded(e);
Message[] msgs = e.getMessages();
for(int i=0;i<msgs.length;i++){
try {
Log.e("add 邮件","add 邮件主题"+msgs[i].getSubject());
} catch (MessagingException e1) {
e1.printStackTrace();
}
}
}
@Override
public void messagesRemoved(MessageCountEvent e) {
super.messagesRemoved(e);
Message[] msgs = e.getMessages();
for(int i=0;i<msgs.length;i++){
try {
Log.e("remove 邮件","remove 邮件主题"+msgs[i].getSubject());
} catch (MessagingException e1) {
e1.printStackTrace();
}
}
}
});
folder.idle(true);
查看官方文档:
Google翻译:与idle()类似,但如果一次为真,则在第一次通知后中止IDLE命令,以允许调用者同步处理任何通知。
然后我就用folder.idle()去替代folder.idle(true),但貌似还是没起作用,下面是idle()方法的介绍
Google翻译:如果服务器支持,则使用IMAP IDLE命令(请参阅RFC 2177)进入空闲模式,以便服务器可以发送未经请求的新消息到达等通知,而无需客户端不断轮询服务器。 使用适当的侦听器来通知新消息或其他事件。 当另一个线程(例如,侦听器线程)需要为该文件夹发出IMAP命令时,将终止空闲模式并返回此方法。 通常,调用者将在循环中调用此方法。
mail.imap.minidletime属性在从此方法返回之前强制执行最小延迟,以确保其他线程有机会在调用者再次调用此方法之前发出命令。 默认延迟为10毫秒。
最后如何解决的:
利用IdleManager迅速解决了此问题(查阅了官网文档)
ExecutorService es = Executors.newCachedThreadPool();
final IdleManager idleManager = new IdleManager(session, es);
IMAPFolder folder = (IMAPFolder)store.getFolder("INBOX");
folder.open(Folder.READ_WRITE);
folder.addMessageCountListener(new MessageCountAdapter() {
@Override
public void messagesAdded(MessageCountEvent e) {
super.messagesAdded(e);
Folder folder = (Folder)e.getSource();
Message[] msgs = e.getMessages();
for(int i=0;i<msgs.length;i++){
try {
Log.e("add 邮件","add 邮件主题"+msgs[i].getSubject());
} catch (MessagingException e1) {
e1.printStackTrace();
}
}
try {
idleManager.watch(folder);
} catch (MessagingException e1) {
e1.printStackTrace();
}
}
@Override
public void messagesRemoved(MessageCountEvent e) {
super.messagesRemoved(e);
Message[] msgs = e.getMessages();
for(int i=0;i<msgs.length;i++){
try {
Log.e("remove 邮件","remove 邮件主题"+msgs[i].getSubject());
} catch (MessagingException e1) {
e1.printStackTrace();
}
}
}
});
idleManager.watch(folder);
目前此方法测试良好,但可能会出现断线重连的状况,IMAP指出30分钟内无任何响应,会自动断开连接,所以这个问题我们也得重视。