【问题标题】:Use Apple Push Notification Service through Java通过 Java 使用 Apple 推送通知服务
【发布时间】:2010-11-24 06:12:57
【问题描述】:

我正在尝试实现一个向 iPhone 客户端应用程序发送 Apple 推送通知的 Java 程序...找到以下库:Java APNs

提供者代码:

创建了以下代码(来自 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 Push Notification Service Guide 并注意到一些事情:

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

在第 17 页,它指出:

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

iPhone 操作系统客户端实现

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

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

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

问题:

(1) 除了不知道从哪里获取设备令牌和移动客户端代码注册之外,还有什么我没有看过或错过的吗?

(2) 我是否以正确的方式使用 Javapns 库?

感谢您抽出宝贵时间阅读本文...

【问题讨论】:

  • DeviceID和Device token一样吗?

标签: java apple-push-notifications


【解决方案1】:

您似乎缺少令牌

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

【解决方案2】:

我试过这个,发送通知时一直被挂起,什么都没有发送。

问题源于以下功能:

         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 in准备好 并且一直在等待.....广告就是你的悬垂

【讨论】:

【解决方案3】:

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

【讨论】:

  • 您能否粘贴代码以支持您的回答?在我的情况下,我没有收到任何错误,也没有通知。请帮忙
  • 这里是:Push.alert("Hello World!", "keystore.p12", "keystore_password", false, "Your token");一切都很好地记录在项目的 wiki 上的 Google 代码中。有基本的和高级的代码示例。
  • @Syslvain P. 如果我可以使用此库为 APNS 有效负载发送 apns-push-type 标头,您能否指导我,这在 iOS13 中是必需的?我的问题:stackoverflow.com/questions/61278008/…
【解决方案4】:

作为可耻的自我广告,我鼓励使用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);

【讨论】:

  • 需要注意的是他的 deviceToken 也是错误的,对吧?这看起来像一个 [[UIDevice currentDevice] uniqueIdentifier],但 java apns 类希望将二进制设备令牌转换为 64 个字符的十六进制字符串。
  • 好的,太好了。只要我将 deviceToken 替换为由类似于 ZaBlanc 的代码生成的完整 64 字符十六进制字符串,我就能够获得您在上面粘贴的确切代码。顺便说一句,很棒的图书馆!
  • @Nate。谢谢,请加入 google 小组并影响图书馆的发展。
  • 嗨。我检查了这个..但在这种情况下默认声音不起作用。
  • @notnoop,上面的代码适用于将单个有效负载推送到一个或多个设备。如果我们需要基于 Web 服务调用重复执行此操作,那么每次都创建 apnsservice 不会很好。有没有办法尽可能长时间地保持这个连接打开?我没有看到任何打开或关闭的连接。它什么时候发生。请指导我。
【解决方案5】:

只是一个小提示,为了将您收到的令牌转换为适合使用 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 还需要这个吗?
【解决方案6】:
  1. 您的 Java 代码看起来很可靠!但是,不要忘记通过PushNotificationManager.closeConnection() 关闭连接。自己清理很重要。

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

  2. 代码中显示的设备令牌不正确。设备令牌,目前,作为 32 位长值,被十六进制转换为 64 个字符。我假设在将通知推送到无效令牌时服务器会静默失败!

  3. 获取设备令牌的唯一方法是从应用程序本身。正如Push Notification guide 所提供的建议,iPhone 应用程序需要在启动时注册以获得通知。在application:didRegisterForRemoteNotificationsWithDeviceToken: 中,iPhone 需要将设备令牌发送到您的 java 提供程序服务器。 (出于调试目的,您可以只NSLog 设备令牌并使用它;它永远不会随着运行而改变)。

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

【讨论】:

猜你喜欢
  • 2017-11-18
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多