通过 Java 使用 Apple 推送通知服务
-
20-09-2019 - |
题
我正在尝试实现一个 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 对象返回给请求应用程序。然后,应用程序必须以二进制或十六进制格式将设备令牌传递给其提供者。”
iPhone操作系统客户端实现
(2) 阅读第 33 - 34 页后,我发现我没有包含让应用程序向 APN 注册的 Objective-C 代码。
我不是 Objective-C 开发人员,那么这是我可以恢复设备代码的地方还是我必须从证书中获取它?
我在哪里获取设备令牌(抱歉,其他人编写了 Objective-C 客户端应用程序,而我是 Java 开发人员)?
问题):
(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);
你的 Java 代码看起来很可靠!但是,不要忘记关闭连接,通过
PushNotificationManager.closeConnection()
. 。事后清理很重要。作为附带评论,我注意到您正在添加设备“iPhone”,但随后查询“Lambo”。这是一个错误的迹象。
代码中显示的设备令牌不正确。设备令牌目前为 32 位长值,十六进制为 64 个字符。我认为当将通知推送到无效令牌时,服务器会默默地失败!
获取设备令牌的唯一方法是从应用程序本身。据提供 推送通知指南 建议,iPhone 应用程序需要在启动时注册通知。在里面
application:didRegisterForRemoteNotificationsWithDeviceToken:
, ,iPhone需要将设备令牌发送到您的java提供商服务器。(出于调试目的,您可以NSLog
设备令牌并使用它;它在运行过程中永远不会改变)。我建议您在 java 提供程序服务器中创建一个服务器来接收设备令牌。设置一个
ServerSocket
接收来自 iPhone 的连接及其设备令牌(以及您需要的任何其他信息)并将令牌插入数据库中。
我尝试了这个,但在发送通知时我一直被挂起,并且没有发送任何内容。
该问题源于以下函数:
public void sendNotification(Device device, PayLoad payload)
看来bufferedreader有NULL
BufferedReader in =
new BufferedReader(new InputStreamReader(this.socket.getInputStream() ) );
因此,当这部分代码被击中时,它就会挂在那里,陷入无限循环
logger.debug( "In: [" + in.readLine() + "]" );
该输出是[空]
那么紧接着循环就会被执行:
while ( ! this.socket.isInputShutdown() ) {
while( in.ready() ) {
logger.debug("ready now");
logger.debug(in.readLine());
System.out.println( this.socket.getInputStream().read() );
}
}
该代码进入第一个循环时进入第一个,并等待BufferedReader准备就绪,并保持等待.....那是你悬挂的广告
JavaPNS 最近更新至 2.0,并修复了截至发布日期报告的所有问题。它确实解决了您所描述的问题,并且使用该库比以往任何时候都简单得多(您现在可以使用一行代码推送通知)。
您似乎缺少令牌
pushManager.addDevice("iPhone", "f4201f5d8278fe39545349d0868a24a3b60ed732");
进行 id 和 token 检查:
获取令牌的唯一方法是通过 iPhone 应用程序。有效的令牌看起来像这样:1d2d6f34 c5028bca c50df5f9 1992c912 ce7deae8 3bbe7da5 447f6a68 cfecdc0e