IOS中消息的推送有两种方式,分别是本地推送和远程推送,本地推送在http://my.oschina.net/u/2340880/blog/405491这篇博客中有详细的介绍,这里主要讨论远程推送的流程与配置过程。php
搜索IOS远程推送,你总能看到一张以下的流程示意图,由于这张图确实很火,因此我也将它引用在此:android
这张图示意的很清晰,大体意思是这样:你的应用服务端将消息发送到apple的APNS服务器,APNS服务器将消息推送到指定的Iphone,最后由Iphone负责将消息推送至你的APP。在此先不说这个过程是如何实现的,仅仅看这个流程,你可能会以为,在大家服务端和客户端之间增长了一个apple的APNS,不是增长开发者的负担么?其实结果偏偏相反,由于apple对推送的统一管理,使咱们开发者的工做变得异常简单。json
若是你是作android开发的,你必定很是了解长连接与心跳包。事实上,大部分的android应用的推送也确实是经过长连接来实现的。由于android系统的开放性,APP是很容易作到自启动和后台长连接的,而心跳验证,就是始终保证长连接属于接通状态,而后由服务端直接推送消息。若是IOS开发者也采用这种思路,就十分困难了,在IOS中想要保持一个APP服务始终不被系统杀死,我只能说太难了。经过上面的流程图,对比android的推送思路,咱们很容易明白,IOS中其实也始终有一个长连接,那就是系统自己,这个长连接始终与APNS服务器相连,而后统一管理全部应用程序的推送。安全
下面的这些,只是我我的的一些见解。系统并没有优劣,优劣在于我的喜爱。服务器
一、由于推送的服务端是appleID的验证用户,推送可靠性会高。app
二、全部推送消息由APNS统一管理,效率高。socket
三、在客户端只需系统维护一个长连接,节省了用户流量消耗和手机的性能消耗,而且提升了安全性,使得有恶意推送和流氓软件的概率下降。性能
(1)请求CSR文件测试
在MAC应用程序中找到钥匙串访问,打开它。ui
点击选项栏中的钥匙串访问中的证书助理:
选择从证书颁发机构申请证书:
填写电子邮件和名称,选择储存到磁盘,而后继续。
这时,咱们存储的地方有了这样一个文件:CertificateSigningRequest.certSigningRequest。
(2)导出密钥文件
打开钥匙串,会发现多了一对密钥,名字就是上面你填写的经常使用名称。
咱们选择专用密钥进行导出,而后设置一个咱们本身的密码:
这时候咱们又有了一个后缀名为.p12的文件。
(3)建立AppId
到https://developer.apple.com的member Center:
用你付过费的开发者appleID登录后,选择Certificates:
若是你的项目已经建立了APP id,则能够不用从新建立,可是你建立的APP id必需要支持远程推送。若是尚未建立,点击加号,建立一个:
以后的界面中APP ID有两种类型:Explicit和Wildcard,分别是特殊的和通配的,咱们须要推送功能,这个ID不能是通配的,因此咱们选择第一个。
这里须要填的的Bundle ID必须和咱们App中的一致:
在APP ID的服务设置中,将Push Notification勾选上,点击continue。
以后点击submit,最后点击Done。这时咱们的APP IDs列表中会出现咱们刚才建立的APP ID。
(4)建立证书
点击咱们刚才建立的APP ID,你会看到Push Notification一行为未设定的。咱们点击Edit。
在Push Notifications设置里是以下界面,development是开发证书,Production是产品证书,咱们如今须要测试,因此用Development证书,上线时要使用Production证书。点击Create Certificate。
接着点击continue,以下界面会让咱们选择一个CSR文件,咱们第一步建立的文件在这里派上用场了,选择那个文件,点击Generate。
将建立好的证书下载到电脑中:
至此,咱们已经有了三个文件了,分别是CSR文件,.p12文件,.cer文件。要将这三个文件放在同一个目录下。.cer文件分为测试和产品两个,须要哪一个自行选择。写了这么多,咱们的准备工做可算是作完了,不要灰心,其实你的推送工做基本上也就作完了。只是申请过程麻烦了一些,但工程的代码,咱们几乎不用怎么配置。
(1)处理证书
打开终端cd到咱们上面获得的三个文件所在的目录。
在终端执行以下命令:
$ openssl x509 -in aps_development.cer -inform der -out PushCert.pem
aps_development.cer是刚才生成的.cer文件的文件名。会在当前文件夹中生成一个pem文件,这是咱们服务端对应的证书。
再执行以下命令:
$ openssl pkcs12 -nocerts -out PushKey.pem -in key.p12
key.p12是上面生成的.p12文件的文件名。这时终端会让输入密码,这里的密码就是上面咱们设置的密钥的密码。输入密码后回车,若是密码正确,会让咱们输入新密码(必定切记),输入两次后,终端会提示成功建立PushKey.pem文件。
最后一步,将咱们生成的两个pem文件和成为一个:
$ cat PushCert.pem PushKey.pem > ck.pem
(2)测试证书是否可用
在终端执行下面的命令:
$ telnet gateway.sandbox.push.apple.com 2195
等一小会,若是终端显示下面的情形,则证书正常。
而后执行以下命令:
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushKey.pem
输入密码后回车显示以下的结果则链接成功:
在咱们项目的AppDelegate中添加以下代码:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { double version = [[UIDevice currentDevice].systemVersion doubleValue];//断定系统版本。 if(version>=8.0f){ UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound|UIRemoteNotificationTypeAlert) categories:nil]; [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; }else{ UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound; [[UIApplication sharedApplication] registerForRemoteNotificationTypes:myTypes]; } } - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{ // 处理推送消息 NSLog(@"userinfo:%@",userInfo); NSLog(@"收到推送消息:%@",[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]); } - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *) error { NSLog(@"Registfail%@",error); } -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{ NSLog(@"%@",deviceToken);//这里的Token就是咱们设备要告诉服务端的Token码 }
下面是网上搜的PHP服务端的代码:
<?php //这里填写设备的Token码 $deviceToken = '74314cc9e8f747e2fa96c2c1585c830cdf994de6b453ce9fa1c09ba396b2f9e9'; //这里是密钥密码 $passphrase = 'abcabc'; //推送的消息 $message = '这是一条推送消息'; //////////////////////////////////////////////////////////////////////////////// $ctx = stream_context_create(); stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');//ck文件 stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase); // Open a connection to the APNS server $fp = stream_socket_client( 'ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx); if (!$fp) exit("Failed to connect: $err $errstr" . PHP_EOL); echo 'Connected to APNS' . PHP_EOL; // Create the payload body $body['aps'] = array( 'alert' => $message, 'sound' => 'default' ); // Encode the payload as JSON $payload = json_encode($body); // Build the binary notification $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload; // Send it to the server $result = fwrite($fp, $msg, strlen($msg)); if (!$result) echo 'Message not delivered' . PHP_EOL; else echo 'Message successfully delivered' . PHP_EOL; // Close the connection to the server fclose($fp); ?>
把上面的PHP文件和咱们的ck文件放在同一目录下。在终端的当前目录下,执行以下命令:
$php push.php
若是咱们的设备王略正常,就可收到推送的消息了:
一、若是终端发送信息时提示密钥不可访问之类的错误,请检查是否cd到了当前目录,若是还存在问题,将密钥部分重新生成一次。
二、注意PHP代码中的字符为英文字符。
专一技术,热爱生活,交流技术,也作朋友。
——珲少 QQ群:203317592