ios消息推送apns(java实现http/2协议发送)(代码片段)

kerryzb kerryzb     2022-12-04     453

关键词:

 首先来了解一下苹果的消息推送APNS(英文全称:Apple Push Notification service)

先来看两张苹果对于推送的两张解释图:

大概的意思就是,提供商把消息推送至苹果的推送服务器,再由苹果推送服务器将消息推送给手机客户端,或者反过来手机客户端把消息推送至苹果推送服务器,再由苹果推送服务将消息推送至提供商。这里提到的提供商可以是像极光推送或其他供应商,亦或是自己的服务器。

这里提到了苹果推送服务器向手机端推送消息,那么它是怎么知道是推送到哪个手机上的呢,这个就汲及到一个Token的问题。

Token是每台iOS手机唯一的标识,在启动手机应用时,会向苹果推送服务器去请求得到唯一的Token。当然,虽然每次应用启动时都会去请求得到Token,但是针对于同一部手机,返回回来的Token值都是一致的。

所以当苹果推送服务器只要知道要推送给哪个Token即可知道是推送至哪个手机。

接下来看一下APNS如何去实现消息的推送

1.首先是要准备好证书

从你的苹果电脑上导出CSR文件,打开钥匙串-->钥匙串访问-->证书助理-->从证书颁发机构请求证书,然后一路输入邮件地址和保存的文件,保存到电脑,CSR文件就生成了。

到苹果开发者官网http://developer.apple.com,登陆进入到证书管理模块,Identifiers --> App IDs, 如果你的应用ID还没有添加进来,那么点右上角加号添加进来,如果已经加进来了,单击进入,进行设置,将Push Notifications 设成Enable.

在Certificates创建推送证书,生成后下载双击安装到电脑。这篇文章写的是HTTP/2无证书发送,所以不需要导出p12给服务器去发消息,只需要安装到mac就可以了。

由于推送需要用到真机,所以还需要Provisioning Profiles 证书,生成后也要在xcode中设置好。

2.给应用注册推送服务

  • 首先在项目的AppDelegate.m中加入以下两个代理方法
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken  
    NSString *token = [NSString stringWithFormat:@"%@", deviceToken];
    //获取终端设备标识,这个标识需要通过接口发送到服务器端,服务器端推送消息到APNS时需要知道终端的标识,APNS通过注册的终端标识找到终端设备。
    NSLog(@"My token is:%@", token);   
  

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error    
    NSString *error_str = [NSString stringWithFormat: @"%@", error];   
    NSLog(@"Failed to get token, error:%@", error_str);   

  • 在AppDelegate.m的(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法中加入注册消息通知推送能力;加入当应用程序处于未启动状态时,判断是否由远程消息通知触发;加入清除消息推送通知标记。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

  //判断是否由远程消息通知触发应用程序启动
    if ([launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]!=nil) 
        //获取应用程序消息通知标记数(即小红圈中的数字)
        int badge = [UIApplication sharedApplication].applicationIconBadgeNumber;
        if (badge>0) 
           //如果应用程序消息通知标记数(即小红圈中的数字)大于0,清除标记。
            badge--;
          //清除标记。清除小红圈中数字,小红圈中数字为0,小红圈才会消除。
            [UIApplication sharedApplication].applicationIconBadgeNumber = badge;
        
    
    //消息推送注册
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeSound|UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeBadge];

  • 在项目AppDelegate.m中加入消息接收处理代理方法。

//处理收到的消息推送
- (void)application:(UIApplication *)application 
didReceiveRemoteNotification:(NSDictionary *)userInfo

    //在此处理接收到的消息。
    NSLog(@"Receive remote notification : %@",userInfo);

3.Java后台苹果推送服务器推送消息(HTTP/2协议)

苹果官方自2021年开始就建议使用HTTP/2协议来发消息到苹果的推送服务器,我是2022年接到有客户的请求收不到信息了才去研究原来之前的发消息方法已经不能再用了,重新研究并写下JAVA发HTTP/2的方法。特别注意,需要 JDK 11 及以上版本才支持HTTP/2的协议,如果低于这个版本的朋友们请赶紧升级JDK吧。

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;

public class ApnsSendUtil 
	
	private static String APPID = "com.renhxyy.erp";
	
	private static String SANDBOX_SERVER = "api.sandbox.push.apple.com:443";
	private static String PRODUCT_SERVER = "api.push.apple.com:443";
	
	
	public static void main(String[] args) throws IOException, InterruptedException, InvalidKeyException, InvalidKeySpecException, NoSuchAlgorithmException, SignatureException 
		// 消息,参考:https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification
		String payload = " \\"aps\\" :  \\"alert\\" : \\"邹宝珠的测试消息!\\"  ";
		Integer statuCode = ApnsSendUtil.send("f215ffebd0b4cac54a6d944a498c209deb5b58b789fb26da08bbb30af8dc8440", false, payload);
		System.out.println(statuCode);
	
	
	public static Integer send(String deviceToken, Boolean isProduct, String payload) 
			throws IOException, InterruptedException, InvalidKeyException, InvalidKeySpecException, NoSuchAlgorithmException, SignatureException 
		
		HttpClient client = HttpClient.newBuilder().build();

		HttpRequest request = HttpRequest.newBuilder()
				.uri(URI.create("https://" + (isProduct ? PRODUCT_SERVER : SANDBOX_SERVER) +"/3/device/" + deviceToken)) // deviceToken 从手机上获取到的设备 token
				.POST(BodyPublishers.ofString(payload)) // 发送的消息内容
				.setHeader("authorization", JWT.getToken()) // 请苹果接口的令牌,通过 JWT 生成,有时间有过期(好像是一个小时过期,所以不要去缓存它,每次请求时去重新生成一个就好)
				.setHeader("apns-id", "eabeae54-14a8-11e5-b60b-1697f925ec7a") // 可以理解成APP名称吧,符合格式即可,随意命名
				.setHeader("apns-push-type", "alert") // 消息的提示方式,alert 是指弹出横幅
				.setHeader("apns-expiration", "0")
				.setHeader("apns-priority", "10") // 10 表示立即发送
				.setHeader("apns-topic", APPID) //  APPID,和证书一致
				.build();

		HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());

		Integer statuCode = response.statusCode(); // 返回状态码,如果是 200 则表示发送成功

		if (statuCode == null || statuCode.intValue() != 200) 
			System.out.println(response.body()); // 如果返回的状态码不是200,则发送失败,response.body() 是错误的原因
		
		
		return statuCode;
	
	
	
	
	


可以参考苹果官方文档说明:

Apple Developer Documentation

附上 JAVA HTTP/2协议请求APNS的完整代码

iOS消息推送(Java实现HTTP/2协议发送APNS)-Java文档类资源-CSDN下载

效果图

备注:这篇文章没有对证书和APP端代码(即第1步和第2步)做详细的描述,网上有很多文章对这部分有详解,如果还不懂可以加我微信 kerryzb 聊。

java通知书怎么实现

1、首先是应用程序注册消息推送。2、IOS跟APNSServer要deviceToken。应用程序接受deviceToken。3、应用程序将deviceToken发送给PUSH服务端程序。4、服务端程序向APNS服务发送消息。5、APNS服务将消息发送给iPhone应用程序。参考技术A请将你... 查看详情

FCM 是直接发送推送通知还是向 APNS 发送消息?

】FCM是直接发送推送通知还是向APNS发送消息?【英文标题】:DoesFCMsendpushnotificationdicrectlyoritsendsmessagetoAPNS?【发布时间】:2018-05-2809:32:34【问题描述】:根据Apple文档,每个推送通知总是遍历APNS服务器。我在某处听说FCM直接将推... 查看详情

用html5开发的webapp怎么实现消息推送

通过后台服务的支持来实现消息推送。实现消息推送的原理是:1、首先,需要在应用程序进行注册一个消息推送。2、然后,IOS跟APNSServer要deviceToken。这样子应用程序才能接受deviceToken。3、紧接着,应用程序将deviceToken发送给PUSH... 查看详情

APNS - 无效的注册消息

】APNS-无效的注册消息【英文标题】:APNS-InvalidRegistrationmessage【发布时间】:2013-11-2315:23:49【问题描述】:我创建了一个简单的iOS应用并启用了推送通知。我使用WindowsAzure作为我的服务器。我按照步骤启用推送通知(使用开发证... 查看详情

APNs 消息发送到服务器,设备 iOS 上没有通知

】APNs消息发送到服务器,设备iOS上没有通知【英文标题】:APNsMessagesendtoServer,NonotificationcomesondeviceiOS【发布时间】:2015-05-2107:51:13【问题描述】:我已经为服务器配置了apns_certificate.pem和apns_privatekey.pem。我正在使用node.js服务器... 查看详情

iOS APN 推送通知 - 设备令牌

...是唯一的,还是我可以使用全局设备令牌来发送推送通知消息?我猜如果设备令牌是唯一的,我必须将它保存到数据库中。【问题讨论】:对于您 查看详情

APNS 内容可用推送在 iOS 15 中不起作用

...:1不工作"aps":"content-available":1,"update":"2|1"但正常的通知消息推 查看详情

通过 FCM 发送推送通知时何时使用 iOS 设备令牌?

...时间】:2020-03-2914:08:04【问题描述】:我对通过FCM实现云消息传递感到困惑。要向iOS设备发送远程(推送)通知,APN需要iOS设备令牌。但是,Firebase应用程序不与APN接口,它与FCM接口,后者与APN接口。但是通过 查看详情

无法接收生产 apns 的推送消息

】无法接收生产apns的推送消息【英文标题】:unabletoreceivepushmessageforproductionapns【发布时间】:2012-07-0217:12:05【问题描述】:我可以使用开发证书接收推送消息,但是当我更改为使用生产证书时,收不到消息,并且没有发生错误... 查看详情

发送 507 推送消息后 APNS 关闭连接

】发送507推送消息后APNS关闭连接【英文标题】:APNScloseconnectionaftersending507pushmessage【发布时间】:2012-09-0102:10:41【问题描述】:我已将我的应用程序提交到苹果商店,现在我想将APNS发送给用户。我想从我的桌面通过这个php代码... 查看详情

PHP - APNs 消息已交付但在 iOS 设备上未收到

】PHP-APNs消息已交付但在iOS设备上未收到【英文标题】:PHP-APNsmessagesaredeliveredbutnotreceivedoniOSdevice【发布时间】:2015-12-2511:15:08【问题描述】:我正在使用以下代码向ios设备发送推送通知。我在php端成功发送消息,但在iOS设备中... 查看详情

ios开发:对苹果apns远程推送原理的理解(代码片段)

...Ns)用户的设备您的应用在用户设备上运行我们要实现一个消息的推送,大概分两步:注册推送和推送消息。注册推送启动APP时,通常会去请求推送权限,当用户点击允许后,手机就会拿着设备标识、推送证书... 查看详情

ios开发:对苹果apns远程推送原理的理解(代码片段)

...Ns)用户的设备您的应用在用户设备上运行我们要实现一个消息的推送,大概分两步:注册推送和推送消息。注册推送启动APP时,通常会去请求推送权限,当用户点击允许后,手机就会拿着设备标识、推送证书... 查看详情

如何使用 APNs Auth Key 和标准 CLI 工具发送 APNs 推送消息?

】如何使用APNsAuthKey和标准CLI工具发送APNs推送消息?【英文标题】:HowtosendAPNspushmessagesusingAPNsAuthKeyandstandardCLItools?【发布时间】:2016-10-0912:36:50【问题描述】:Apple最近向APNS(ApplePushNotificationAuthenticationKey(Sandbox&Production))添加... 查看详情

来自 APNS(Apple 推送通知服务器)的反馈服务

...】:我们使用Java作为APNS.I的推送通知提供商,我能够将消息发送到APNS,但我不知道如何获得消息的反馈。请帮忙【问题讨论】:【参考方案1】:反馈服务有一个类似于用于发送推送通知的接口的二进制接口。您可以 查看详情

APNS 多久尝试一次向设备推送消息?

】APNS多久尝试一次向设备推送消息?【英文标题】:HowoftendoesAPNStrytopushmessagetodevices?【发布时间】:2011-07-2706:35:32【问题描述】:如果目标设备离线,APNS多久尝试一次将消息转发到设备?是设备刚上线的时候吗?它是怎么发生... 查看详情

使用 PHP 通过 APNs 发送 iOS 推送通知

】使用PHP通过APNs发送iOS推送通知【英文标题】:UsingPHPtosendiOSPushNotificationsviaAPNs【发布时间】:2018-01-0619:15:59【问题描述】:我已经在我的项目中实现了推送通知,到目前为止一切正常。我试过通过Pusher发送通知,结果很好。但... 查看详情

APNS 接受推送消息,但它们永远不会成为目标

】APNS接受推送消息,但它们永远不会成为目标【英文标题】:APNSacceptspushmessages,buttheyarenevercometotarget【发布时间】:2015-01-2916:57:05【问题描述】:我正在尝试为我的后端服务器服务添加苹果推送通知,但我遇到了一个我无法理... 查看详情