`
RamosLi
  • 浏览: 120057 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

最好用的Java APNS类库

阅读更多
    我在公司的项目组一直都在做一款ios应用,涉及到聊天功能,当用户在线时,可以使用长连接将消息推送过去,但应用可能并不处于运行中,比如用户关闭应用,或者切换到后台10分钟后应用会停止运行。如果这时需要给用户推送消息,那怎么办呢?此时就需要用到APNS(Apple Push Notification Service),网上关于APNS的介绍一大堆,这里就不做过多叙述了。大概是这么一个过程:我的server将消息发到苹果的服务器(APNS Server),苹果服务器再将消息转发到用户的iphone上,iphone收到消息后再弹窗提示用户。我们需要做的就是将消息发给APNS Server。下图是iphone收到通知后的截屏:
 

      我是Java码农,网上比较流行的Java APNS的类库主要有两个:1. JavaPNS. 2.Java APNS(notnoop)  
 
    JavaPNS优点是简单,但缺点也很明显,效率不高,没有考虑各种通知发送出错的情况。这个库适合那些每天通知发送量特别小,并且用户收没收到也无所谓的应用。
 
    notnoop的Java APNS就要强大很多,目前它应该是使用最多的Java类库。我们也用了将近一年,但随着使用的加深,发现它有很多不完善之处。最严重的问题是,运行一段时间后就死掉了,通知再也发不出去了,但重启下就又恢复了。经查,应该是死锁了,通知堆积在内存中并没有真正发出去。这对于对消息送达率和及时性要求非常高的聊天软件来说,是不能忍受的。因此,打算重写,自己实现!
 
    在这个背景下,dbay-apns-for-java 开源项目应运而生。目前已经放到了Github上供大家下载,中英双语注释,力争每个人都看的懂,地址:https://github.com/RamosLi/dbay-apns-for-java
 
    dbay-apns4j 吸取了其他类库的优点,修正了不足之处,更是将一些极端情况都考虑进去了。比如跟APNS Server建立的长连接,对方可能会单方面关闭连接(connection_idle),此时会造成通知发送看起来成功其实失败的情况,dbay-apns4j也考虑到了。
 
    目前,已经在我的Server上运行一段时间,每天需要发送上百万的消息,表现良好。我自信这是目前最好的Java APNS类库,欢迎大家下载使用,也欢迎指出一些不足之处。
 
    另外:关于APNS的一些深入研究,我在上篇文章中已经写出来了,地址:http://ramosli.iteye.com/admin/blogs/1940843
  • 大小: 682.5 KB
8
1
分享到:
评论
12 楼 kill1 2014-04-09  
我用这工具显示推送成功,但实际上手机没收到是怎么回事,我用JAVApns推这个手机是能收到的;以下是用此工具推送后的日志:
2014-04-09 16:31:59.171 [pool-2-thread-1] [com.umpay.require.pushmanage.apns4j.impl.ApnsConnectionImpl.java:180] - pro-1 Send success. count: 1, notificaion: id=101 token=1436318785dfc72f9011bc21361b31e0202e63dd85e988948f00d9c4a2f31a8a payload={"aps":{"alert":"test1","badge":1,"sound":""},"uid":123456,"type":12}
2014-04-09 16:32:13.156 [Thread-0] [com.umpay.require.pushmanage.apns4j.impl.ApnsConnectionImpl$1.java:313] - pro-1 Socket is closed
11 楼 RamosLi 2014-04-03  
@ 9楼 afei1689
你说的很对,这儿确实不太严谨。我已经改了
不过在实际的运行过程中我还没碰到过这种情况,APNS Server关闭连接有三种情况,1.发送的消息有误,比如device_token无效,2.超过了Idle Time,3,APNS Server更新服务,重启。

情况1:关闭前,APNS Server会发一段error-response,此时socket能读到,没有问题
情况2:APNS Server Idle time大约是两小时,dbay-apns4j半小时就强制重连一次,也没有问题
情况3:APNS Server更新服务,看起来人家应该是无缝切换,咱们的长连接连的应该是APNS的负载均衡设备,真正提供服务的Server重启不影响长连接(应该是这样的)
10 楼 冰影轮 2014-04-03  
你好 ,下载了你的代码,我这执行的是这个结果,可以帮忙看看为什么吗?
信息: pro-2 Send success. count: 1, notificaion: id=102 token=eaa863405c2e2996413cf518b7f15ba02684c2865cd09c9c55c55b0a232c7c23 payload={"aps":{"sound":"","alert":{"loc-args":["Jenna","Frank"],"loc-key":"你好啊"},"badge":1}}
四月 03, 2014 5:18:20 下午 com.dbay.apns4j.impl.ApnsConnectionImpl sendNotification
信息: pro-1 Send success. count: 1, notificaion: id=101 token=eaa863405c2e2996413cf518b7f15ba02684c2865cd09c9c55c55b0a232c7c23 payload={"uid":123456,"aps":{"sound":"msg.mp3","alert":"How are you?","badge":1},"type":12}
四月 03, 2014 5:18:25 下午 com.dbay.apns4j.impl.ApnsConnectionImpl$1 run
严重: pro-2s Socket Closed
java.net.SocketException: Socket Closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
at sun.security.ssl.InputRecord.read(InputRecord.java:480)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:884)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:102)
at java.io.InputStream.read(InputStream.java:101)
at com.dbay.apns4j.impl.ApnsConnectionImpl$1.run(ApnsConnectionImpl.java:258)
at java.lang.Thread.run(Thread.java:744)

四月 03, 2014 5:18:25 下午 com.dbay.apns4j.impl.ApnsConnectionImpl$1 run
严重: pro-1s Socket operation on nonsocket: recv failed
java.net.SocketException: Socket operation on nonsocket: recv failed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
at sun.security.ssl.InputRecord.read(InputRecord.java:480)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:884)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:102)
at java.io.InputStream.read(InputStream.java:101)
at com.dbay.apns4j.impl.ApnsConnectionImpl$1.run(ApnsConnectionImpl.java:258)
at java.lang.Thread.run(Thread.java:744)信息: pro-2 Send success. count: 1, notificaion: id=102 token=eaa863405c2e2996413cf518b7f15ba02684c2865cd09c9c55c55b0a232c7c23 payload={"aps":{"sound":"","alert":{"loc-args":["Jenna","Frank"],"loc-key":"你好啊"},"badge":1}}
四月 03, 2014 5:18:20 下午 com.dbay.apns4j.impl.ApnsConnectionImpl sendNotification
信息: pro-1 Send success. count: 1, notificaion: id=101 token=eaa863405c2e2996413cf518b7f15ba02684c2865cd09c9c55c55b0a232c7c23 payload={"uid":123456,"aps":{"sound":"msg.mp3","alert":"How are you?","badge":1},"type":12}
四月 03, 2014 5:18:25 下午 com.dbay.apns4j.impl.ApnsConnectionImpl$1 run
严重: pro-2s Socket Closed
java.net.SocketException: Socket Closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
at sun.security.ssl.InputRecord.read(InputRecord.java:480)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:884)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:102)
at java.io.InputStream.read(InputStream.java:101)
at com.dbay.apns4j.impl.ApnsConnectionImpl$1.run(ApnsConnectionImpl.java:258)
at java.lang.Thread.run(Thread.java:744)

四月 03, 2014 5:18:25 下午 com.dbay.apns4j.impl.ApnsConnectionImpl$1 run
严重: pro-1s Socket operation on nonsocket: recv failed
java.net.SocketException: Socket operation on nonsocket: recv failed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
at sun.security.ssl.InputRecord.read(InputRecord.java:480)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:884)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:102)
at java.io.InputStream.read(InputStream.java:101)
at com.dbay.apns4j.impl.ApnsConnectionImpl$1.run(ApnsConnectionImpl.java:258)
at java.lang.Thread.run(Thread.java:744)
9 楼 afei1689 2014-03-31  
RamosLi 写道
moniori 写道
今天仔细读了一下代码,可以忽略我之前的评论拉,当时看的不够仔细全面
问题解决了就好,不过我在自己的服务器上运行cpu都很低。

while (true) {
  try {
    size = socketIs.read(res);
    if (size > 0) {
      // break, only when something was read
      break;
    }
  } catch (SocketTimeoutException e) {
    // There is no data. Keep reading.
  }
}
这段代码是有bug的,当长连接apn server关闭输入流时,这里read操作返回-1的,会导致这段代码死循环的,我在使用的时候加上这个控制
8 楼 RamosLi 2014-03-25  
moniori 写道
今天仔细读了一下代码,可以忽略我之前的评论拉,当时看的不够仔细全面
问题解决了就好,不过我在自己的服务器上运行cpu都很低。
7 楼 moniori 2014-03-25  
今天仔细读了一下代码,可以忽略我之前的评论拉,当时看的不够仔细全面
6 楼 moniori 2014-03-25  
Hi, 我遇到了和5楼同样的问题。看了下源代码,卡在了ApnsConnectionImpl类下的startErrorWorker方法里:
while (true) {
  try {
    size = socketIs.read(res);
    if (size > 0) {
      // break, only when something was read
      break;
    }
  } catch (SocketTimeoutException e) {
    // There is no data. Keep reading.
  }
}
由于你给出的“关于APNS的一些深入研究”文章无法访问也搜索不到,我也没能详细理解你在这里的思路。

如果你现在还在某些项目里使用这个库并且“每天需要发送上百万的消息,表现良好”,我想也许是我配置上有什么问题?不知可否给些提示

如果你现在没有在用,不知道是否可以提供下这部分处理的思路?也许我可以顺着你的思路再做些研究,将这个问题解决?解决的花我会来联系你更新代码

如果你没有时间,我想也许可以直接在这里做个简单的超时判断?这个思路仍然最好首先连接你这边的设计思路。

总之,希望可以我们联系上把问题解决。如果你方便的话我们一起,或者希望得到你的一些思路介绍。无论如何,如果可以解决,我都会发给你解决后代码,如果你愿意,可以更新到Git上。留个油箱:moniori^163^c o m
5 楼 xiaobenbenxiong 2014-02-18  
您好,我在用dbay-apns4j-1.4.jar的过程中,并发数设置为10,服务器的cpu在运行一天多后达到了接近100%,jstack查看,发现几个占用cpu高的线程,对应的信息如下:
"Thread-76" prio=10 tid=0x00007f71d400f000 nid=0x6e11 runnable [0x00007f71c73f2000]
   java.lang.Thread.State: RUNNABLE
at java.io.InputStream.read(InputStream.java:82)
at com.dbay.apns4j.impl.ApnsConnectionImpl$1.run(ApnsConnectionImpl.java:258)
at java.lang.Thread.run(Thread.java:662)

能帮忙解决下吗?
4 楼 hymcn2008 2014-02-14  
还没看,顶一个
3 楼 RamosLi 2013-11-06  
fww4022 写道
您好, 我用您在github上的库测试时报这个错误:

java.io.IOException: failed to decrypt safe contents entry: java.io.IOException: getSecretKey failed: PBE SecretKeyFactory not available
at sun.security.pkcs12.PKCS12KeyStore.engineLoad(Unknown Source)
at java.security.KeyStore.load(Unknown Source)
at com.dbay.apns4j.tools.ApnsTools.createSocketFactory(ApnsTools.java:98)
at com.dbay.apns4j.impl.ApnsServiceImpl.<init>(ApnsServiceImpl.java:55)
at com.dbay.apns4j.impl.ApnsServiceImpl.createInstance(ApnsServiceImpl.java:128)
at com.dbay.apns4j.demo.Apns4jDemo.getApnsService(Apns4jDemo.java:30)
at com.dbay.apns4j.demo.Apns4jDemo.main(Apns4jDemo.java:36)
Caused by: java.io.IOException: getSecretKey failed: PBE SecretKeyFactory not available
at sun.security.pkcs12.PKCS12KeyStore.getPBEKey(Unknown Source)
... 7 more
Caused by: java.security.NoSuchAlgorithmException: PBE SecretKeyFactory not available
at javax.crypto.SecretKeyFactory.<init>(SecretKeyFactory.java:121)
at javax.crypto.SecretKeyFactory.getInstance(SecretKeyFactory.java:159)
... 8 more
能帮忙看看吗?


你的运行环境是什么样的?一般来说,应该是证书的问题,转换成xx.p12了么
2 楼 fww4022 2013-11-05  
您好, 我用您在github上的库测试时报这个错误:

java.io.IOException: failed to decrypt safe contents entry: java.io.IOException: getSecretKey failed: PBE SecretKeyFactory not available
at sun.security.pkcs12.PKCS12KeyStore.engineLoad(Unknown Source)
at java.security.KeyStore.load(Unknown Source)
at com.dbay.apns4j.tools.ApnsTools.createSocketFactory(ApnsTools.java:98)
at com.dbay.apns4j.impl.ApnsServiceImpl.<init>(ApnsServiceImpl.java:55)
at com.dbay.apns4j.impl.ApnsServiceImpl.createInstance(ApnsServiceImpl.java:128)
at com.dbay.apns4j.demo.Apns4jDemo.getApnsService(Apns4jDemo.java:30)
at com.dbay.apns4j.demo.Apns4jDemo.main(Apns4jDemo.java:36)
Caused by: java.io.IOException: getSecretKey failed: PBE SecretKeyFactory not available
at sun.security.pkcs12.PKCS12KeyStore.getPBEKey(Unknown Source)
... 7 more
Caused by: java.security.NoSuchAlgorithmException: PBE SecretKeyFactory not available
at javax.crypto.SecretKeyFactory.<init>(SecretKeyFactory.java:121)
at javax.crypto.SecretKeyFactory.getInstance(SecretKeyFactory.java:159)
... 8 more
能帮忙看看吗?
1 楼 liangcoder 2013-10-12  
good job

相关推荐

    iphone消息推送APNS

    **苹果推送通知服务(Apple Push Notification service,简称APNS)** APNS是苹果公司提供的一项服务,用于向iOS、iPadOS、watchOS、tvOS以及macOS设备推送通知。通过APNS,应用开发者可以在他们的应用不在前台运行...

    苹果消息推送 java端

    - 在Java中,有多个第三方库可以帮助我们与APNs交互,例如`Apns4j`、`JavaAPNS`和`ApnsPushNotification`等。这些库通常提供了API,简化了证书管理、构建推送消息和处理反馈等功能。 4. **推送消息结构**: - 一...

    javapns-jdk

    在文件名“javapns-jdk16-163.jar”中,".jar"是Java Archive的缩写,它是Java平台下用于打包和部署类库的标准格式。这意味着这个文件是一个可直接在Java环境中使用的库,包含了JavaPNS的代码和其他依赖,以便开发者...

    基于Java的即时通信软件

    1. **Java基础知识**:Java的核心特性包括平台独立性(JVM使得Java代码可以在任何支持Java的设备上运行)、面向对象编程(OOP)以及丰富的类库。在开发即时通信软件时,开发者可以利用Java的多线程特性来处理并发...

    Java+XML日程提醒系统.7z

    Java的类库丰富,支持网络通信、多线程、数据库连接等多种功能,这使得Java成为开发跨平台应用程序的理想选择。 XML,全称为eXtensible Markup Language,是一种标记语言,用于描述数据的结构和内容。与HTML不同,...

    仿QQ开发的即时通讯软件

    Java的基础语法、类库和设计模式都是开发此类应用的基础。 2. **Socket编程**:即时通讯的核心在于网络通信,Java中的Socket编程提供了客户端和服务器端通信的能力。通过创建Socket连接,服务器可以接收并处理来自...

    xiaoyuantong

    Java的类库丰富,提供了大量用于网络通信、数据库连接、图形用户界面(GUI)构建的API,这对于构建一个功能全面的校园信息系统非常有利。 在"校园通"程序中,教务管理部分可能利用了Java的集合框架来存储和操作学生...

    jsp iOS推送的包

    3. **commons-lang-2.1.jar**:Apache Commons Lang是Java的一个工具类库,包含了一系列实用的工具方法,增强了Java的内置类。在处理推送服务时,可能会用到字符串操作、数组处理等工具。 4. **...

    Teacher-student-corner:大学课程的师生交流应用

    Java是一种广泛使用的面向对象的编程语言,以其跨平台性、安全性以及强大的类库支持而著称。在开发此类应用时,Java的Swing或JavaFX库可以用于构建用户界面,提供丰富的图形元素和交互功能。此外,Java的多线程特性...

    information-release-sys:信息发布系统

    在这个过程中,Java作为强大的后端开发语言,以其优秀的跨平台性能和丰富的类库,为系统的构建提供了坚实的基础。 在Java中,信息发布系统可能采用MVC(Model-View-Controller)架构模式,这种模式可以清晰地分离...

    CommitNotifier

    Java是一种跨平台的、面向对象的编程语言,具有丰富的类库和强大的性能,适合开发这样的桌面应用程序。 3. **事件监听和处理**:为了在SVN仓库有新的提交时发送通知,CommitNotifier需要实现事件监听机制。这可能...

    XamChat:适用于iOS和Android的简单聊天应用程序

    通过这些库,开发者可以使用C#创建原生的iOS和Android界面,同时利用.NET类库来实现应用程序的后端功能。 **XamChat应用结构** 在XamChat项目中,我们可能会看到以下主要组成部分: 1. **用户界面(UI)**:...

Global site tag (gtag.js) - Google Analytics