Hello, this weekend we had an event and the opportunity to send out >2700 pushes at time and would love to share our wrapping class around this very good project lib 1.6.1: this class resume the sending of the token chain list where it stopped. It may not be the best code, but it works great. Cheers Lorenzo
package com.cryms.push.frontend; import java.io.InputStream; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import com.notnoop.apns.APNS; import com.notnoop.apns.ApnsDelegate; import com.notnoop.apns.ApnsNotification; import com.notnoop.apns.ApnsService; import com.notnoop.apns.ApnsServiceBuilder; import com.notnoop.apns.DeliveryError; import com.notnoop.apns.internal.Utilities; public class APNSender implements ApnsDelegate, Runnable{ private ArrayList clients = null; private String simplePayload; private ApnsService service; private ApnsServiceBuilder builder; private ArrayList sendingList = null; private ArrayList problematicList = new ArrayList(); private PrintWriter out; private int errorAt = 0; private Thread t = null; public APNSender(ArrayList clients, String message, String sound, int badge, boolean production, InputStream cert, String certPasswd, PrintWriter out) { this.clients = clients; this.out = out; simplePayload = APNS.newPayload().alertBody(message).badge(badge).sound(sound).build(); if(production){ builder = APNS.newService().withCert(cert,certPasswd).withProductionDestination().withDelegate(this); }else{ builder = APNS.newService().withCert(cert,certPasswd).withSandboxDestination().withDelegate(this); } service = builder.build(); } public APNSender(ArrayList clients, String message, String sound, int badge, boolean production, String certfile, String certPasswd, PrintWriter out) { this.clients = clients; this.out = out; simplePayload = APNS.newPayload().alertBody(message).badge(badge).sound(sound).build(); if(production){ builder = APNS.newService().withCert(certfile,certPasswd).withProductionDestination().withDelegate(this); }else{ builder = APNS.newService().withCert(certfile,certPasswd).withSandboxDestination().withDelegate(this); } service = builder.build(); } public void send(boolean andWait) throws InterruptedException{ this.t = new Thread(this); this.t.start(); if(andWait){ out.println("waiting for process to finish..."); t.join(); } } /** * @param args */ public static void main(String[] args) { ArrayList clients = new ArrayList(); clients.add("goodtoken1"); clients.add("badtoken1"); clients.add("badtoken2"); clients.add("goodtoken2"); clients.add("badtoken3"); APNSender pt = new APNSender(clients, "Messagge", "default", 0, false, "./PushDev.p12", "password", new PrintWriter(System.out)); System.out.println("Start..."); try { pt.send(true); } catch (InterruptedException e) { e.printStackTrace(); } for(String token:pt.getProblematicList()){ System.out.println("Had problem on:"+token); } System.out.println("End!"); } @SuppressWarnings("unchecked") @Override public void run() { out.println("Sending "+clients.size()+" messages"); out.flush(); while(clients.size()>0){ sendingList = (ArrayList)clients.clone(); service.push(sendingList, simplePayload); try { // TODO would love to have a service.join(3000) to wait for monitor to finish with timeout out.println("sleep 3s waiting monitor"); out.flush(); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } if(errorAt>0){ List sublist = clients.subList(0, errorAt); for(int i=0;i0){ out.println("Retry sending last "+clients.size()+" messages"); service.stop(); service = builder.build(); }else{ out.println("No more messages to send"); service.stop(); } out.flush(); errorAt=0; }else{ // this call make the connection monitor throw an exception since is still waiting for an error from apple. It's anyway correct. for(int i=0;i inactive = service.getInactiveDevices(); for(String id:inactive.keySet()){ problematicList.add(id); out.println("inactive "+id+" "+inactive.get(id)); } out.flush(); } @Override public void connectionClosed(DeliveryError e, int nth) { //break the sending at nth-1 element of this.clients list String token = sendingList.get(nth-1); out.println("connectionClosed code:"+e+" id:"+nth+" token:"+token); problematicList.add(token); errorAt = nth; out.flush(); } @Override public void messageSendFailed(ApnsNotification message, Throwable e) { String token = Utilities.encodeHex(message.getDeviceToken()); problematicList.add(token); out.println("messageSendFailed token:"+(token)+" err:"+e); e.printStackTrace(out); out.flush(); } @Override public void messageSent(ApnsNotification message) { // this method is always called, even if the message is not being really sent...not really useful } public ArrayList getProblematicList() { return problematicList; } }