Menu

  • 博客
  • 关于唯我&博客
  • 唯我DIY
  • 讨论区

Copyright © VIIIO.COM | Theme by Theme in Progress | 基于 WordPress

千里之行,始于足下唯我 - 梦想从此起航

iOS Push Notification APNS消息推送全攻略

2016年4月15日iOS Standard
Views: 5,847

iOS 消息推送是及其重要的功能,但其配置并不如想象中的那么简单——甚至可以说比较复杂,博主在部署过程中可是遇到了不少问题。

本着分享至上的原则,本文将从零开始,一步步指引你完成消息推送的部署。

一、推送原理: APNS(Apple Push Notification Service)

iOS平台所有的消息推送都要依赖APNS(翻译过来就是苹果消息推送服务),目前虽然有很多第三方推送平台如百度云推送、极光推送等等也提供类似服务,但最终还是要依赖APNS。

消息推送流程图:

apns_01

一句话攻略:服务器(Provider)发推送请求 –> APNS确认 –> 发给指定设备(iPhone、iPad…) –> 发消息给指定App

 

但是我们的App是如何知道自己需要接收推送呢?流程如下:

apns_02

可以概括为:

1、App启动时在APNS注册推送需求(一般在didFinishLaunchingWithOptions中)

2、注册成功,返回deviceToken即推送令牌(didRegisterForRemoteNotificationsWithDeviceToken中)。在这里我们将此令牌发回自己的服务器并存储下来,证明这个设备已经可以接收消息推送啦^_^

3、服务器想推送消息时,把消息内容和deviceToken发送给APNS,其他什么都不用考虑。

 

听起来很简单,是吧?那么让我们开始进入地狱难度~

 

二、证书和授权

在此之前需要声明,推送服务不支持模拟器,所以请务必先搞到一台iPhone/iPad或其他iOS设备。

1、创建CSR,这个不是本文重点,我就直接搬运了~

打开钥匙串,然后:

csr_01

csr_02

csr_03

生成CSR文件的同时,在钥匙串中会生成常用名对应的公钥和私钥,待会会有用

csr_04

 

2、登陆苹果开发者平台,开始创建证书,地址:https://developer.apple.com/account/ios/certificate/

2.1 创建App ID,记得选Explicit App ID并且勾选Push Notifications。

appid_01

完成之后不要急,还需要创建SSL证书,此时推送功能待配置:

appid_02

点Edit进入此App的编辑页面,创建并下载相应证书,详细步骤将在下一步说明:

appid_03

 

创建完后下载之,得到aps_development.cer,双击导入钥匙串。确保Push Notifications处于Enabled状态,如图

appid_04

2.2 创建证书(接上一步,如果上一步你已经做了就不用看了,跳2.3)

cer_01

选择刚刚生成的App ID

cer_02

上传我们在第1步中制作的CSR

cer_03

cer_04

完成后下载证书,导入钥匙串

2.3 创建Profile

主要记得选择刚才的App ID,并且将自己的开发设备给选进去

profile_01

profile_02

完成后下载,双击打开

2.4 导出p12私钥

打开钥匙串,找到我们生成的CSR常用名对应私钥,导出为p12文档。导出过程中会让输入一个文档访问密码(要牢记)以及一次电脑登陆密码。

pem_01

 

至此我们得到了全部的文件:

①、pushKey.p12   ——私钥

②、aps_development.cer   ——SSL证书

③、AppID.mobileprovision  ——开发者描述文档,用于iOS项目

但想要立即进行测试则还需要进行一定处理(我们将利用一个PHP文档做简易的服务端)

 

3、证书格式转换及打包

3.1 转换SSL证书和私钥
打开终端,进入证书和私钥路径,执行以下命令

1
openssl x509 -in aps_development.cer -inform der -out PushCert.pem
1
openssl pkcs12 -nocerts -out PushKey.pem -in PushKey.p12

转换私钥时会让输入刚才导出时的密码,并设定一个新密码 囧,建议设定成一样吧不然容易混淆。

3.2 打包(php中用到)

我们已经由上一步得到了PushCert.pem和PushKey.pem,接下来把它们打包一下:

1
cat PushCert.pem PushKey.pem > ck.pem

3.4 连接测试
用自带的telnet命令连接gateway.sandbox.push.apple.com 2195,这是苹果的测试推送服务器地址。如果成功,你会看到以下输出;失败的话检查你的防火墙是否没开放2195端口

1
2
3
4
telnet gateway.sandbox.push.apple.com 2195
Trying 17.172.232.18...  
Connected to gateway.sandbox.push-apple.com.akadns.net.  
Escape character is '^]'.

 

接下来测试证书是否有效

1
2
3
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushCert.pem -key PushKey.pem
//接下来要输入一次私钥的密码
//然后是一大串输出结果

结尾是这样就算成功啦
cer_05

三、真机推送测试

用Xcode新建一个测试项目,填好Bundle Identifier并选择对应Team

test_01

Build Settings -> Code Signing设置为开发者,Provisioning Profile选择我们刚才创建的,博主被坑了很久才搞定的:

test_02

若测试过程中出现问题的话建议先删除所有Provisioning Profile,再重新来过。

接下来在AppDelegate.m文件中实现以下方法:

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
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //进行消息推送注册,iOS 8之前和现在调用方法不同,以下为兼容性写法
    if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
    {
        // iOS 8 Notifications
        [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
 
        [application registerForRemoteNotifications];
    }
    else
    {
        // iOS < 8 Notifications
        [application registerForRemoteNotificationTypes:
         (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];
    }
    return YES;
}
 
///注册成功、失败及消息接收
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
    NSLog(@"regisger success:%@",deviceToken);
    //注册成功,将deviceToken保存到应用服务器数据库中
}
 
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
    NSLog(@"Registfail%@",error);
    //注册失败
}
 
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
#if !TARGET_IPHONE_SIMULATOR
    NSLog(@"remote notification: %@",[userInfo description]);
    NSDictionary *apsInfo = [userInfo objectForKey:@"aps"];
    NSString *alert = [apsInfo objectForKey:@"alert"];
    NSLog(@"Received Push Alert: %@", alert);
    NSString *sound = [apsInfo objectForKey:@"sound"];
    NSLog(@"Received Push Sound: %@", sound);
    NSString *badge = [apsInfo objectForKey:@"badge"];
    NSLog(@"Received Push Badge: %@", badge);
    application.applicationIconBadgeNumber = [[apsInfo objectForKey:@"badge"] integerValue];
#endif
}

到此iOS工程配置完毕,连上你的手机,运行并允许接收推送。不出意外的话应该在控制台能够得到deviceToken。

test_04

开始配置简易服务端:
点此下载简易服务端PHP,解压后将pushTest.php与ck.pem放置到同一目录

1、更改$deviceToken为你的设备的deviceToken(didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken获得),注意去掉中间空格

2、更改$pass为私钥密码

3、更改pem名称,要与你打包后的文件相同(本例中为ck.pem)

4、注意当前请求地址

沙盒测试地址:tls://gateway.sandbox.push.apple.com:2195

正式环境地址:tls://gateway.push.apple.com:2195

OS X默认是可以运行php的,因此直接打开终端,导航到php文件的路径,执行命令:

1
php pushTest.php

test_03
然后就可以看到手机收到消息啦!!

test_05

test_06

四、备注 & 问题

再次附上php下载地址:点我下载

php文件修改注意:

1、现在苹果推送服务器已经不支持使用SSL连接了,全部改为TLS(不过说不定哪天又改了)

2、DeviceToken不能有空格、不能有左右尖括号,并且开发环境和正式环境的DeviceToken是不同的

3、pem应该使用打包后的(本例中为ck.pem),博主就是最开始混淆用错了,浪费了很多时间囧

4、发布证书和开发证书使用的地址是不同的,一定要搞清楚

5、$badge指消息数量(桌面图标上显示的那个)。$sound指提示音,去除的话收到消息时不会有声音。

常见问题:

1、didRegisterForRemoteNotificationsWithDeviceToken不触发

先检查手机网络是否正常,连不上网是肯定不行的。之后才考虑是配置问题,检查Build Setting是否正确。实在不行建议先删除所有Provisioning Profile,再重新来过

2、php执行成功,但手机没有收到推送

首先检查deviceToken是否正确(不能有空格、不能有左右尖括号,并且值可能有变化);然后再考虑Build Setting的问题,检查设定、检查Provisioning Profile是否匹配等。

评论

alex 2016年5月12日 at 下午5:21 - 回复

楼主好!按着你上面的步骤,我又去重新配了一个,最后PHP服务器的结果是:
63
Connection OK
Sending message :{“aps”:{“alert”:”A test message!”,”sound”:”default”,”badge”:4}}
但是手机还是死活收不到推送的消息,楼主还知道有什么原因吗?

    Vision 2016年5月17日 at 下午3:22 - 回复

    你能够得到这样的消息说明已经发送成功了,并且证书没有问题。
    1、主要侧重检查你的App工程的Bundle Id以及Build Setting -》Code Sign Identity 中各项设置是否与你的证书匹配。
    2、确认你的DeviceToken没有错误

发表评论或回复 取消回复

邮箱地址不会被公开。

63 − 56 =

近期文章

  • OC UIWindow setRootViewController切换界面引发的内存问题
  • iOS证书、AppId、PP文件之间的关系
  • SVN服务器搭建、备份及多服务器同步方案(Windows)
  • [转]iOS多线程-各种线程锁的简单介绍
  • Mac 下Apache2 配置多虚拟主机

近期评论

  • NARYTHY288954NEYRTHYT发表在《ASP.NET整合Discuz PHP站 并实现用户同步》
  • nym402059flebno发表在《ASP.NET整合Discuz PHP站 并实现用户同步》
  • nem2182758krya发表在《ASP.NET整合Discuz PHP站 并实现用户同步》
  • aresgrb.se发表在《ASP.NET整合Discuz PHP站 并实现用户同步》
  • Vincenturbam发表在《ASP.NET整合Discuz PHP站 并实现用户同步》

分类目录

  • ASP.NET (15)
  • Git (2)
  • HTML (1)
  • iOS (31)
  • Javascript (7)
  • Oracle (8)
  • SQL (3)
  • SQLSERVER (2)
  • SVN (1)
  • 一行代码系列 (5)
  • 微信小程序 (1)
  • 正则表达式 (2)
  • 网站建设 (5)

文章归档

  • 2018年12月 (1)
  • 2018年4月 (1)
  • 2017年12月 (2)
  • 2017年7月 (3)
  • 2017年6月 (1)
  • 2017年4月 (1)
  • 2017年1月 (1)
  • 2016年12月 (3)
  • 2016年10月 (1)
  • 2016年7月 (1)
  • 2016年6月 (1)
  • 2016年5月 (3)
  • 2016年4月 (5)
  • 2016年3月 (4)
  • 2016年2月 (2)
  • 2016年1月 (3)
  • 2015年12月 (11)
  • 2015年11月 (7)
  • 2015年10月 (3)
  • 2015年9月 (1)
  • 2015年8月 (1)
  • 2015年7月 (1)
  • 2015年6月 (1)
  • 2015年5月 (1)
  • 2015年4月 (1)
  • 2014年7月 (1)
  • 2014年6月 (1)
  • 2014年5月 (2)
  • 2014年4月 (2)
  • 2014年3月 (2)
  • 2014年2月 (2)
2025年5月
一 二 三 四 五 六 日
« 12月    
 1234
567891011
12131415161718
19202122232425
262728293031