iOS边城之推送APNS详解

官方指南


 

1、介绍

苹果推送服务APNS(Apple Push Notification Service),是苹果自己维护的推送服务,如果你想用推送就必须经过APNS服务器。推送形式包括顶部消息条、声音以及badge number()有了APNS,应用程序可在任意状态接收到与程序有关的消息(包括运行状态not running,foreground以及background),由于在大多数情况下,iOS中最多只有一个应用能处于active状态,所以,APNS为应用的交互提供了极大的便利。

需要注意的几点

1、APNS是免费的。只要有开发者账号便可以申请APNS证书。

2、APNS又是不可靠的,苹果对信息推送的可靠性不做任何保证。

3、APNS对消息的大小是有限制的,总容量不能超过256字节


2、架构模式

在系统级别有一个推送服务程序使用 5223 端口。使用这个端口的协议源于 Jabber 后来发展为 XMPP ,被用于 Gtalk 等 IM 软件中。


所以, iOS 的推送,可以不严谨的理解为:

苹果服务器朝手机后台挂的一个 IM 服务程序发送的消息。

然后,系统根据该 IM 消息识别告诉哪个 Apps 具体发生了什么事。

然后,系统分别通知这些 Apps 。

 

现在市面上的IM应用,大部分采用离线推送,就是应用处于background时走APNS,应用foreground时使用自家的通讯服务。


3、工作流程


1& 2:用户第一次安装应用并第一次启动时,会弹出对话框提示应用需要开通推送,是否允许,如果允许,应用会得到一个硬件token

有三点需要注意:

第一,token唯一与设备相关,同一设备上不同应用获取的token是一样的。一般应用第一次打开时,会token发到应用服务器进行保存

第二,当应用被卸载,然后重新安装时,确认对话框不会再出现,自动继承前一次安装的设置信息;

第三,推送设置可以在设置-通知中进行更改。可以选择开启消息框、声音以及badge number中的一种或多种。

3:开发者此时应该将收到的token发送到应用服务端并保存数据库中(也就是APNS消息的源头)

4:应用服务器通过token及证书向苹果的消息服务器发送消息。

5:苹果将接收到的消息发送到对应设备上的对应应用。

6:如果应用未处于Active状态(未启动或backgroud),默认设置下,屏幕顶部会弹出消息框,同时有声音提示,点击改消息框会进入应用,如不点击则应用图标上会有badge number出现。


4、开发流程

在开始之前,假设已拥有开发者账号,并已经创建APPID

step1 开启PushNotification

登陆 iOS Dev Center 选择进入iOS Provisioning Portal,点击App IDS,为 App 开启 Push Notification 功能


因为我们这边是测试。所以先配置开发证书,应用上线时才需要生产证书。但步骤是一样的


注意:app id需要指定具体的Bundle ID不要使用通配符。

Step2 配置证书

1、如果你之前没有创建过 Push证书或者是要重新创建一个新的,请在证书列表下面新建。


2、新建证书需要注意选择证书种类(开发证书用于开发和调试使用,生产证书用于 App Store发布)


3、点击 Continue后选择证书对应的应用ID,然后继续会出现“About Creating a Certificate Signing Request (CSR)”


4、根据它的说明创建打开钥匙串访问创建CertificateSigning Request(csr文件 )。



邮件地址与常用名称随便写,然后选择存储到磁盘,点击继续,将文件保存到桌面。

 5、然后继续返回Apple developer网站点击 Continue,上传刚刚生成的.certSigningRequest 文件生成 APNs Push  Certificate

6、下载并双击打开证书,证书打开时会启动钥匙串访问工具。

7、在钥匙串访问中你的证书会显示在我的证书中,注意选择“My Certificates” "login"


选择,右键导出到桌面,命名为cert.p12,密码设置为123456



然后展开,选择里面的private key(这里的名称是之前创建csr文件时的名称),同样右键导出到桌面,命名为key.p12,密码设置为123456

8、打开终端,切换到桌面,输入以下命令生成pem文件 (什么?不知道pem文件时做什么,通俗的说,有了pem文件你就可以与APNS通信,一般这个证书会放到应用服务器上)

openssl pkcs12 -clcerts -nokeys -out cert.pem -in cert.p12

生成cert.pem;输入访问密码123456,设置pem文件的密码123456(服务器访问pem的密码)

 

openssl pkcs12 -nocerts -out key.pem -in key.p12

生成key.pem;操作同上


(可选)openssl rsa -inkey.pem -out key.unencrypted.pem如果需要对key不进行加密。


cat cert.pem key.unencrypted.pem > ck.pem

合并两个.pem文件, 这个ck.pem就是服务端需要的证书了。

 

最后,测试一下得到的ck.pem文件

首先运行:

命令:telnet gateway.sandbox.push.apple.com 2195

如果网络正常,会出现如下所示,ctrl + C终止连接。

Trying 17.172.232.226...

Connected to gateway.sandbox.push-apple.com.akadns.net.

Escape character is '^]'.

 

然后使用ssl测试连接

命令:openssl s_client -connectgateway.sandbox.push.apple.com:2195 -cert cert.pem -key key.pem

输入密码123456后,如果一切正常,会出现很多的输出,你将可以输入若干字符,回车后,连接将中断。

至此,我们证书配置就完成啦!

Step3 代码编写

注意,项目的bundle identifier需要和apple developer上的一致,否则拿不到DeviceToken的



1、注册。首先,在项目中AppDelegate.m的didFinishLaunchingWithOptions中加入如下代码

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //注册服务器推送,在应用第一次启动时弹出对话框让用户确认是否开启消息推送,本句注册的消息类型有BadgeNumber, 声音, 顶部消息框. 可以选择其中的一种或多种。  
  2.     [[UIApplication sharedApplication] registerForRemoteNotificationTypes:  
  3. (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];  

2、拿到DeviceToken

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. - (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken  
  2. {  
  3.     //此token唯一与设备相关,同一设备上不同应用获取的token是一样的;  
  4.     NSLog(@"My token is: %@", deviceToken);  
  5. }  
  6.   
  7. - (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error  
  8. {  
  9.     NSLog(@"Failed to get token, error: %@", error);  
  10. }  

如果获取token成功,运行后控制台中会有如下格式的输出:

 My token is: <cb4f6b40 424b0cb7 e32288a1 826b7d27 4ccb1904 80d65b84bd3c5645 7510f985>

3、推送回调

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  *  经测试,此方法在应用活动状态与停止状态都可以回调,上述方法只可在应用活动状态时才可以。 
  3.  */  
  4. - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{  
  5.     if ( application.applicationState == UIApplicationStateActive) {  
  6.         // 程序在运行过程中受到推送通知  
  7.         UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:@"提示" message:userInfo.description delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];  
  8.         NSLog(@"%@",userInfo.description);  
  9.         [alert1 show];  
  10.     } else {  
  11.         //在background状态受到推送通知  
  12.         UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:@"提示" message:userInfo.description delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];  
  13.         [alert1 show];  
  14.     }  
  15.     //完成为什么要通知系统?不明学历。。  
  16.     completionHandler(UIBackgroundFetchResultNewData);  
  17. }  

此处的userInfo为后台服务器推送过来信息,是一个Json string,大致是这样的

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. {  
  2.     "aps" : {  
  3.         "alert" : {  
  4.             "body" : "Bob wants to play poker",  
  5.             "action-loc-key" : "PLAY"  
  6.         },  
  7.         "badge" : 5,  
  8.     },  
  9.     "acme1" : "bar",  
  10.     "acme2" : [ "bang",  "whiz" ]  
  11. }  

其中body为信息。Badge为icon通知数字,其中几个应该为自定义字段。对!应该是这样的!


最后我们运行应用、进入下一步


Step4测试

在应用服务器如果要推送,java可以使用JavaPNS、php可以使用php样例程序

 

我们为了方便,就使用php进行测试。 

首先下载样例程序

将ck.pem替换为刚刚生成的ck.pem

然后打开simplepush.php,将其中的devicetoken字段设为刚才保存的token,注意,去掉空格

将password设为123456(ck.pem的密码,如果执行了去密码那条语句,此处为空就好)

将message设为你想设置的内容,保存

然后切换到simplepush目录,运行php simplepush.php

 

如果人品够好,你的设备上马上会咚咚的响一下~

此时xcode控制台输出



什么?文中有很多似曾相识的段落?没错,就是抄袭!如你是原帖作者。如有不满。小生在此敬上:放学后你来打我啊!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值