public class ApnsClient extends Object
An APNs client sends push notifications to the APNs gateway. Clients authenticate themselves to APNs servers in one of two ways: they may either present a TLS certificate to the server at connection time, or they may present authentication tokens for each notification they send. Clients that opt to use TLS-based authentication may send notifications to any topic named in the client certificate. Clients that opt to use token-based authentication may send notifications to any topic for which they have a signing key. Please see Apple's Local and Remote Notification Programming Guide for a detailed discussion of the APNs protocol, topics, and certificate/key provisioning.
Clients are constructed using an ApnsClientBuilder
. To use TLS-based client authentication, callers may
provide a certificate provisioned by Apple and its accompanying private key at construction time. The certificate and
key will be used to authenticate the client and identify the topics to which it can send notifications. Callers may
optionally specify an EventLoopGroup
when constructing a new client. If no event loop group is specified,
clients will create and manage their own single-thread event loop group. If many clients are operating in parallel,
specifying a shared event loop group serves as a mechanism to keep the total number of threads in check. Callers may
also want to provide a specific event loop group to take advantage of platform-specific features (i.e.
epoll
).
If callers do not provide a certificate/private key at construction time, the client will use token-based
authentication. Callers must register signing keys for the topics to which the client will send notifications using
one of the registerSigningKey
methods.
Once a client has been constructed, it must connect to an APNs server before it can begin sending push
notifications. Apple provides a production and development gateway; see PRODUCTION_APNS_HOST
and
DEVELOPMENT_APNS_HOST
. See the
Communicating
with APNs documentation for additional details.
Once a connection has been established, an APNs client will attempt to restore that connection automatically if
the connection closes unexpectedly. APNs clients employ an exponential back-off strategy to manage the rate of
reconnection attempts. Clients will stop trying to reconnect automatically if disconnected via the
disconnect()
method.
Notifications sent by a client to an APNs server are sent asynchronously. A
io.netty.util.concurrent.Future
is returned immediately when a notification
is sent, but will not complete until the attempt to send the notification has failed, the notification has been
accepted by the APNs server, or the notification has been rejected by the APNs server. Please note that the
Future
returned is a io.netty.util.concurrent.Future
, which is an extension of the
java.util.concurrent.Future
interface that allows callers to attach listeners
that will be notified when the Future
completes.
APNs clients are intended to be long-lived, persistent resources. Callers should shut them down when they are no longer needed (i.e. when shutting down the entire application). If an event loop group was specified at construction time, callers should shut down that event loop group when all clients using that group have been disconnected.
Modifier and Type | Field and Description |
---|---|
static int |
ALTERNATE_APNS_PORT
An alternative port for communication with the APNs gateway.
|
static int |
DEFAULT_APNS_PORT
The default (HTTPS) port for communication with the APNs gateway.
|
static long |
DEFAULT_WRITE_TIMEOUT_MILLIS
The default write timeout, in milliseconds.
|
static String |
DEVELOPMENT_APNS_HOST
The hostname for the development APNs gateway.
|
static String |
PRODUCTION_APNS_HOST
The hostname for the production APNs gateway.
|
Modifier and Type | Method and Description |
---|---|
Future<Void> |
connect(String host)
Connects to the given APNs gateway on the default (HTTPS) port
(443).
|
Future<Void> |
connect(String host,
int port)
Connects to the given APNs gateway on the given port.
|
Future<Void> |
disconnect()
Gracefully disconnects from the APNs gateway.
|
Future<Void> |
getReconnectionFuture()
Returns a
Future that will succeed when the client has re-established a connection to the APNs gateway. |
boolean |
isConnected()
Indicates whether this client is connected to the APNs gateway and ready to send push notifications.
|
void |
registerSigningKey(ECPrivateKey signingKey,
String teamId,
String keyId,
Collection<String> topics)
Registers a private signing key for the given topics.
|
void |
registerSigningKey(ECPrivateKey signingKey,
String teamId,
String keyId,
String... topics)
Registers a private signing key for the given topics.
|
void |
registerSigningKey(File signingKeyPemFile,
String teamId,
String keyId,
Collection<String> topics)
Registers a private signing key for the given topics.
|
void |
registerSigningKey(File signingKeyPemFile,
String teamId,
String keyId,
String... topics)
Registers a private signing key for the given topics.
|
void |
registerSigningKey(InputStream signingKeyInputStream,
String teamId,
String keyId,
Collection<String> topics)
Registers a private signing key for the given topics.
|
void |
registerSigningKey(InputStream signingKeyInputStream,
String teamId,
String keyId,
String... topics)
Registers a private signing key for the given topics.
|
void |
removeKeyForTeam(String teamId)
Removes all registered keys and associated topics for the given team.
|
<T extends ApnsPushNotification> |
sendNotification(T notification)
Sends a push notification to the APNs gateway.
|
public static final long DEFAULT_WRITE_TIMEOUT_MILLIS
public static final String PRODUCTION_APNS_HOST
public static final String DEVELOPMENT_APNS_HOST
public static final int DEFAULT_APNS_PORT
public static final int ALTERNATE_APNS_PORT
An alternative port for communication with the APNs gateway. According to Apple's documentation:
You can alternatively use port 2197 when communicating with APNs. You might do this, for example, to allow APNs traffic through your firewall but to block other HTTPS traffic.
public Future<Void> connect(String host)
Connects to the given APNs gateway on the default (HTTPS) port (443).
Once an initial connection has been established and until the client has been explicitly disconnected via the
disconnect()
method, the client will attempt to reconnect automatically if the connection
closes unexpectedly. If the connection closes unexpectedly, callers may monitor the status of the reconnection
attempt with the Future
returned by the getReconnectionFuture()
method.
host
- the APNs gateway to which to connectFuture
that will succeed when the client has connected to the gateway and is ready to send
push notificationsPRODUCTION_APNS_HOST
,
DEVELOPMENT_APNS_HOST
public Future<Void> connect(String host, int port)
Connects to the given APNs gateway on the given port.
Once an initial connection has been established and until the client has been explicitly disconnected via the
disconnect()
method, the client will attempt to reconnect automatically if the connection
closes unexpectedly. If the connection closes unexpectedly, callers may monitor the status of the reconnection
attempt with the Future
returned by the getReconnectionFuture()
method.
host
- the APNs gateway to which to connectport
- the port on which to connect to the APNs gatewayFuture
that will succeed when the client has connected to the gateway and is ready to send
push notificationsPRODUCTION_APNS_HOST
,
DEVELOPMENT_APNS_HOST
,
DEFAULT_APNS_PORT
,
ALTERNATE_APNS_PORT
public boolean isConnected()
true
if this client is connected and ready to send notifications or false
otherwisepublic Future<Void> getReconnectionFuture()
Returns a Future
that will succeed when the client has re-established a connection to the APNs gateway.
Callers may use this method to determine when it is safe to resume sending notifications after a send attempt
fails with a ClientNotConnectedException
.
If the client is already connected, the Future
returned by this method will succeed immediately. If
the client was not previously connected (either because it has never been connected or because it was explicitly
disconnected via the disconnect()
method), the Future
returned by this method will
fail immediately with an IllegalStateException
.
Future
that will succeed when the client has established a connection to the APNs gatewaypublic void registerSigningKey(File signingKeyPemFile, String teamId, String keyId, Collection<String> topics) throws InvalidKeyException, NoSuchAlgorithmException, IOException
Registers a private signing key for the given topics. Clears any topics and keys previously associated with the given team.
Callers using token-based authentication must register signing keys for all topics to which they intend to send notifications. Callers must not attempt to register signing keys when using TLS-based client authentication. Tokens may be registered at any time in a client's life-cycle.
signingKeyPemFile
- a PEM file that contains a PKCS#8-formatted elliptic-curve private key with which to
sign authentication tokensteamId
- the Apple-issued, ten-character identifier for the team to which the given private key belongskeyId
- the Apple-issued, ten-character identifier for the given private keytopics
- the topics to which the given signing key is applicableIllegalStateException
- if this client uses TLS-based authentication instead of token-based authenticationInvalidKeyException
- if the given key is invalid for any reasonNoSuchAlgorithmException
- if the JRE does not support the required token-signing algorithmIOException
- if a private key could not be loaded from the given file for any reasonpublic void registerSigningKey(File signingKeyPemFile, String teamId, String keyId, String... topics) throws InvalidKeyException, NoSuchAlgorithmException, IOException
Registers a private signing key for the given topics. Clears any topics and keys previously associated with the given team.
Callers using token-based authentication must register signing keys for all topics to which they intend to send notifications. Callers must not attempt to register signing keys when using TLS-based client authentication. Tokens may be registered at any time in a client's life-cycle.
signingKeyPemFile
- a PEM file that contains a PKCS#8-formatted elliptic-curve private key with which to
sign authentication tokensteamId
- the Apple-issued, ten-character identifier for the team to which the given private key belongskeyId
- the Apple-issued, ten-character identifier for the given private keytopics
- the topics to which the given signing key is applicableIllegalStateException
- if this client uses TLS-based authentication instead of token-based authenticationInvalidKeyException
- if the given key is invalid for any reasonNoSuchAlgorithmException
- if the JRE does not support the required token-signing algorithmIOException
- if a private key could not be loaded from the given file for any reasonpublic void registerSigningKey(InputStream signingKeyInputStream, String teamId, String keyId, Collection<String> topics) throws InvalidKeyException, NoSuchAlgorithmException, IOException
Registers a private signing key for the given topics. Clears any topics and keys previously associated with the given team.
Callers using token-based authentication must register signing keys for all topics to which they intend to send notifications. Callers must not attempt to register signing keys when using TLS-based client authentication. Tokens may be registered at any time in a client's life-cycle.
signingKeyInputStream
- an input stream that provides a PEM-encoded, PKCS#8-formatted elliptic-curve private
key with which to sign authentication tokensteamId
- the Apple-issued, ten-character identifier for the team to which the given private key belongskeyId
- the Apple-issued, ten-character identifier for the given private keytopics
- the topics to which the given signing key is applicableIllegalStateException
- if this client uses TLS-based authentication instead of token-based authenticationInvalidKeyException
- if the given key is invalid for any reasonNoSuchAlgorithmException
- if the JRE does not support the required token-signing algorithmIOException
- if a private key could not be loaded from the given input stream for any reasonpublic void registerSigningKey(InputStream signingKeyInputStream, String teamId, String keyId, String... topics) throws InvalidKeyException, NoSuchAlgorithmException, IOException
Registers a private signing key for the given topics. Clears any topics and keys previously associated with the given team.
Callers using token-based authentication must register signing keys for all topics to which they intend to send notifications. Callers must not attempt to register signing keys when using TLS-based client authentication. Tokens may be registered at any time in a client's life-cycle.
signingKeyInputStream
- an input stream that provides a PEM-encoded, PKCS#8-formatted elliptic-curve private
key with which to sign authentication tokensteamId
- the Apple-issued, ten-character identifier for the team to which the given private key belongskeyId
- the Apple-issued, ten-character identifier for the given private keytopics
- the topics to which the given signing key is applicableIllegalStateException
- if this client uses TLS-based authentication instead of token-based authenticationInvalidKeyException
- if the given key is invalid for any reasonNoSuchAlgorithmException
- if the JRE does not support the required token-signing algorithmIOException
- if a private key could not be loaded from the given input stream for any reasonpublic void registerSigningKey(ECPrivateKey signingKey, String teamId, String keyId, Collection<String> topics) throws InvalidKeyException, NoSuchAlgorithmException
Registers a private signing key for the given topics. Clears any topics and keys previously associated with the given team.
Callers using token-based authentication must register signing keys for all topics to which they intend to send notifications. Callers must not attempt to register signing keys when using TLS-based client authentication. Tokens may be registered at any time in a client's life-cycle.
signingKey
- the private key with which to sign authentication tokensteamId
- the Apple-issued, ten-character identifier for the team to which the given private key belongskeyId
- the Apple-issued, ten-character identifier for the given private keytopics
- the topics to which the given signing key is applicableIllegalStateException
- if this client uses TLS-based authentication instead of token-based authenticationInvalidKeyException
- if the given key is invalid for any reasonNoSuchAlgorithmException
- if the JRE does not support the required token-signing algorithmpublic void registerSigningKey(ECPrivateKey signingKey, String teamId, String keyId, String... topics) throws InvalidKeyException, NoSuchAlgorithmException
Registers a private signing key for the given topics. Clears any topics and keys previously associated with the given team.
Callers using token-based authentication must register signing keys for all topics to which they intend to send notifications. Callers must not attempt to register signing keys when using TLS-based client authentication. Tokens may be registered at any time in a client's life-cycle.
signingKey
- the private key with which to sign authentication tokensteamId
- the Apple-issued, ten-character identifier for the team to which the given private key belongskeyId
- the Apple-issued, ten-character identifier for the given private keytopics
- the topics to which the given signing key is applicableIllegalStateException
- if this client uses TLS-based authentication instead of token-based authenticationInvalidKeyException
- if the given key is invalid for any reasonNoSuchAlgorithmException
- if the JRE does not support the required token-signing algorithmpublic void removeKeyForTeam(String teamId)
teamId
- the Apple-issued, ten-character identifier for the team for which to remove keys and topicspublic <T extends ApnsPushNotification> Future<PushNotificationResponse<T>> sendNotification(T notification)
Sends a push notification to the APNs gateway.
This method returns a Future
that indicates whether the notification was accepted or rejected by the
gateway. If the notification was accepted, it may be delivered to its destination device at some time in the
future, but final delivery is not guaranteed. Rejections should be considered permanent failures, and callers
should not attempt to re-send the notification.
The returned Future
may fail with an exception if the notification could not be sent. Failures to
send a notification to the gateway—i.e. those that fail with exceptions—should generally be considered
non-permanent, and callers should attempt to re-send the notification when the underlying problem has been
resolved.
In particular, attempts to send a notification when the client is not connected will fail with a
ClientNotConnectedException
. If the client was previously connected and has not been explicitly
disconnected (via the disconnect()
method), the client will attempt to reconnect
automatically. Callers may wait for a reconnection attempt to complete by waiting for the Future
returned
by the getReconnectionFuture()
method.
T
- the type of notification to be sentnotification
- the notification to send to the APNs gatewayFuture
that will complete when the notification has been either accepted or rejected by the
APNs gatewaypublic Future<Void> disconnect()
Gracefully disconnects from the APNs gateway. The disconnection process will wait until notifications that
have been sent to the APNs server have been either accepted or rejected. Note that some notifications passed to
sendNotification(ApnsPushNotification)
may still be enqueued and
not yet sent by the time the shutdown process begins; the Futures
associated with those notifications
will fail.
The returned Future
will be marked as complete when the connection has closed completely. If the
connection is already closed when this method is called, the returned Future
will be marked as complete
immediately.
If a non-null EventLoopGroup
was provided at construction time, clients may be reconnected and reused
after they have been disconnected. If no event loop group was provided at construction time, clients may not be
restarted after they have been disconnected via this method.
Future
that will be marked as complete when the connection has been closedCopyright © 2013–2016 Turo. All rights reserved.