通过Java使用Apple推送通知服务

我试图实现一个Java程序,它将Apple推送通知发送到iPhone客户端应用程序…找到以下库: Java APN

提供者代码:

创建以下代码(来自Javapns)以在我的应用程序中使用:

try { PayLoad payLoad = new PayLoad(); payLoad.addAlert("My alert message"); payLoad.addBadge(45); payLoad.addSound("default"); PushNotificationManager pushManager = PushNotificationManager.getInstance(); pushManager.addDevice("iPhone", "f4201f5d8278fe39545349d0868a24a3b60ed732"); log.warn("Initializing connectiong with APNS..."); // Connect to APNs pushManager.initializeConnection(HOST, PORT, "/etc/Certificates.p12", "password", SSLConnectionHelper.KEYSTORE_TYPE_PKCS12); Device client = pushManager.getDevice("Lambo"); // Send Push log.warn("Sending push notification..."); PushNotificationManager.getInstance().sendNotification(client, payLoad); } catch (Exception e) { throw new ApnsPushNotificationException("Unable to send push " + e); } 

当我运行这个应用程序时(你可以通过Log4j语句看到),没有例外情况发生:

  WARN [MyCode] Initializing connectiong with APNS... WARN [MyCode] Sending push notification... 

但我的客户端应用程序没有收到任何通知!

IDPP注册流程:

此外,在iPhone开发人员计划门户(IDPP)上做了以下事情:

  • 创建了基于APNS的SSL证书和密钥

  • 创建并安装了配置文件

  • 在服务器上安装了SSL证书和密钥。

已多次阅读Apple推送通知服务指南并注意到以下几点:

(1)在页15上,它指出设备令牌与设备UDID不同(我当前错误地将其作为PushNotificationManager.addDevice()方法中的第二个参数传入(参见上文))。

在第17页,它指出:

“APN使用唯一设备证书中包含的信息生成设备令牌。设备令牌包含设备的标识符。然后使用令牌密钥加密设备令牌并将其返回给设备。设备将设备令牌返回给设备令牌。请求应用程序作为NSData对象。然后,应用程序必须以二进制或hex格式将设备令牌传递给其提供者。“

iPhone OS客户端实施

(2)在阅读第33-34页后,我发现我没有包含Objective-C代码以使app注册APN。

我不是Objective-C开发人员,所以我可以恢复设备代码,还是必须从证书中获取它?

我在哪里获取设备令牌(抱歉,其他人编写了Objective-C客户端应用程序,我是Java开发人员)?

问题(S):

(1)除了不知道从何处获取设备令牌和移动客户端代码注册外,还有其他我没有查看或错过的内容吗?

(2)我是否正确使用Javapns库?

感谢您抽出时间来阅读…

只是一点点提示,为了将收到的令牌转换为适合javapns注册的格式,这段代码可以解决问题:

 - (NSString *)convertTokenToDeviceID:(NSData *)token { NSMutableString *deviceID = [NSMutableString string]; // iterate through the bytes and convert to hex unsigned char *ptr = (unsigned char *)[token bytes]; for (NSInteger i=0; i < 32; ++i) { [deviceID appendString:[NSString stringWithFormat:@"%02x", ptr[i]]]; } return deviceID; 

}

作为一个可耻的自我广告,我鼓励使用java-apns库。 您的代码将如下所示:

 ApnsService service = APNS.newService() .withCert("/etc/Certificates.p12", "password") .withSandboxDestination() // or .withProductionDestination() .build(); String payload = APNS.newPayload() .alertBody("My alert message") .badge(45) .sound("default") .build(); String deviceToken = "f4201f5d8278fe39545349d0868a24a3b60ed732"; log.warn("Sending push notification..."); service.push(deviceToken, payload); 
  1. 您的Java代码看起来很稳固! 但是,不要忘记通过PushNotificationManager.closeConnection()关闭连接。 自己清理后很重要。

    作为旁注,我注意到你正在添加设备’iPhone’,但之后查询’Lambo’。 这表明存在错误。

  2. 代码中显示的设备令牌不正确。 设备令牌,当前为32位长值,可以变为64个字符。 我假设在将通知推送到无效令牌时服务器无声地失败!

  3. 获取设备令牌的唯一方法是从应用程序本身。 根据推送通知指南的建议,iPhone应用程序需要在启动时注册通知。 在application:didRegisterForRemoteNotificationsWithDeviceToken: ,iPhone需要将设备令牌发送到您的java提供程序服务器。 (出于调试目的,您可以只使用NSLog设备令牌并使用它;它不会在运行期间发生变化)。

    我建议您在Java提供程序服务器中创建一个服务器来接收设备令牌。 设置ServerSocket以接收来自iPhone及其设备令牌的连接(以及您需要的任何其他信息),并将令牌插入数据库中。

我尝试了这个,并且在发送通知时我一直被绞死,没有任何东西被发送。

问题源于以下function:

  public void sendNotification(Device device, PayLoad payload) 

似乎bufferedreader有NULL

  BufferedReader in = new BufferedReader(new InputStreamReader(this.socket.getInputStream() ) ); 

因此,当代码的这部分被击中时,它就会在无限循环中挂起

  logger.debug( "In: [" + in.readLine() + "]" ); 

此输出为[null]

那么之后就会执行循环:

  while ( ! this.socket.isInputShutdown() ) { while( in.ready() ) { logger.debug("ready now"); logger.debug(in.readLine()); System.out.println( this.socket.getInputStream().read() ); } } 

代码进入第一个while循环并等待BufferedReader进入准备就绪并等待…..广告是你挂

JavaPNS最近更新到2.0,并修复了所有报告的问题,直到发布日期。 它确实解决了您所描述的问题,并且使用该库比以往任何时候都简单得多(您现在可以通过一行代码推送通知)。

你似乎错过了令牌

 pushManager.addDevice("iPhone", "f4201f5d8278fe39545349d0868a24a3b60ed732"); 

进行id和token检查:

https://github.com/o-sam-o/javapns/blob/master/src/javapns/notification/PushNotificationManager.java#L501

获取令牌的唯一方法是从iPhone应用程序。 有效令牌如下所示:1d2d6f34 c5028bca c50df5f9 1992c912 ce7deae8 3bbe7da5 447f6a68 cfecdc0e