Pushy is a Java library for sending APNs (iOS and OS X) push notifications

简介: pushyPushy is a Java library for sending APNs (iOS and OS X) push notifications. It is written and maintained by the engineers at RelayRides and is built on the Netty framework.



pushy

Pushy is a Java library for sending APNs (iOS and OS X) push notifications. It is written and maintained by the engineers at RelayRides and is built on the Netty framework.

Pushy was created because we found that the other APNs libraries for Java simply didn't meet our needs in terms of performance or (especially) reliability. Pushy distinguishes itself from other libraries with several important features:

  • Asynchronous network IO (via Netty) for maximum performance
  • Efficient connection management
  • Graceful handling and reporting of permanent notification rejections and connection failures
  • Thorough documentation

We believe that Pushy is already the best tool for sending APNs push notifications from Java applications, and we hope you'll help us make it even better via bug reports and pull requests. If you have questions about using Pushy, please join us on the Pushy mailing list or take a look at the wiki. Thanks!

Getting Pushy

If you use Maven, you can add Pushy to your project by adding the following dependency declaration to your POM:

<dependency>
    <groupId>com.relayridesgroupId>
    <artifactId>pushyartifactId>
    <version>0.4.1version>
dependency>

If you don't use Maven, you can download Pushy as a .jar file and add it to your project directly. You'll also need to make sure you have Pushy's runtime dependencies on your classpath. They are:

Pushy itself requires Java 1.6 or newer.

Using Pushy

The main public-facing part of Pushy is the PushManager class, which manages connections to APNs and manages the queue of outbound notifications. Before you can create a PushManager, though, you'll need appropriate SSL certificates and keys from Apple. They can be obtained by following the steps in Apple's "Provisioning and Development" guide.

Once you have your certificates and keys, you can construct a new PushManager like this:

final PushManager<SimpleApnsPushNotification> pushManager =
    new PushManager<SimpleApnsPushNotification>(
        ApnsEnvironment.getSandboxEnvironment(),
        SSLContextUtil.createDefaultSSLContext("path-to-key.p12", "my-password"),
        null, // Optional: custom event loop group
        null, // Optional: custom ExecutorService for calling listeners
        null, // Optional: custom BlockingQueue implementation
        new PushManagerConfiguration(),
        "ExamplePushManager");

pushManager.start();

Many aspects of a PushManager's behavior can be customized. See the PushManagerdocumentation for details. Some important highlights:

  1. If you have multiple PushManager instances, you may want to share an event loop group and/or listener executor service between them to keep the number of active threads at a reasonable level.
  2. By default, a PushManager will use an unbounded public queue; depending on your use case, you may want to use a bounded BlockingQueue implementation or even a SynchronousQueue.
  3. Many other low-level options can be configured by providing a customPushManagerConfiguration.

Once you have your PushManager constructed and started, you're ready to start constructing and sending push notifications. Pushy provides utility classes for working with APNs tokens and payloads. Here's an example:

final byte[] token = TokenUtil.tokenStringToByteArray(
    "<5f6aa01d 8e335894 9b7c25d4 61bb78ad 740f4707 462c7eaf bebcf74f a5ddb387>");

final ApnsPayloadBuilder payloadBuilder = new ApnsPayloadBuilder();

payloadBuilder.setAlertBody("Ring ring, Neo.");
payloadBuilder.setSoundFileName("ring-ring.aiff");

final String payload = payloadBuilder.buildWithDefaultMaximumLength();

pushManager.getQueue().put(new SimpleApnsPushNotification(token, payload));

When your application shuts down, make sure to shut down the PushManager, too:

pushManager.shutdown();

When the PushManager takes a notification from the queue, it will keep trying to send that notification. By the time you shut down the PushManager (as long as you don't give the shutdown process a timeout), the notification is guaranteed to have either been accepted or rejected by the APNs gateway.

Error handling

Pushy deals with most problems for you, but there are two classes of problems you may want to deal with on your own.

Rejected notifications

Push notification providers communicate with APNs by opening a long-lived connection to Apple's push notification gateway and streaming push notification through that connection. Apple's gateway won't respond or acknowledge push notifications unless something goes wrong, in which case it will send an error code and close the connection (don't worry -- Pushy deals with all of this for you). To deal with notifications that are rejected by APNs, Pushy provides a notion of aRejectedNotificationListener. Rejected notification listeners are informed whenever APNs rejects a push notification. Here's an example of registering a simple listener:

private class MyRejectedNotificationListener implements RejectedNotificationListener<SimpleApnsPushNotification> {

    @Override
    public void handleRejectedNotification(
            final PushManagerSimpleApnsPushNotification> pushManager,
            final SimpleApnsPushNotification notification,
            final RejectedNotificationReason reason) {

        System.out.format("%s was rejected with rejection reason %s\n", notification, reason);
    }
}

// ...

pushManager.registerRejectedNotificationListener(new MyRejectedNotificationListener());

Lots of things can go wrong when sending notifications, but rejected notification listeners are only informed when Apple definitively rejects a push notification. All other IO problems are treated as temporary issues, and Pushy will automatically re-transmit notifications affected by IO problems later. You may register a rejected notification listener at any time before shutting down the PushManager.

Failed connections

While running, a PushManager will attempt to re-open any connection that is closed by the gateway (i.e. if a notification was rejected). Occasionally, connection attempts will fail for benign (or at least temporary) reasons. Sometimes, though, connection failures can indicate a more permanent problem (like an expired certificate) that won't be resolved by retrying the connection, and letting thePushManager try to reconnect indefinitely won't help the situation.

You can listen for connection failures with a FailedConnectionListener like this:

private class MyFailedConnectionListener implements FailedConnectionListener<SimpleApnsPushNotification> {

    @Override
    public void handleFailedConnection(
            final PushManagerSimpleApnsPushNotification> pushManager,
            final Throwable cause) {

        if (cause instanceof SSLHandshakeException) {
            // This is probably a permanent failure, and we should shut down
            // the PushManager.
        }
    }
}

// ...

pushManager.registerFailedConnectionListener(new MyFailedConnectionListener());

Generally, it's safe to ignore most failures (though you may want to log them). Failures that result from a SSLHandshakeException, though, likely indicate that your certificate is either invalid or expired, and you'll need to remedy the situation before reconnection attempts are likely to succeed. Poorly-timed connection issues may cause spurious exceptions, though, and it's wise to look for a pattern of failures before taking action.

Like RejectedNotificationListeners, FailedConnectionListeners can be registered any time before the PushManager is shut down.

The feedback service

Apple also provides a "feedback service" as part of APNs. The feedback service reports which tokens are no longer valid because the end user uninstalled the receiving app. Apple requires push notification providers to poll for expired tokens on a daily basis. See "The Feedback Service" for additional details from Apple.

To get expired device tokens with Pushy, you'll need to register an ExpiredTokenListener with yourPushManager, then call the requestExpiredTokens method. For example:

private class MyExpiredTokenListener implements ExpiredTokenListener<SimpleApnsPushNotification> {

    @Override
    public void handleExpiredTokens(
            final PushManagerSimpleApnsPushNotification> pushManager,
            final Collection<ExpiredToken> expiredTokens) {

        for (final ExpiredToken expiredToken : expiredTokens) {
            // Stop sending push notifications to each expired token if the expiration
            // time is after the last time the app registered that token.
        }
    }
}

// ...

pushManager.registerExpiredTokenListener(new MyExpiredTokenListener());
pushManager.requestExpiredTokens();

Logging

Pushy uses SLF4J for logging. If you're not already familiar with it, SLF4J is a facade that allows users to choose which logging library to use at deploy time by adding a specific "binding" to the classpath. To avoid making the choice for you, Pushy itself does not depend on any SLF4J bindings; you'll need to add one on your own (either by adding it as a dependency in your own project or by installing it directly). If you have no SLF4J bindings on your classpath, you'll probably see a warning that looks something like this:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

For more information, see the SLF4J user manual.

Pushy uses logging levels as follows:

Level Events logged
error Serious, unrecoverable errors; recoverable errors that likely indicate a bug in Pushy
warn Serious, but recoverable errors; errors that may indicate a bug in caller's code
info Important lifecycle events
debug Minor lifecycle events; expected exceptions
trace Individual IO operations

Limitations and known issues

Although we make every effort to fix bugs and work around issues outside of our control, some problems appear to be unavoidable. The issues we know about at this time are:

  • In cases where we successfully write a push notification to the OS-controlled outbound buffer, but the notification has not yet been written to the network, the push notification will be silently lost if the TCP connection is closed before the OS sends the notification over the network. See#14 for additional discussion.
  • Under Windows, if writing a notification fails after the APNs gateway has rejected a notification and closed the connection remotely, the rejection details may be lost. See #6 for additional discussion.
  • We recommend against using Pushy in a container environment (e.g. a servlet container like Tomcat). Netty, by design, leaves behind some long-running threads and ThreadLocalinstances that we can't reliably clean up, and this can cause leaks when shutting down your app. To be clear, Pushy will send notifications as expected from a container environment, but may not be cleaned up properly at shutdown. If you choose to use Pushy in a container environment, please be aware of the following issues:
    • After shutting down Pushy, a GlobalEventExecutor owned by Netty will continue running for about a second. This can cause warnings in environments that look for thread/resource leaks (e.g. servlet containers), but there is no real harm because the GlobalEventExecutorwill eventually shut itself down. To avoid warnings in these environments, you can add aThread.sleep(1000) call after shutting down Pushy. See #29 for additional discussion.
    • A number of ThreadLocal instances will be left behind by Netty, and these are likely to cause memory leaks. See #73 for details and additional discussion.

License and status

Pushy is available to the public under the MIT License.

The current version of Pushy is 0.4.1. We consider it to be fully functional (and use it in production!), but the public API may change significantly before a 1.0 release.

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
网络安全 数据安全/隐私保护 iOS开发
push证书申请_iOS上架App Store
iOS APP需要推送通知,要用到iOS推送证书,分为测试调试用的iOS推送证书和上架到App Store的ios 推送证书!
|
网络安全 数据安全/隐私保护 iOS开发
push证书申请_iOS上架App Store
OS APP需要推送通知,要用到iOS推送证书,分为测试调试用的iOS推送证书和上架到App Store的ios 推送证书!
|
iOS开发
iOS开发 - 点击tabbar某一个item,直接push跳转进入需要的页面,而不是切换tab
iOS开发 - 点击tabbar某一个item,直接push跳转进入需要的页面,而不是切换tab
469 0
|
iOS开发
iOS开发 - 不通过import引入类名实现push或present
iOS开发 - 不通过import引入类名实现push或present
110 0
|
人工智能 安全 算法
从苹果iOS到欧瑞博HomeAI OS,全屋智能也需要一款操作系统?
从苹果iOS到欧瑞博HomeAI OS,全屋智能也需要一款操作系统?
384 0
从苹果iOS到欧瑞博HomeAI OS,全屋智能也需要一款操作系统?
|
iOS开发
IOS正确解决隐藏导航栏后push、pop闪黑问题
IOS正确解决隐藏导航栏后push、pop闪黑问题
685 0
|
iOS开发
iOS 系统push转场动画
iOS 系统push转场动画
285 0
|
API iOS开发 MacOS
iOS 和 Mac OS X 的字符串渲染
为了简单起见,我们先看看UIKit在字符串渲染方面为我们提供了哪些控件。之后我们将讨论一下对于字符串的渲染, iOS 和 OS X 系统中有哪些相似和不同。 UIKit 提供了很多可以在屏幕上显示和编辑文本的类。每一个类都是为特定使用情况准备的,所以为了避免不必要的问题,为你手上的任务挑选正确的工具是非常重要的。
198 0
iOS 和 Mac OS X 的字符串渲染
|
网络协议 Apache 数据安全/隐私保护
CocoaSPDY:Twitter推出的用于iOS和Mac OS X的SPDY框架
SPDY最初是Google设计的用于替代HTTP的试验品。虽然SPDY是一个二进制协议(无法像HTTP那样,人们可以直观读懂),但是SPDY与HTTP完全兼容。而且,颇具现实意义的是,目前正在进行中的 HTTP2.0 草稿就是基于SPDY的。
265 0
|
iOS开发 MacOS Python
从ld: library not found for -lzookeeper_mt 看ZooKeeper 在Mac OS EI Capitan的安装方式
版权声明:本文为半吊子子全栈工匠(wireless_com,同公众号)原创文章,未经允许不得转载。
1689 0

热门文章

最新文章

  • 1
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    14
  • 2
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    28
  • 3
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    34
  • 4
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    29
  • 5
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    23
  • 6
    uniapp开发ios打包Error code = -5000 Error message: Error: certificate file(p12) import failed!报错问题如何解决
    143
  • 7
    【05】2025年1月首发完整版-篇幅较长-苹果app如何上架到app store完整流程·不借助第三方上架工具的情况下无需花钱但需仔细学习-优雅草央千澈详解关于APP签名以及分发-们最关心的一篇来了-IOS上架app
    235
  • 8
    app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
    90
  • 9
    深入探索iOS开发中的SwiftUI框架
    145
  • 10
    ios样式开关按钮jQuery插件
    60
  • 推荐镜像

    更多