iOS 推送

最近在研究ios的推送问题,遇到了一些问题,最终整理了一下。放在这里和大家分享
APNS的推送机制
首先我们看一下苹果官方给出的对ios推送机制的解释。如下图


 
Provider就是我们自己程序的后台服务器,APNS是Apple Push Notification Service的缩写,也就是苹果的推送服务器。
上图可以分为三个阶段:
第一阶段:应用程序的服务器端把要发送的消息、目的iPhone的标识打包,发给APNS。
第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发送到iPhone。
第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。
 
APNS推送通知的详细工作流程
下面这张图是说明APNS推送通知的详细工作流程:
 

根据图片我们可以概括一下:
1、应用程序注册APNS消息推送。
2、iOS从APNS Server获取devicetoken,应用程序接收device token。
3、应用程序将device token发送给程序的PUSH服务端程序。
4、服务端程序向APNS服务发送消息。
5、APNS服务将消息发送给iPhone应用程序。
 
准备工作
首先要有一台苹果的设备,模拟器是不支持推送的,所以你需要一台iphone,ipod touch或者ipad。
 
我们的客户端与苹果服务器之间和我们自己的服务器与苹果服务器之间都需要证书来进行链接。下面我们来开始进入证书的制作过程。
 
一 CSR文件
首先我们要有生成一个Certificate Signing Request(也就是CSR)的请求文件。
在应用程序里的使用工具中找到钥匙串访问。

选择从证书颁发机构请求证书

填上你的邮箱和常用名,常用名要记一下,一会会用到。然后选择保存到磁盘,继续

保存位置在桌面,点击存储。


到这里点击完成后我们会在桌面上看到一个CertificateSigningRequest.certSigningRequest的请求文件,也就是我们说的CSR文件。在我们生成CSR文件的同时,会在钥匙串访问中生成一对秘钥,名称为刚才我们填写的常用名
 
二 下载开发证书和发布证书
(这里我为了大家能看清楚,已经把之前的证书事先吊销了)
到https://developer.apple.com/devcenter/ios/index.action登录后,在右侧的ios Developer Program里点击iOS Provisioning Portal。
进入下一级页面后在左侧选择Certificates

点击红色的部分生成一个开发证书

点击选择文件,选择刚才我们生成到桌面的CSR请求文件。
注意,如果你在后面测试的时候出现了问题,请检查一下这里,这里的CSR请求文件必须是我们刚才生成的那个


选择完成后点击Submit提交

提交完成后返回页面。页面会是这样的,然后我们刷新一下页面

刷新后会出现一个下载按钮,我们点击下载。现在我们的开发证书已经配置并下载好了,发布证书的配置过程和开发证书是一致的,不再赘述。下载完后双击,会跳到钥匙串访问里。这就是我们之后要进行测的证书
 
三 配置AppID,配置并下载SSL证书
点击左侧的App IDs,找到我们要做推送功能的程序的id(如果没有的话要先New一个。注意,这里的App ID必须不能是通配的,通配的不可以做推送)。点击Configure

进入后默认推送功能是关闭的,我们需要把推送功能打开

选中打开后,点击右边灰色的Configure按钮


这里的文件同样的,还是选择我们生成在桌面上的CSR请求文件



然后点击继续

出现了我们需要的SSL证书,我们点击下载后点击Done完成。

Status状态变成了绿色可用了。这里右边的下载和上一步的下载是一样的,如果在上一步中下载了证书,便无需再次下载。此时我们有了一个名字叫aps_development.cer的SSL证书,同样,我们把他放在桌面。双击后会跳到钥匙串访问,出现我们的SSL推送证书
同样的,发布的SSL证书的步骤也是一样的。
 
四 下载Provisioning证书
在左侧选择Provisioning

配置好后点击提交(注意App ID要与我们刚的程序对应)
之后变回出现下载按钮,我们点击下载。下载后双击,并将我们的设备上的描述文件更新一下(最好把之前的全部删除,然后再安装,防止出错)。
 
五 从钥匙串访问中导出秘钥
打开钥匙串访问,找到我们的专用秘钥(专用秘钥的名称就是我们在最开始生成CSR请求的时候填写的常用名)

右键选择导出

导出的文件名我们叫做Push

在这里需要输入一个密码来对文件进行加密。这里我们选择abcabc,当然你也可以自己选择是什么,但是这个密码必须要铭记,切记!

然后输入你电脑的密码,点击允许。
这样我们就在桌面上生成了一个Push.p12文件。
 
到此为止,我们在桌面上一共生成了三个文件。一个是CSR请求文件,一个是aps_development .cer的SSL证书文件,还有一个刚才生成的Push.p12秘钥文件。
 
现在我们的准备工作已经做完了。要开始对生成的文件进行处理了。原因上面已经解释过,因为我们的服务链接苹果服务器也是需要证书的,但是我们直接生成的证书windows系统(我们一般的服务器都是win系统的)是不识别的,所以我们需要生成一个后缀为pem的带证书带秘钥的文件。
 
六 处理证书
下面我们打开终端(位置:应用程序à实用工具à终端)。
cd到桌面,我们那三个文件所在的位置
 
1、把.cer的SSL证书转换为.pem文件,执行命令:
openssl x509 -in aps_development.cer -inform der -out PushChatCert.pem
在桌面上会生成一个PushChatCert.pem文件

 
2、把私钥Push.p12文件转化为.pem文件:
openssl pkcs12 -nocerts -out PushChatKey.pem -in Push.p12
 
这里需要我们输入密码,这个密码也就是我们导出p12文件时的密码,也就是我们上面设置的abcabc。然后,需要我们对生成的pem文件设置一个密语,这里我们推荐还是用上面这个abcabc,防止混乱(当然你也可以设置成别的更有意义的密语),这里的密语是要告诉我们服务器的。这样,桌面上又会生成一个PushChatKey.pem文件

3、对生成的这两个pem文件再生成一个pem文件,来把证书和私钥整合到一个文件里:
cat PushChatCert.pem PushChatKey.pem > ck.pem
生成ck.pem文件
 
这样,我们的文件就制作完了。下面进入测试阶段
为了测试证书是否工作,执行下面的命令:
telnet gateway.sandbox.push.apple.com 2195
它将尝试发送一个规则的,不加密的连接到APNS服务。如果你看到上面的反馈,那说明你的MAC能够到达APNS。按下Ctrl+C关闭连接。如果得到一个错误信息,那么你需要确保你的防火墙允许2195端口。一般这里都不会出现什么问题。
 
下面我们要使用我们生成的SSL证书和私钥来设置一个安全的链接去链接苹果服务器:
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushChatKey.pem
执行完这一句命令后需要我们输入密语
Enter pass phrase for PushChatKey.pem:
我们输入abcabc按回车
你会看到一个完整的输出,让你明白OpenSSL在后台做什么。如果链接是成功的,你可以随便输入一个字符,按下回车,服务器就会断开链接,如果建立连接时有问题,OpenSSL会给你返回一个错误信息。
 当你在最后的时候你看到这样说明你已经成功了:
CONNECTED(00000003)
depth=1 /C=US/O=Entrust, Inc./OU=www.entrust.net/rpa isincorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust CertificationAuthority - L1C
verify error:num=20:unable to get local issuercertificate
verify return:0
---
Certificate chain
 0s:/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=iTMSEngineering/CN=gateway.sandbox.push.apple.com
  i:/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated byreference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C
 1s:/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated byreference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C
   i:/O=Entrust.net/OU=www.entrust.net/CPS_2048incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.netCertification Authority (2048)
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFGzCCBAOgAwIBAgIETBz90jANBgkqhkiG9w0BAQUFADCBsTELMAkGA1UEBhMC
……省略……
fMGbLqkGn8YogdPqe5T1
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Cupertino/O=AppleInc./OU=iTMS Engineering/CN=gateway.sandbox.push.apple.com
issuer=/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa isincorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust CertificationAuthority - L1C
---
No client certificate CA names sent
---
SSL handshake has read 2731 bytes and written 2165 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES256-SHA
    Session-ID:
    Session-ID-ctx:
    Master-Key:C7A47EED5E1F5……省略……369D4
    Key-Arg   : None
    Start Time:1361862882
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
在这里提醒一下,也许你会看到像我这样的提示:verify error:num=20:unable to get local issuercertificate
verify return:0
其实是没问题的。


七 项目测试
建立我们的推送的项目(注意BundleIdentifier必须和我们推送应用的App id一致)
在AppDelegate里didFinishLaunchingWithOptions函数里写
- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
……
  //推送的形式:标记,声音,提示
   [[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert];
   return YES;
}
 
- (void)application:(UIApplication *)applicationdidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken {
   NSLog(@"regisger success:%@",pToken);
   //注册成功,将deviceToken保存到应用服务器数据库中
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
    // 处理推送消息
    NSLog(@"userinfo:%@",userInfo);
   
    NSLog(@"收到推送消息:%@",[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]);
}
- (void)application:(UIApplication *)applicationdidFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
   NSLog(@"Registfail%@",error);
}
我们运行程序的时候会有提示,说我们的程序要发送推送通知
 
 
下面我们把php服务器代码和生成的ck.pem文件放在统一文件夹下面(这里我们还是统一放在桌面上)。
用Xcode打开(其他工具也可以)php服务器端的代码,把deviceToken改成我们现在要进行测试的iphone的deviceToken(获得方法:首先运行我们的程序,程序启动后打印的日志文件里可以看到。感谢 边玩勺子把儿去 同学的提醒),密语改成我们之前设置的abcabc。然后保存。
然后在终端运行命令(如果刚才你关闭了终端的话,最好ls一下,看看当前是不是在桌面),执行命令:
php pushMe.php
然后回车(pushMe为服务器文件名称)

如果出现这样的提示说明成功了,然后在iphone上,我们期待已久的推送消息终于来了。
以下是推送的几种效果:


 
常见问题:
1、在用证书和秘钥链接服务器时出现提示:
Error opening client certificate private key filePushChatKey.pem
20839:error:02001002:system library:fopen:No such file ordirectory:/SourceCache/OpenSSL098/OpenSSL098-44/src/crypto/bio/bss_file.c:356:fopen('PushChatKey.pem','r')
20839:error:20074002:BIO routines:FILE_CTRL:systemlib:/SourceCache/OpenSSL098/OpenSSL098-44/src/crypto/bio/bss_file.c:358:
unable to load client certificate private key file
 
解决:
文件路径不对。cd到生成的pem文件路径下再进行链接
 
2、前期测试没有问题,将ck.pem给服务器,通过服务器进行推送时推送不成功,提示链接APNS失败。
解决:一,看一下证书的名称,密语是否正确;二,路径是否正确;然后检查一下库,OpenSSL和libssl;此外apache还要开启OpenSSL权限,确保可以访问pem
 
3、APNS地址
测试地址gateway.sandbox.push.apple.com:2195
发布地址 gateway.push.apple.com:2195
测试的地址用的是沙盒,发布地址是不同的。发布软件的时候记得改过来

4、要注意顺序问题,一定要按照这个顺序来:
生成钥匙串请求 -->配置下载开发证书-->  配置App ID ,配置、下载SSL证书-->Provisioning证书

5、多注意一下红色字体部分

在此感谢曾经为此而努力过的前辈们,尤其是感谢杨大哥的帮助。
在这里附上杨大哥的帖子:http://www.cocoachina.com/bbs/read.php?tid=102110&page=1
 
另外附上几个关于推送的不错的帖子:
http://zxs19861202.iteye.com/blog/1532460
一篇很不错的帖子,老外写的
http://www.raywenderlich.com/3443/apple-push-notification-services-tutorial-part-12
中文翻译
http://article.ityran.com/archives/194
 
在过程中如果有疑问可以新浪或腾讯微博@showhilllee虽然本人是菜鸟一个,也许不能为你把问题解决掉,但是会本着菜鸟精神去帮你解决
 
转帖请注明出处:http://blog.csdn.net/showhilllee/article/details/8631734

php服务器代码pushMe.php:   http://download.csdn.net/detail/showhilllee/7208681
本文若有问题,欢迎大家斧正

官方文档地址:https://developer.apple.com/library/ios/technotes/tn2265/_index.html

全面的推送博客:http://54im.com/ios/%E6%89%8B%E6%8A%8A%E6%89%8B%E6%95%99%E4%BD%A0%E9%85%8D%E7%BD%AE%E8%8B%B9%E6%9E%9Capns%E6%8E%A8%E9%80%81%E6%9C%8D%E5%8A%A1.html

集成信鸽推送:http://www.jianshu.com/p/f464b72b106c
 
14年10月27号补充:
1、这里说下php代码问题,有些童鞋反馈说收不到消息,我记得以前测试的时候确实会有这种情况,至于原因一个是可能超时了(苹果推送也会超时的),另一个就是不明原因了。另外注意下以下几点:
1)、记得修改deviceToken,要换成你自己的
2)、修改密语
3)、生成的pem文件名称
4)、查看下当前连接的是苹果推送的测试地址还是正式地址
2、iOS8以上版本注册推送方式已经变更
[[UIApplicationsharedApplication]registerUserNotificationSettings:[UIUserNotificationSettings
                                                                            settingsForTypes:(UIUserNotificationTypeSound |UIUserNotificationTypeAlert | UIUserNotificationTypeBadge)
                                                                            categories:nil]];
        [[UIApplicationsharedApplication]registerForRemoteNotifications];

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/458548.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Bash判断文件夹(目录)是否存在

1 #!/bin/bash 2 if [ -d DirName ]; then 3 echo Dir exist 4 else 5 echo Dir not exist 6 fi 转载于:https://www.cnblogs.com/imzye/p/5059031.html

iOS 加载本地html文件详细操作

webView的加载,如果是纯文本,有内部样式的话,简单的加载请求就可以了。如下: 这种加载简单直接,易操作。 如果需要加载images,css文件 需要把xcode的项目请求路径的位置告诉webView.代码如下: 这样html文件…

HDU 5573 Binary Tree 构造

Binary Tree题目连接: http://acm.hdu.edu.cn/showproblem.php?pid5573 Description The Old Frog King lives on the root of an infinite tree. According to the law, each node should connect to exactly two nodes on the next level, forming a full binary…

志邦橱柜坑爹,志邦橱柜大忽悠,志邦橱柜欺骗

本人实实在在经历的,志邦橱柜就是个大忽悠,志邦橱柜没诚信!! 志邦橱柜先骗客户下订单,在预算时低开,到真正签合同时,不仅仅尺寸坑你,一大堆增项都会出来,原本1.5w预算到最后签合同总价到2.2w,签合同增项高开最后志邦橱柜总价超预算非常非常离谱&#xff…

多线程的那点儿事(之读写锁)

在编写多线程的时候,有一种情况是十分常见的。那就是,有些公共数据修改的机会比较少。相比较改写,它们读的机会反而高的多。通常而言,在读的过程中,往往伴随着查找的操作,中间耗时很长。给这种代码段加锁&a…

iOS获取设备IP

获取iOS设备IP wifi和流量环境下 在网上找的比较好的获取ip的代码 #include <ifaddrs.h> #include <arpa/inet.h> #include <net/if.h> #define IOS_CELLULAR "pdp_ip0" #define IOS_WIFI "en0" #define IOS_VPN …

一些不错的网站

http://www.huxiu.com/虎嗅网&#xff0c;一个关注最新创业信息的网站http://36kr.com/创业天花板https://www.zhihu.com/与世界分享你的经验http://www.mafengwo.cn/世界那么大&#xff0c;想去哪就去那http://www.mt-bbs.com/找到属于自己的设计本http://www.guokr.com/科技有…

[原]详解如何将cocos2dx项目编译到Android平台上的(方式一:Cywin+NDK)

链接地址&#xff1a;http://m.blog.csdn.net/blog/yhc13429826359/29357815 2014-6-8阅读578 评论0 前言&#xff1a;cocos2dx作为一个开源的移动2D游戏框架&#xff0c;其跨平台的特性让它备受开发公司的欢迎。这里我就不做概念性的解释了&#xff0c;通过这篇文章你就会了解…

互斥锁和读写锁的区别

原文地址&#xff1a;http://blog.csdn.NET/u012884354/article/details/46691761 相交进程之间的关系主要有两种&#xff0c;同步与互斥。 所谓互斥&#xff0c;是指散布在不同进程之间的若干程序片断&#xff0c;当某个进程运行其中一个程序片段时&#xff0c;其它进程就不能…

JSP EL表达式使用

为什么80%的码农都做不了架构师&#xff1f;>>> ##1.EL全名为Expression Language out.print(str) <%str%> ${str}例子&#xff1a; Hi! <%username%> 和 Hi! ${username}是一样的 只要是支持servlet2.4/jsp2.0的Container就都可以在jsp网页中直接使用e…

eclipse 中 Android sdk 无法更新的问题

诶&#xff0c;真是麻烦&#xff0c;想下个东西都下不了。我也好久没折腾过这个了&#xff0c;在家的电脑是早就下载好了的&#xff0c;然后如今又须要下载一份。下不到。网上搜到了资料&#xff0c;记录下来&#xff1a; 第一种方法:sdk manager - tools - option 选择强制 xx…

iOS10 xcode8 分页请求MJRefresh崩溃问题

MJRefresh出现崩溃现象 解决办法&#xff1a;类库增加判断 if (range.location ! NSNotFound) { language [language substringToIndex:range.location]; }

网络编程学习笔记一:Socket编程

from: http://blog.csdn.net/gneveek/article/details/8699198 “一切皆Socket&#xff01;” 话虽些许夸张&#xff0c;但是事实也是&#xff0c;现在的网络编程几乎都是用的socket。 ——有感于实际编程和开源项目研究。 我们深谙信息交流的价值&#xff0c;那网络中进程之间…

JavaScript原生对象常用方法总结

这是4年前学习JavaScript基础的学习笔记&#xff0c;当初是照着W3School教程学习的&#xff0c;4年恍然如云烟&#xff0c;仿佛还在昨天。现发布与此&#xff0c;留作纪念&#xff0c;纪念那段不悔的青葱岁月。下面都是我学习W3C School教程中有关JavaScript写的学习笔记&#…

[delphi]修改indy源码后重新编译

http://blog.csdn.net/nerdy/article/details/8702568 虽然indy有一身的毛病&#xff0c;但是一般情况下使用起来还是多方便的。 今天在做一个使用到indy的程序的时候&#xff0c;发现无论你怎么修改idhttp.request.accept-encoding&#xff0c;他都会在其后添加一个值 identit…

xcode8 崩溃问题

【1】、Xcode8代码出现ubsystem: com.apple.UIKit, category: HIDEventFiltered, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0 2016-09-14 17:18:…

前端工具--less篇

前端工具–less篇 less 中文网http://www.bootcss.com/p/lesscss/ 常见错误及解决&#xff1a; sublime text 3 安装less2css保存less出现错误 未安装这个 npm install -g less-plugin-clean-css 未安装这个 npm install less -gd less语法 LESS 做为 CSS 的一种形式的扩展&a…

从static变量导出问题解析 __declspec(dllexport) 和 __declspec(dllimport)的作用

这段时间要把tinyxml从静态库弄成动态库&#xff0c;要用到__declspec(dllexport)和__declspec(dllimport)来导出dll和lib文件。终于弄明白了export和import的作用&#xff0c;下面从使用的角度来说明一下他们的功能。 首先要知道&#xff0c;头文件是C的接口文件&#xff0c;不…

4月26日作业

2016年4月26日作业 一、项目整体绩效评估1、*三E审计是什么的合称&#xff1f;&#xff08;记&#xff09; 答&#xff1a;经济审计&#xff0c;效率审计和效果审计2、霍尔三维结构是从哪三个方面考察系统工程的工作过程的&#xff1f; 答&#xff1a;逻辑&#xff0c;时间和知…

xcode8 快捷键失效

因为苹果解决xcode ghost,把插件屏蔽了。 解决方法: 命令运行&#xff1a; sudo /usr/libexec/xpccachectl 然后必须重启电脑后生效