提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
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.IOS app端 根据证书注册APNS 获取deviceToken 令牌 上报服务端
2.服务端根据令牌发送通知请求
3.异步获取APNS 服务器反馈结果信息
代码如下(示例):
#gradle
com.eatthepath:pushy:0.15.0
代码如下(示例):
# 初始化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;
}
}
@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 不对等情况