mwkirk / javapns

Test import of svn javapns repo from Google Code
3 stars 0 forks source link

how to use response and feedback ? #79

Closed mwkirk closed 11 years ago

mwkirk commented 11 years ago

Original author: wangyana...@gmail.com (November 04, 2011 01:17:16)

I used javapns like this:

public static void main(String args[]) {

    List<PushedNotification> notifications = Push.combined("message+badge+sound", 1, "default", 
            "apns-key+cert-exported-from-mac.p12", "hadoop", 
            false, 
            "cef981xxxxbxxxxxad5bd880");

    ResponsePacket response=null;
    for (PushedNotification notification : notifications) {
        response = notification.getResponse();
        if(response!=null)
        {
            response.getMessage();
            System.out.println(response.getMessage());
        }
        if (notification.isSuccessful()) {
                /* Apple accepted the notification and should deliver it */  
                System.out.println("Push notification sent successfully to: " +
                                                notification.getDevice().getToken());
                /* Still need to query the Feedback Service regularly */  
        } else {
                String invalidToken = notification.getDevice().getToken();
                /* Add code here to remove invalidToken from your database */  
        }
}
    List<Device> devList = Push.feedback("apns-key+cert-exported-from-mac.p12", "hadoop", false);
    for(Device basicDevice: devList)
    {
        System.out.println(basicDevice.getToken());
        System.out.println(basicDevice.getDeviceId());
    }
    System.out.println("end push");

}

The notification was pushed to my iphone successfully. But I always get a null response, leading to a null pointer exception. So , what is the right way to use response?

Original issue: http://code.google.com/p/javapns/issues/detail?id=79

mwkirk commented 11 years ago

From sype...@gmail.com on November 04, 2011 01:54:10 A ResponsePacket will only be attached if an actual error response packet was received from the server. If no error occurred, there won't be any response packet attached. The isSuccessful() method will return true if no error response packet was received, so there shouldn't be any need to get the response packet itself.

If you are getting a NullPointerException from the library though, please provide a stack trace so the issue can be investigated.

mwkirk commented 11 years ago

From wangyana...@gmail.com on November 04, 2011 02:00:13 Thank you for your answering. The null pointer exception is caused by the null response :) Is it that only a enhanced notification will get a respose? How to send a enhanced notification? Thank you very much!

mwkirk commented 11 years ago

From wangyana...@gmail.com on November 04, 2011 02:33:35 And I have removed the application on the iphone, but I still can't get a error response(it is always null). please help me. thank you!

mwkirk commented 11 years ago

From sype...@gmail.com on November 04, 2011 04:59:39 JavaPNS always uses the enhanced notification format.

Please provide a full stack trace for your exception. Without it, I don't understand where you're getting it from exactly in your code.

mwkirk commented 11 years ago

From wangyana...@gmail.com on November 04, 2011 05:12:29 this is all the console output: log4j:WARN No appenders could be found for logger (javapns.devices.DeviceFactory). log4j:WARN Please initialize the log4j system properly. log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. Exception in thread "main" java.lang.NullPointerException at javaApnsTest.main(javaApnsTest.java:37)

here is the source code:

public static void main(String args[]) throws JSONException {

    PushNotificationPayload payload = new PushNotificationPayload("message+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+soundmessage+badge+sound", 1, "default");
    payload.setExpiry(1);
    List<PushedNotification> notifications = Push.payload(payload, "apns-key+cert-exported-from-mac.p12", "hadoop", 
            false, 
            "cef981279b88xxxxxxxxxxxxxxxx0679ad5bd880"); //for privacy
    ResponsePacket response=null;
    for (PushedNotification notification : notifications) {
        response = notification.getResponse();

        {
            response.getMessage();
            System.out.println(response.getMessage());
        }
        if (notification.isSuccessful()) {
                /* Apple accepted the notification and should deliver it */  
                System.out.println("Push notification sent successfully to: " +
                                                notification.getDevice().getToken());
                /* Still need to query the Feedback Service regularly */  
        } else {
                String invalidToken = notification.getDevice().getToken();
                /* Add code here to remove invalidToken from your database */  
        }
}
    List<Device> devList = Push.feedback("apns-key+cert-exported-from-mac.p12", "hadoop", false);
    for(Device basicDevice: devList)
    {
        System.out.println(basicDevice.getToken());
        System.out.println(basicDevice.getDeviceId());
    }
    System.out.println("end push");

}

thanks again!

mwkirk commented 11 years ago

From sype...@gmail.com on November 04, 2011 05:15:33 Well, the code you just pasted is different from the one you provided initially. The "if(response!=null)" condition is missing, so if response is null (which it will always be if no error occurs), your code will indeed throw a NullPointerException. If you put back the condition like you had before, your code will work fine.

mwkirk commented 11 years ago

From wangyana...@gmail.com on November 04, 2011 05:22:51 yes, I removed the "if(response!=null)" statement just to show you the exception I initially said about. But I didn't get a non-null response still even when I have removed the client application from my phone and I have send a invalid payload which is too long as in the later code. I want to get a error response to show it to my team leader, but I can't get it. this is the problem. thank you for your patience!

mwkirk commented 11 years ago

From sype...@gmail.com on November 04, 2011 05:40:23 Ok, I understand a little bit more what you are trying to accomplish (get an actual error-response packet). However, your attempts are not even making it to the transmission phase because the library has safeguards against malformed tokens, payload size, etc. It would be quite inefficient to let Apple servers throw errors for these kinds of basic specs violations while the library can do basic validations first. So, what's happening in your case is that the library is detecting your oversize payload and is rejecting it without even trying to send it to Apple servers. The "isSuccessful()" method returning false does hint at an error, but your errors are not reported by Apple (as error response packets), they are reported as exceptions, which you can get using "getException()" on the PushedNotification object.

Had you enabled logging as stated on the "Troubleshooting" wiki page here, you would have seen a nice exception in your log output that would have explained that your payload was rejected by the library.

If you want to get an error response packet from Apple, try pushing a proper payload to a 64-bytes device token that does not exist. Since it is 64 bytes long, the library will accept it, and Apple will return an error-response packet because it will find that the token does not correspond to a valid device. I just ran your code with a cut-down payload and an invalid 64-bytes token, and I got a nice error-response packet as expected.

mwkirk commented 11 years ago

From wangyana...@gmail.com on November 04, 2011 05:57:29 yes, I have got a error-response packet using the method that you told me. I want to check the state of the notifications, like a pending or failing to deliver state. How should I do that? Is the code under enough? List devList = Push.feedback("apns-key+cert-exported-from-mac.p12", "hadoop", false); for(Device basicDevice: devList) { System.out.println(basicDevice.getToken()); System.out.println(basicDevice.getDeviceId()); } Or should wait for some time to excute the Push.feedback method? I'm really a freshmen to java. Thanks a lot for your patience!

mwkirk commented 11 years ago

From sype...@gmail.com on November 04, 2011 06:05:55 The purpose of the Feedback Service is not to check on the status of a notification delivery. It is simply to get a list of device tokens which should no longer be used by your provider. But the how and when a device gets listed there is entirely up to Apple and to a lot of undocumented technical reasons. You should query the Feedback Service from time to time to cleanup your own list of device tokens, but that is all it is useful for.

There's a lot of useful information in the Wiki on this site (including more detailed information about what I just wrote about), so I would strongly suggest you read the entire wiki before going any further. This will probably save you a lot of time by understanding what you can and cannot do with Apple's Push Notification Service.

mwkirk commented 11 years ago

From wangyana...@gmail.com on November 04, 2011 06:10:04 OK. That's very kind of you to answer my questions and I will read the wiki more. Thank you very much again!

mwkirk commented 11 years ago

From sype...@gmail.com on November 04, 2011 06:11:28 My pleasure!