/** * Sends APNs notifications ({@link UnifiedPushMessage}) to all devices, that are represented by * the {@link Collection} of tokens for the given {@link iOSVariant}. * * @param iOSVariant the logical construct, needed to lookup the certificate and the passphrase. * @param tokens collection of tokens, representing actual iOS devices * @param pushMessage the payload to be submitted */ public void sendPushMessage( iOSVariant iOSVariant, Collection<String> tokens, UnifiedPushMessage pushMessage) { // no need to send empty list if (tokens.isEmpty()) { return; } PayloadBuilder builder = APNS.newPayload() // adding recognized key values .alertBody(pushMessage.getAlert()) // alert dialog, in iOS .badge(pushMessage.getBadge()) // little badge icon update; .sound(pushMessage.getSound()); // sound to be played by app // apply the 'content-available:1' value: if (pushMessage.isContentAvailable()) { // content-available:1 is (with iOS7) not only used // Newsstand, however 'notnoop' names it this way (legacy)... builder = builder.forNewsstand(); } builder = builder.customFields(pushMessage.getData()); // adding other (submitted) fields final String apnsMessage = builder.build(); // build the JSON payload, for APNs ApnsService service = buildApnsService(iOSVariant); if (service != null) { try { logger.fine(String.format("Sending transformed APNs payload: '%s' ", apnsMessage)); // send: service.start(); Date expireDate = createFutureDateBasedOnTTL(pushMessage.getTimeToLive()); service.push(tokens, apnsMessage, expireDate); // after sending, let's ask for the inactive tokens: final Set<String> inactiveTokens = service.getInactiveDevices().keySet(); // transform the tokens to be all lower-case: final Set<String> transformedTokens = lowerCaseAllTokens(inactiveTokens); // trigger asynchronous deletion: clientInstallationService.removeInstallationsForVariantByDeviceTokens( iOSVariant.getVariantID(), transformedTokens); } catch (RuntimeException e) { logger.log(Level.SEVERE, "Error sending messages to APN server", e); } finally { // tear down and release resources: service.stop(); } } else { logger.severe("No certificate was found. Could not send messages to APNs"); } }