当前位置: 首页 > 工具软件 > apns4j > 使用案例 >

java 引用Pushy 实现Apns 完成ios 推送

刘元青
2023-12-01

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、Pushy是什么?

pushy框架介绍
Pushy是用于发送APN(iOS,MacOS和Safari)推送通知的Java库。它由Turo的工程师编写和维护。

Pushy使用Apple的基于HTTP / 2的APN协议发送推送通知,并支持TLS和基于令牌的身份验证。它与其他推送通知库区别开来,重点在于全面的文档记录,异步操作和用于工业规模操作的设计; 通过Pushy,维护到APN网关的多个并行连接可以轻松高效地向大量不同的应用程序(“主题”)发送大量通知。

我们相信Pushy已经是从Java应用程序发送APN推送通知的最佳工具,并且我们希望您能通过错误报告和拉取请求帮助我们更好地实现它。如果您对使用Pushy有任何疑问,请加入我们的Pushy邮件列表或查看wiki。谢谢!

上面摘抄于git文档
源码网址:pushy源码地址

二、使用步骤

1.APNS 推送流程

1.IOS app端 根据证书注册APNS 获取deviceToken 令牌 上报服务端
2.服务端根据令牌发送通知请求
3.异步获取APNS 服务器反馈结果信息

代码如下(示例):

#gradle
com.eatthepath:pushy:0.15.0

2 设置相关配置

1.p12 证书准备

相关证书需要找ios 开发 导出文件 证书分为 开发环境证书 生产环境证书 后续初始化apnsclient 需要根据不同环境的证书初始化请求地址(PS:后续代码说明)

2.初始化APNSClient 请求对象

代码如下(示例):

# 初始化APNS请求对象
public class APNSConnect {

    private static ApnsClient apnsClient = null;

    public static ApnsClient getAPNSConnect() {
        if (apnsClient == null) {
            try {
                //设置环境
                InputStream inputStream =PushFcmApnsProperties.iosP12Path.getInputStream();
				//读取证书文件信息
                File bathFile = File.createTempFile(UUID.randomUUID().toString(), ".p12");
                FileUtils.copyInputStreamToFile(inputStream, bathFile);
                //设置信息包含服务器地址  ApnsClientBuilder.DEVELOPMENT_APNS_HOST 开发环境地址
                //ApnsClientBuilder.PRODUCTION_APNS_HOST  对应生产环境
                apnsClient = new ApnsClientBuilder().setApnsServer(PushFcmApnsProperties.pushEnvironment?ApnsClientBuilder.PRODUCTION_APNS_HOST:ApnsClientBuilder.DEVELOPMENT_APNS_HOST)
                //setClientCredentials 包含  证书file 文件  证书对应的文件密码(找ios 开发确定导出密码)
                        .setClientCredentials(bathFile, PushFcmApnsProperties.iosP12PassWord)
                        .setConcurrentConnections(4).build();
            } catch (Exception e) {
                log.error("ios get pushy apns client failed!");
                e.printStackTrace();
            }
        }
        return apnsClient;

    }
}

3.工具类示例

@Slf4j
public class ApnsPush {

    public static void push(List<String> deviceTokens, String alertTitle, String alertBody,
                            boolean contentAvailable, Map<String, String> customProperty,
                            Map<String, NotificationPushDevice> badgeMap) {
        long startTime = System.currentTimeMillis();
        ApnsClient apnsClient = APNSConnect.getAPNSConnect();
        long total=deviceTokens.size();
        long startPushTime =  System.currentTimeMillis();
        for (String deviceToken : deviceTokens) {

        ApnsPayloadBuilder payloadBuilder =new SimpleApnsPayloadBuilder();

        if(alertBody!=null) {
            payloadBuilder.setAlertBody(alertBody);
        }

        if(alertTitle !=null){
            payloadBuilder.setAlertTitle(alertTitle);
        }

        //如果badge小于0,则不推送这个右上角的角标,主要用于消息盒子新增或者已读时,更新此状态
        payloadBuilder.setBadgeNumber(1);

        //将所有的附加自定义参数全部放进去
        if(customProperty!=null) {
            for(Map.Entry<String, String> map:customProperty.entrySet()) {
                payloadBuilder.addCustomProperty(map.getKey(),map.getValue());
            }
        }
        payloadBuilder.setContentAvailable(contentAvailable);
        String payload = payloadBuilder.build();
        final String token = TokenUtil.sanitizeTokenString(deviceToken);
            SimpleApnsPushNotification pushNotification = new SimpleApnsPushNotification(token, PushFcmApnsProperties.iosTopic, payload,Instant.now().plus(Duration.ofDays(1)), DeliveryPriority.IMMEDIATE, PushType.ALERT);

            //发送消息回复返回值
            final PushNotificationFuture<SimpleApnsPushNotification, PushNotificationResponse<SimpleApnsPushNotification>>
                    sendNotificationFuture = apnsClient.sendNotification(pushNotification);

            //监听--用以提高效率
            sendNotificationFuture.whenComplete((pushNotificationResponse, cause) -> {
                if (pushNotificationResponse != null) {
                    // Handle the push notification response as before from here.
                    if (pushNotificationResponse.isAccepted()) {
                        log.info("Push notification accepted by APNs gateway.");
                    } else {
                        log.error("Notification rejected by the APNs gateway: " +
                                pushNotificationResponse.getRejectionReason());
                        pushNotificationResponse.getTokenInvalidationTimestamp().ifPresent(timestamp -> {
                            log.error("\t…and the token is invalid as of " + timestamp);
                        });
                    }
                } else {
                    // Something went wrong when trying to send the notification to the
                    // APNs server. Note that this is distinct from a rejection from
                    // the server, and indicates that something went wrong when actually
                    // sending the notification or waiting for a reply.
                    cause.printStackTrace();
                }
            });

        }
        long endPushTime = System.currentTimeMillis();

        log.info("test pushMessage success. [共推送" + total + "个],time= " + (endPushTime - startTime) );
    }

小记

接入流程没任何难度,看pushy 对应的wiki 很清晰,主要是app 联调过程中需要注意各个环境的细节,报错错误码没有对应的文档 ,这个比较麻烦,大部分错误都是证书过期 或者对应的环境有问题 token 不对等情况

 类似资料: