通过 Java 使用 Apple 推送通知服务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1355837/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Use Apple Push Notification Service through Java
提问by mw_javaguy
Am trying to implement a Java program which sends an Apple Push Notification to an iPhone client app... Found the following library: Java APNs
我正在尝试实现一个 Java 程序,该程序将 Apple 推送通知发送到 iPhone 客户端应用程序...找到以下库:Java APNs
Provider code:
供应商代码:
Created the following code (from Javapns) to use in my app:
创建了以下代码(来自 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);
}
When I run this app (as you can see through the Log4j statements) there's no exceptions which occur:
当我运行这个应用程序时(正如你可以通过 Log4j 语句看到的),没有发生任何异常:
WARN [MyCode] Initializing connectiong with APNS...
WARN [MyCode] Sending push notification...
But my client app doesn't receive any notifications!
但是我的客户端应用程序没有收到任何通知!
IDPP Registration Process:
IDPP注册流程:
Also, did the following on the iPhone Developer Program Portal (IDPP):
此外,在 iPhone 开发者计划门户 (IDPP) 上执行了以下操作:
Created the APNS based SSL Certificate and Keys
Created and installed the provisioning profile
Installed the SSL Certificate and Key on the server.
创建基于 APNS 的 SSL 证书和密钥
创建并安装配置文件
在服务器上安装 SSL 证书和密钥。
Have read over the Apple Push Notification Service Guide several times and noticed a few things:
已多次阅读 Apple 推送通知服务指南,并注意到以下几点:
(1) On page 15, it states that the device token is not the same as the device UDID (which I am currently incorrectly passing in as the second parameter inside the PushNotificationManager.addDevice() method (see above)).
(1) 在第 15 页上,它指出设备令牌与设备 UDID 不同(我目前错误地将其作为 PushNotificationManager.addDevice() 方法中的第二个参数传入(见上文))。
On page 17, it states:
在第 17 页,它指出:
"APNs generates a device token using information contained in the unique device certificate. The device token contains an identifier of the device. It then encrypts the device token with a token key and returns it to the device. The device returns the device token to the requesting application as an NSData object. The application then must deliver the device token to its provider in either binary or hexidecimal format."
“APNs 使用唯一设备证书中包含的信息生成设备令牌。设备令牌包含设备的标识符。然后它使用令牌密钥加密设备令牌并将其返回给设备。设备将设备令牌返回给设备请求应用程序作为 NSData 对象。然后应用程序必须以二进制或十六进制格式将设备令牌交付给其提供者。”
iPhone OS Client Implementation
iPhone OS 客户端实现
(2) After reading pages 33 - 34, I discovered that I didn't include the Objective-C code to have the app register with APNs.
(2) 阅读第 33 - 34 页后,我发现我没有包含 Objective-C 代码来让应用程序注册到 APNs。
Am not an Objective-C developer, so is this where I can recover the device code or do I have to get it from the certificate?
我不是 Objective-C 开发人员,所以我可以在这里恢复设备代码还是必须从证书中获取它?
Where do I obtain the device token (sorry, someone else wrote the Objective-C client app and I am a Java Developer)?
我从哪里获得设备令牌(抱歉,其他人编写了 Objective-C 客户端应用程序,而我是一名 Java 开发人员)?
Question(s):
问题):
(1) With the exception of not knowing where to get the device token and the mobile client code registration, is there anything else that I have not looked over or missed?
(1) 除了不知道从哪里获取device token和手机客户端注册码之外,还有什么是我没有看过或者错过的?
(2) Am I using the Javapns library the right way?
(2) 我是否以正确的方式使用 Javapns 库?
Thank you for taking the time to read this...
感谢您抽出时间来阅读...
采纳答案by ZaBlanc
Just a little tip, in order to convert your received token into a format suitable for registration with javapns, this code will do the trick:
只是一点提示,为了将您收到的令牌转换为适合使用 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;
}
}
回答by Sam
You seem to be missing the token
你似乎缺少令牌
pushManager.addDevice("iPhone", "f4201f5d8278fe39545349d0868a24a3b60ed732");
Takes id and token check:
接受 id 和 token 检查:
The only way to get a token is from the iphone app. A valid token looks something like this: 1d2d6f34 c5028bca c50df5f9 1992c912 ce7deae8 3bbe7da5 447f6a68 cfecdc0e
获取令牌的唯一方法是从 iphone 应用程序。一个有效的令牌看起来像这样: 1d2d6f34 c5028bca c50df5f9 1992c912 ce7deae8 3bbe7da5 447f6a68 cfecdc0e
回答by notnoop
Your Java code looks solid! However, don't forget to close the connection, through
PushNotificationManager.closeConnection()
. It's important to cleanup after yourself.As a side comment, I notice that you are adding the device 'iPhone' but querying for 'Lambo' afterwards. This is an indication of a bug.
The device token shown in the code is incorrect. Device tokens, currently, as 32-bit long value, which gets hexed into 64 characters. I assume that the server is failing silently when pushing the notification to invalid token!
The only way to get the device token is from the app itself. As provided by the Push Notification guidesuggests, the iPhone app needs to register for notification upon launch. In the
application:didRegisterForRemoteNotificationsWithDeviceToken:
, the iPhone needs to send the device token to your java provider server. (For debugging purposes, you can justNSLog
the device token and use it; it never changes across runs).I would recommend that you create a server in your java provider server to receive device tokens. Set up a
ServerSocket
to receive connections from the iPhone and their device token (and any additional info you need) and insert the tokens in the database.
您的 Java 代码看起来很可靠!但是,不要忘记关闭连接,通过
PushNotificationManager.closeConnection()
. 自己清理干净很重要。作为旁注,我注意到您正在添加设备“iPhone”,但随后查询“Lambo”。这是一个错误的迹象。
代码中显示的设备令牌不正确。设备令牌,目前为 32 位长值,十六进制为 64 个字符。我假设服务器在将通知推送到无效令牌时静默失败!
获取设备令牌的唯一方法是从应用程序本身。正如推送通知指南所提供的那样,iPhone 应用程序需要在启动时注册通知。在 中
application:didRegisterForRemoteNotificationsWithDeviceToken:
,iPhone 需要将设备令牌发送到您的 Java 提供程序服务器。(出于调试目的,您可以只NSLog
使用设备令牌并使用它;它在运行期间永远不会改变)。我建议您在 Java 提供程序服务器中创建一个服务器来接收设备令牌。设置 a
ServerSocket
以接收来自 iPhone 的连接及其设备令牌(以及您需要的任何其他信息)并将令牌插入数据库中。
回答by notnoop
As a shameful self-advertising, I encourage to use java-apns
library. Your code will look like:
作为可耻的自我宣传,我鼓励使用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);
回答by sergio
I tried this and I keep getting hanged when sending the notification, and nothing gets sent.
我试过这个,我在发送通知时一直被挂起,但没有发送任何内容。
The issue stems from the following function:
该问题源于以下功能:
public void sendNotification(Device device, PayLoad payload)
It seems that the bufferedreader has NULL
似乎bufferedreader有NULL
BufferedReader in =
new BufferedReader(new InputStreamReader(this.socket.getInputStream() ) );
So when this portion of the code gets hit it just hangs there in endless loop
所以当这部分代码被击中时,它就会无限循环地挂在那里
logger.debug( "In: [" + in.readLine() + "]" );
This output is [null]
此输出为 [null]
So then right after then the loops get executed:
然后紧接着循环被执行:
while ( ! this.socket.isInputShutdown() ) {
while( in.ready() ) {
logger.debug("ready now");
logger.debug(in.readLine());
System.out.println( this.socket.getInputStream().read() );
}
}
The code enters the first while loop and waits for the BufferedReader in to be ready and just keeps waiting..... ad that is your hanging
代码进入第一个 while 循环并等待 BufferedReader 准备就绪,然后继续等待.....
回答by Sylvain P.
JavaPNS was recently updated to 2.0, and fixed ALL reported issues up to the release date. It does fix the issue you are describing, and using the library is MUCH simpler than it ever was (you can push a notification with a single line of code now).
JavaPNS 最近更新到 2.0,并修复了截至发布日期的所有报告问题。它确实解决了您所描述的问题,并且使用该库比以往任何时候都简单得多(您现在可以使用一行代码推送通知)。