All Downloads are FREE. Search and download functionalities are using the official Maven repository.

co.fingerprintsoft.notification.apns.APNSSender Maven / Gradle / Ivy

The newest version!
package co.fingerprintsoft.notification.apns;


import co.fingerprintsoft.notification.NotificationResult;
import co.fingerprintsoft.notification.PushNotificationSender;
import com.relayrides.pushy.apns.ApnsClient;
import com.relayrides.pushy.apns.ClientNotConnectedException;
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;
import lombok.Data;
import lombok.ToString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutionException;

/**
 * Parent class of ProductionAPNSService and SandboxAPNSService.
 * Setups the push manager for push notifications for apple devices.
 * The environment to which to connect to apples servers is determined by the sub class
 * PushManager comes from the pushy plugin which can be found at
 * RelayRides Pushy
 */
public class APNSSender implements PushNotificationSender {

    private static final Logger LOG = LoggerFactory.getLogger(APNSSender.class);

    private APNSSettings apnsSettings;
    private ApnsClient apnsClient;

    public APNSSender(APNSSettings apnsSettings, ApnsClient apnsClient) {
        this.apnsSettings = apnsSettings;
        this.apnsClient = apnsClient;
    }

    @Override
    public NotificationResult sendNotification(String alertBody, String deviceToken) {
        return new APNSNotificationResult(send(alertBody, deviceToken));
    }

    private String send(String alertBody, String deviceToken) {
        Future connectFuture;

        synchronized (apnsClient) {
            if (!apnsClient.isConnected()) {
                if (apnsSettings.isSandboxed()) {
                    connectFuture = apnsClient.connect(ApnsClient.DEVELOPMENT_APNS_HOST);
                } else {
                    connectFuture = apnsClient.connect(ApnsClient.PRODUCTION_APNS_HOST);
                }
                try {
                    connectFuture.await();
                } catch (InterruptedException e) {
                    LOG.error("Could not connect", e);
                    return "Could not connect";
                }
            }
        }

        final SimpleApnsPushNotification pushNotification;

        {
            final ApnsPayloadBuilder payloadBuilder = new ApnsPayloadBuilder();
            payloadBuilder.setAlertBody(alertBody);
            payloadBuilder.setAlertTitle("Forex Notification"); // this is only used for the Apple Smart Watch
            payloadBuilder.setAlertBody(alertBody);
            payloadBuilder.setBadgeNumber(1);
            payloadBuilder.setSoundFileName("ring-ring.aiff"); // notification sound to play

            final String payload = payloadBuilder.buildWithDefaultMaximumLength();
            final String token = TokenUtil.sanitizeTokenString(deviceToken);

            pushNotification = new SimpleApnsPushNotification(token, "co.za.albaraka.forex.abb-fx-requestor", payload);
        }

        try {
            String result = getResponse(pushNotification);
            if (result != null) return result;
        } catch (final ExecutionException e) {
            LOG.error("Failed to send push notification.", e);
            if (e.getCause() instanceof ClientNotConnectedException) {
                LOG.debug("Waiting for client to reconnect…");
                try {
                    apnsClient.getReconnectionFuture().await();
                    LOG.debug("Reconnected.");
                } catch (InterruptedException e1) {
                    LOG.error("Could not reconnect", e1);
                }
                try {
                    String result = getResponse(pushNotification);
                    if (result != null) return result;
                } catch (ExecutionException | InterruptedException re) {
                    LOG.error("Failed retrying to send push notification.", re);
                }
            }
        } catch (InterruptedException e) {
            LOG.error("Could not send", e);
        }
        return "Error Occurred please check the logs";
    }

    private String getResponse(SimpleApnsPushNotification pushNotification) throws InterruptedException, ExecutionException {
        final PushNotificationResponse pushNotificationResponse =
                apnsClient.sendNotification(pushNotification).get();

        if (pushNotificationResponse.isAccepted()) {
            LOG.debug("Push notification accepted by APNs gateway.");
            return "Push notification accepted by APNs gateway.";
        }
        LOG.error("Notification rejected by the APNs gateway: {}", pushNotificationResponse.getRejectionReason());
        String result = String.format("Notification rejected by the APNs gateway: %s", pushNotificationResponse.getRejectionReason());
        if (pushNotificationResponse.getTokenInvalidationTimestamp() != null) {
            LOG.error("\t…and the token is invalid as of {}", pushNotificationResponse.getTokenInvalidationTimestamp());
            result += String.format("\t…and the token is invalid as of {}", pushNotificationResponse.getTokenInvalidationTimestamp());
        }
        return result;
    }

    @Data
    @ToString(callSuper = true)
    class APNSNotificationResult implements NotificationResult {
        private String result;
        public APNSNotificationResult(String result) {
            this.result = result;
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy