Safari Notifications not getting delivered using Pushy Library

259 views
Skip to first unread message

Jai Vaswani

unread,
Jun 9, 2017, 3:50:18 AM6/9/17
to pushy
Hi,
I am using Pushy 0.9.3 for sending Push Notifications.
For sending push notification to IPhone device it is absolutely working fine. But, Safari the notifications on Mac are not getting delivered.
Although the code prints success while sending push notification on Safari, it is never delivered.

To cross check if the inputs were correct, I  tried using php-apns library and the safari notifications were delivered on my Mac.


I went through this issue  where someone tried the same and in the comments it was mentioned -
@jchambers
Contributor

jchambers commented on Dec 6 2016

Connecting to api.push.apple.com works fine, but apnsClient.connect("gateway.push.apple.com", 2195) I want to use Pushy for sending safari notification gives the following exception.

gateway.push.apple.com is the old binary-streaming server and does not support HTTP/2.


Also at developer.apple  it is mentioned -

Pushing Notifications

You send push notifications to clients in the same way that iOS and OS X apps push notifications to APNs. As a push notification provider, you communicate with APNs over a binary interface. This a high-speed, high-capacity interface uses a streaming TCP socket design with binary content. The binary interface is asynchronous.

../Art/safari_notifs_2_2x.png

The binary interface of the production environment is available through gateway.push.apple.com, port 2195. Do not connect to the development environment to send Safari Push Notifications. You may establish multiple parallel connections to the same gateway or to multiple gateway instances.



My concern is how do I use Pushy Library to Send Safari Notification ? Does Pushy Library really support sending Safari Notifications ?
If not, any other alternative library or working java code would be a great help.

Thanks.





import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.Principal;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import javax.net.ssl.SSLException;

import com.relayrides.pushy.apns.ApnsClient;
import com.relayrides.pushy.apns.ApnsClientBuilder;
import com.relayrides.pushy.apns.ClientNotConnectedException;
import com.relayrides.pushy.apns.DeliveryPriority;
import com.relayrides.pushy.apns.PushNotificationResponse;
import com.relayrides.pushy.apns.util.ApnsPayloadBuilder;
import com.relayrides.pushy.apns.util.SimpleApnsPushNotification;
import com.relayrides.pushy.apns.util.TokenUtil;

import io.netty.util.concurrent.Future;

public class TestSafariPush {
   
public static String p12path = "/tmp/WebPushDist.p12";
   
public static String p12pass = "123456";
           
   
private String getTopicName(String p12Path, String p12Pass) throws Exception {
       
KeyStore p12 = KeyStore.getInstance("pkcs12");
        p12
.load(new FileInputStream(p12Path), p12Pass.toCharArray());
       
Enumeration e = p12.aliases();
       
Map<String,String> subjectMap = new HashMap<String,String>();
       
while (e.hasMoreElements()) {
           
String alias = (String) e.nextElement();
            X509Certificate c
= (X509Certificate) p12.getCertificate(alias);
           
Principal subject = c.getSubjectDN();
           
String subjectArray[] = subject.toString().split(",");
           
for (String s : subjectArray) {
               
String[] str = s.trim().split("=");
                subjectMap
.put(str[0], str[1]);
           
}
       
}
       
return subjectMap.get("UID");
   
}
   
   
private Date getInvalidationDatetime(int ttl){
       
long ttlmillisecs = System.currentTimeMillis() + (ttl * 1000);
       
Calendar calendar = Calendar.getInstance();
        calendar
.setTimeInMillis(ttlmillisecs);
       
return calendar.getTime();
   
}
   
   
private ApnsClient getClient() throws SSLException, IOException, InterruptedException{
       
final ApnsClient apnsClient = new ApnsClientBuilder().setClientCredentials(new File(p12path), p12pass).build();
       
final Future<Void> connectFuture = apnsClient.connect(ApnsClient.PRODUCTION_APNS_HOST);
        connectFuture
.await();
       
return apnsClient;
   
}
   
   
   
   
   
public void sendSingleMessage(String title, String message, int ttl, String collapseKey, String topic, String token) throws IOException, InterruptedException {
       
       
try {
           
ApnsClient apnsClient = getClient();
           
final ApnsPayloadBuilder payloadBuilder = new ApnsPayloadBuilder();
            payloadBuilder
.setAlertBody(message);
            payloadBuilder
.setAlertTitle(title);
            payloadBuilder
.setActionButtonLabel("view");
           
           
           
final String payload = payloadBuilder.buildWithDefaultMaximumLength();
            token
= TokenUtil.sanitizeTokenString(token);
           
           
Date invalidationTime = getInvalidationDatetime(ttl);
           
           
final SimpleApnsPushNotification pushNotification = new SimpleApnsPushNotification(token, topic, payload, invalidationTime, DeliveryPriority.IMMEDIATE, collapseKey);
           
final Future<PushNotificationResponse<SimpleApnsPushNotification>> sendNotificationFuture = apnsClient.sendNotification(pushNotification);
           
try {
               
final PushNotificationResponse<SimpleApnsPushNotification> pushNotificationResponse = sendNotificationFuture.get();
               
if (pushNotificationResponse.isAccepted()) {
                   
System.out.println("APNS Send SingleMessage Success : ");
               
} else {
                   
System.out.println("APNS Send SingleMessage Failed : " + pushNotificationResponse.getRejectionReason() + " : ");
                   
if (pushNotificationResponse.getTokenInvalidationTimestamp() != null) {
                       
System.out.println("Token is invalid as of "+ pushNotificationResponse.getTokenInvalidationTimestamp());
                   
}
               
}
           
} catch (final ExecutionException e) {
               
if (e.getCause() instanceof ClientNotConnectedException) {
                   
System.out.println("Waiting for client to reconnect…");
                    apnsClient
.getReconnectionFuture().await();
                   
System.out.println("Reconnected.");
               
}
           
}
       
} catch (Exception e) {
           
System.out.println("Some Error");
       
}
   
}
   
   
   
public static void main(String args[]){
       
       
TestSafariPush test = new TestSafariPush();
       
String token = "4B304B43A406DDBA912CAB3EE9982478793C4D51CC8AADF289BFCD5D0AFE89F3";
       
String topic;
       
try {
            topic
= test.getTopicName(p12path, p12pass);
            test
.sendSingleMessage("Hi Jai", "Make It Happen", 100, "1", topic, token);
       
} catch (Exception e) {
           
// TODO Auto-generated catch block
            e
.printStackTrace();
       
}
       
       
       
   
}
   
}



Kenneth Key

unread,
Jun 9, 2017, 3:34:01 PM6/9/17
to pushy
Pushy went to the HTTP/2 interface for APNS in 0.5 so you will need to drop back, I believe, to 0.4.3 for binary interface support.  My head explodes that Safari push is not available via the much better HTTP/2 protocol.  Although reading through the safari push doc, Apple dealt with the crappy error reporting on the binary interface with a log-back interface to the web server.

Best of luck,
K^2

Jon Chambers

unread,
Jun 9, 2017, 3:41:01 PM6/9/17
to Kenneth Key, pushy
Are you certain that the HTTP/2 API won't deliver Safari push notifications? My understanding is that is *should* work, and maybe the docs are a little outdated. I'm reasonably confident other users have had success with the HTTP/2 API; can anybody on the list confirm that's the case?

-Jon

--
Pushy is an open-source Java library for sending APNs (iOS and OS X) push notifications. Pushy is brought to you by the engineers at RelayRides.
---
You received this message because you are subscribed to the Google Groups "pushy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pushy-apns+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jai Vaswani

unread,
Jun 13, 2017, 9:27:40 AM6/13/17
to pushy
Thanks a lot Kenneth.
I am able to send Safari notifications via Pushy 0.4.3 and they are successfully delivered.
The only problem that I faced is the payload creation. payloadBuilder.setAlertTitle("Title") doesn't add the title inside the payload and also there is no provision for adding url-args.
I managed to create the desired payload string and it works fine for me.

Jai Vaswani

unread,
Jun 13, 2017, 9:55:03 AM6/13/17
to pushy, ken...@gmail.com
Yes I am pretty sure that Safari notifications are delivered only through binary interface. It works using Pushy 0.4.3 but doesn't works with 0.9.3 .
Can't we have support for the old binary interface in the upcoming versions??
As I am already using 0.9.3 for sending IOS notifications in my application, Now I will have to create a separate application for sending Safari notifications through 0.4.3 .
To unsubscribe from this group and stop receiving emails from it, send an email to pushy-apns+...@googlegroups.com.

Jon Chambers

unread,
Jul 11, 2017, 9:14:19 AM7/11/17
to Jai Vaswani, pushy, Kenneth Key
Yes I am pretty sure that Safari notifications are delivered only through binary interface. It works using Pushy 0.4.3 but doesn't works with 0.9.3 .

Folks, I've received confirmation that Safari push notifications SHOULD work via the HTTP/2 APNs API. Further, I've received confirmation that the Safari push notification docs are simply out of date.

Hope that helps!

-Jon
Reply all
Reply to author
Forward
0 new messages