您的位置:首页 > 移动开发 > IOS开发

iOS边城之推送APNS详解

2014-09-23 18:16 525 查看

官方指南

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中加入如下代码

//注册服务器推送,在应用第一次启动时弹出对话框让用户确认是否开启消息推送,本句注册的消息类型有BadgeNumber, 声音, 顶部消息框. 可以选择其中的一种或多种。
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];


2、拿到DeviceToken

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
//此token唯一与设备相关,同一设备上不同应用获取的token是一样的;
NSLog(@"My token is: %@", deviceToken);
}

- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{
NSLog(@"Failed to get token, error: %@", error);
}

如果获取token成功,运行后控制台中会有如下格式的输出:
My token is: <cb4f6b40 424b0cb7 e32288a1 826b7d27 4ccb1904 80d65b84bd3c5645 7510f985>
3、推送回调

/**
*  经测试,此方法在应用活动状态与停止状态都可以回调,上述方法只可在应用活动状态时才可以。
*/
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
if ( application.applicationState == UIApplicationStateActive) {
// 程序在运行过程中受到推送通知
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:@"提示" message:userInfo.description delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
NSLog(@"%@",userInfo.description);
[alert1 show];
} else {
//在background状态受到推送通知
UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:@"提示" message:userInfo.description delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
[alert1 show];
}
//完成为什么要通知系统?不明学历。。
completionHandler(UIBackgroundFetchResultNewData);
}


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

{
"aps" : {
"alert" : {
"body" : "Bob wants to play poker",
"action-loc-key" : "PLAY"
},
"badge" : 5,
},
"acme1" : "bar",
"acme2" : [ "bang",  "whiz" ]
}

其中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控制台输出



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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: