一、引言
ios中消息的推送有两种方式,分别是本地推送和远程推送,本地推送在这篇博客中有详细的介绍 http://www.zzvips.com/article/136226.html,这里主要讨论远程推送的流程与配置过程。
二、远程推送机制的原理
1、从一张很火的图说起
搜索ios远程推送,你总能看到一张如下的流程示意图,因为这张图确实很火,所以我也将它引用在此:
这张图示意的很清晰,大致意思是这样:你的应用服务端将消息发送到apple的apns服务器,apns服务器将消息推送到指定的iphone,最后由iphone负责将消息推送至你的app。在此先不说这个过程是如何实现的,仅仅看这个流程,你可能会觉得,在你们服务端和客户端之间增加了一个apple的apns,不是增加开发者的负担么?其实结果恰恰相反,因为apple对推送的统一管理,使我们开发者的工作变得异常简单。
2、服务端如何连接到客户端的
如果你是做android开发的,你一定非常了解长链接与心跳包。事实上,大部分的android应用的推送也确实是通过长链接来实现的。因为android系统的开放性,app是很容易做到自启动和后台长链接的,而心跳验证,就是始终保证长链接属于接通状态,然后由服务端直接推送消息。如果ios开发者也采用这种思路,就十分困难了,在ios中想要保持一个app服务始终不被系统杀死,我只能说太难了。通过上面的流程图,对比android的推送思路,我们很容易明白,ios中其实也始终有一个长链接,那就是系统本身,这个长链接始终与apns服务器相连,然后统一管理所有应用程序的推送。
3、这是ios推送机制的优势?
下面的这些,只是我个人的一些看法。系统并无优劣,优劣在于个人喜好。
1、因为推送的服务端是appleid的验证用户,推送可靠性会高。
2、所有推送消息由apns统一管理,效率高。
3、在客户端只需系统维护一个长链接,节省了用户流量消耗和手机的性能消耗,并且提高了安全性,使得有恶意推送和流氓软件的几率降低。
三、分分钟让你的app收到远程推送
1、工欲善其事、必先利其器——创建推送证书
(1)请求csr文件
在mac应用程序中找到钥匙串访问,打开它。
点击选项栏中的钥匙串访问中的证书助理:
选择从证书颁发机构申请证书:
填写电子邮件和名称,选择储存到磁盘,然后继续。
这时,我们存储的地方有了这样一个文件: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。
分分钟搞定ios远程消息推送
之后点击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文件分为测试和产品两个,需要哪个自行选择。写了这么多,我们的准备工作可算是做完了,不要灰心,其实你的推送工作基本上也就做完了。只是申请过程麻烦了一些,但工程的代码,我们几乎不用怎么配置。
2、兵马未动、粮草先行——服务端进行信息推送的设置
(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
输入密码后回车显示如下的结果则连接成功:
3、天涯海角、一步之遥——应用程序中的配置
在我们项目的appdelegate中添加如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
- ( 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服务端的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
<?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
如果我们的设备王略正常,就可收到推送的消息了:
四、几点注意
1、如果终端发送信息时提示密钥不可访问之类的错误,请检查是否cd到了当前目录,如果还存在问题,将密钥部分从新生成一次。
2、注意php代码中的字符为英文字符。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://my.oschina.net/u/2340880/blog/413584