iOS推送流程(APNS)

一、APNS(Apple Push Notification Service)

苹果推送通知服务(APNs)是推送通知的网关,iPhone ipad 对于应用程序在后台运行有诸多限制,考虑到手机电池电量,应用不允许在后台进行过多的操作。因此,当用户切换到其他程序后,原先的程序无法保持运行状态。对于那些需要保持持续连接状态的应用程序(比如社区网络应用),将不能收到实时的信息。推送是解决轮询所造成的流量消耗和电量消耗的一个比较好的解决方案

为解决这一限制,苹果推出了APNs(苹果推送通知服务 Apple Push Notification services)。APNs 允许设备与苹果的推送通知服务器保持常连接状态。当你想发送一个推送通知给某个用户的iPhone上的应用程序时,你可以使用 APNs 发送一个推送消息给目标设备上已安装的某个应用程序。

苹果的推送服务APNs基本原理简单来说就是苹果利用自己专门的推送服务器(APNs)接收来自我们自己应用服务器的需要被推送的信息,然后推送到指定的iOS设备上,然后由设备通知到我们的应用程序,设备以通知或者声音的形式通知用户有新的消息。推送的前提是装有我们应用的设备需要向APNs服务器注册,注册成功后APNs服务器会返给我们一个device_token,拿到这个token后我们将这个token发给我们自己的应用服务器,当有需要被推送的消息时,我们的应用服务器会将消息按指定的格式打包,然后结合设备的device_token一并发给APNs服务器,由于我们的应用和APNs维持一个基于TCP的长连接,APNs将新消息推送到我们设备上,然后在屏幕上显示出新消息来。

我们的设备和APNS服务器之间的通讯是基于SSL协议的TCP流通讯,二者之间维持一个长连接。

上图显示的这个消息体就是我们的服务器(Provider)发送给APNS服务器的消息结构,APNS验证这个结构正确并提取其中的信息后,再将消息推送到指定的设备。

//Payload内容
{"aps":{"alert":"一些文字","badge":"1","sound":"default",}
}

这其实就是个JSON结构体,alert标签的内容就是会显示在用户手机上的推送信息,badge显示的数量(注意是整型)是会在应用Icon右上角显示的数量,提示有多少条未读消息等,sound就是当推送信息送达是手机播放的声音,传defalut就标明使用系统默认声音,如果传比如“beep.wav”就会播放在我们应用工程目录下名称为beep.wav的音频文件,比如当手机锁屏时QQ在后台收到新消息时的滴滴声。

有这么一种情况,当我们将应用从设备卸载后,推送的消息改如何处理呢。我们知道,当我们将应用从设备卸载后,我们是收不到Provider给我们推送的消息的,但是,如何让APNS和Provider都知道不去向这台卸载了应用的设备推送消息呢?针对这个问题,苹果也已经帮我们解决了,那就是Feedback service。他是APNS的一部分,APNS会持续的更新Feedback service的列表,当我们的Provider将信息发给APNS推送到我们的设备时,如果这时设备无法将消息推送到指定的应用,就会向APNS服务器报告一个反馈信息,而这个信息就记录在feedback service中。按照这种方式,Provider应该定时的去检测Feedback service的列表,然后删除在自己数据库中记录的存在于反馈列表中的device_token,从而不再向这些设备发送推送信息。连接Feedback service的过程同样使用Socket的方式,连接上后,直接接收由APNS传输给我们的反馈列表,传输完成后断开连接,然后我们根据这个最新的反馈列表在更新我们自己的数据库,删除那些不再需要推送信息的设备的device_token。从Feedback service读取的数据结构如下:

结构中包含三个部分,第一部分是一个时间戳,记录的是设备失效后的时间信息,第二个部分是device_token的长度,第三部分就是失效的device_token,我们所要获取的就是第三部分,跟我们的数据库进行对比后,删除对应的device_token,下次不再向这些设备发送推送信息。

二、配置推送准备工作

首先要有一台苹果的设备,模拟器是不支持推送的,所以你需要一台iphone,ipod touch或者ipad。

准备CSR文件,生成带有Push Notifications功能的AppID,给该AppID的Push Notifications配置CSR,下载证书配置钥匙串,导出p12文件。
其中

证书: 内容是公钥或私钥,由其他机构对其签名组成的数据包。
Entitlements: 包含了 App 权限开关列表。
CertificateSigningRequest: 本地公钥。
p12: 本地私钥,可以导入到其他电脑。
Provisioning Profile: 包含了 证书 / Entitlements 等数据,并由苹果后台私钥签名的数据包。
  • CSR文件:
    首先我们要通过证书助手生成一个Certificate Signing Request(也就是CSR)的请求文件。


    继续之后选择保存位置,点击保存
    这时该位置上会有一个CertificateSigningRequest.certSigningRequest的请求文件,也就是我们说的CSR文件。
  • 生成带有Push Notifications功能的AppID

    在此处点+添加,按需求填写信息即可。


    这里的bundleID是识别APP的唯一ID,一个APP对应一个APP ID 也就是一个bundleID,一般采用域名反写的方式命名,输入部分的英文建议如此。
    当然也可以一个APP ID对应多的应用,为多个APP设定同一个bundleID,使用下面的Wildcard App ID设定,但是会少一些功能,例如游戏中心,内购,数据保护,iCloud。

    这里要把Push Notifications勾选上,应用才能带有推送能力。
    全部设定好之后继续,保存,生成了一个新的APP ID
    PS:当然一开始没有选上也没有关系,在我们生成的APP ID后,选择编辑,也会有勾选框可以选择增加能力。
  • 给该AppID的Push Notifications配置CSR:

    这部分是为这个APP ID配置push notifications,一个SSL Certificate可以让你手机上的notification server连接到Apple Push Notification Service(APNS)
    可以看到配置部分有两个:
    Development SSL Certificate:开发推送证书配置,开发环境可以收到推送。
    Production SSL Certificate:生辰推送证书配置,线上环境可以收到推送。
    点击Create Certificate,看完了About Creating a Certificate Signing Request (CSR)页,到达配置页

    选取之前生成的CSR文件:CertificateSigningRequest.certSigningRequest点击continue即可配置完成。
  • 下载推送证书,加到自己电脑上的钥匙串里:

    点击Download,下载开发和生产的推送证书。

    双击两个证书,会自动添加在钥匙串里去,

    找到自己的APP(后面的名字为当时设定的bundleID),右键导出p12文件,填上密码,保存。


    生成的这个p12文件,通常是给推送平台配置(自己的推送平台,或第三方推送平台,友盟等),以便他们能够发送推送通知到APNS。

这样,全部配置方面的事情就做完了。

三、App里处理推送

iOS处理生命周期和推送都在AppDelegate里面,AppDelegate继承自UIResponder,遵守UIApplicationDelegate协议,其中跟推送相关的方法都在UIApplicationDelegate协议中。包含本地推送和远程推送。

由于iOS不断更新,推送相关的配置方法也不断变化,iOS8,iOS 10分别更新了一些方法,废弃了一系列方法。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {[self registPushNotification:application];//程序未启动时,收到远程推送,保存下来,在应用进入前台后可以处理。_launchNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
}- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{[application registerForRemoteNotifications];
}- (void)registPushNotification:(UIApplication *)application
{if ([application respondsToSelector:@selector(registerForRemoteNotifications)]) { // ios8+的远程通知注册UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];[[UIApplication sharedApplication] registerUserNotificationSettings:settings];[application registerForRemoteNotifications];}else { // ios8以下SUPPRESS_DEPRECATED_WARNING([application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)]);}
}- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{[self processLocalNotification:userInfo];}- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{}

上面的方法,可以让推送达到正常使用的水平。

  1. 调用流程:

    • 应用启动
    • 注册配置
    • 注册推送
    • 注册deviceToken
    • 收到推送进行处理
  2. 推送处理流程
    处理推送必须是通过点击通知进入,收到通知,点应用进入不会触发通知处理的方法。

    • 程序未启动,收到通知,系统展示通知栏,点击进入:
      此时程序启动,会响应- (BOOL)application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary )launchOptions 方法,在该方法中,可以通过[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];拿到未启动时收到的推送信息,之后怎么处理,就按需求来了。
    • 程序已启动,在后台,收到通知,系统展示通知栏,点击进入:
      此时程序会响应- (void)application:(UIApplication )application didReceiveRemoteNotification:(NSDictionary )userInfo方法,userInfo就是需要信息内容。
    • 程序已启动,在前台,收到通知,系统不展示通知栏:
      此时程序会响应- (void)application:(UIApplication )application didReceiveRemoteNotification:(NSDictionary )userInfo方法,userInfo就是需要信息内容。

    可以看到程序在启动的情况下,不管在前台还是后台,都会进入到- (void)application:(UIApplication )application didReceiveRemoteNotification:(NSDictionary )userInfo方法中,区别只是系统会不会进行通知栏弹窗,如果想要前台弹窗,就需要自己去做效果了。
    另外可以通过application.applicationState != UIApplicationStateActive来判断当前app前后台的状态,进而分别处理。

  3. iOS 10推荐的推送处理方式:
    优点:

    • 通知处理代码可以从AppDelegate中剥离。
    • 通知的注册,设置,处理更加结构化,更易于模块化开发。
    • UserNotification支持自定义通知音效和启动图。
    • UserNotification支持向通知内容中添加媒体附件,例如音频,视频。
    • UserNotification支持开发者定义多套通知模板。
    • UserNotification支持完全自定义的通知界面。
    • UserNotification支持自定义通知中的用户交互按钮。
    • 通知的触发更加容易管理。

    引入

    #import <UserNotifications/UserNotifications.h>

使用UNUserNotificationCenterDelegate协议里的方法,

具体代码中:

- (BOOL)application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary )launchOptions{UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];// 必须写代理,不然无法监听通知的接收与点击center.delegate = self;[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {if (granted) {// 点击允许NSLog(@"注册成功");[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {NSLog(@"%@", settings);}];} else {// 点击不允许NSLog(@"注册失败");}}];
}// iOS 10收到通知
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{NSDictionary * userInfo = notification.request.content.userInfo;UNNotificationRequest *request = notification.request; // 收到推送的请求UNNotificationContent *content = request.content; // 收到推送的消息内容NSNumber *badge = content.badge;  // 推送消息的角标NSString *body = content.body;    // 推送消息体UNNotificationSound *sound = content.sound;  // 推送消息的声音NSString *subtitle = content.subtitle;  // 推送消息的副标题NSString *title = content.title;  // 推送消息的标题if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {NSLog(@"iOS10 前台收到远程通知:%@", [self logDic:userInfo]);}else {// 判断为本地通知NSLog(@"iOS10 前台收到本地通知:{\\\\nbody:%@,\\\\ntitle:%@,\\\\nsubtitle:%@,\\\\nbadge:%@,\\\\nsound:%@,\\\\nuserInfo:%@\\\\n}",body,title,subtitle,badge,sound,userInfo);}completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert); // 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以设置,Alert可以设定前台展示通知栏。
}

iOS推送流程(APNS)相关推荐

  1. java 引用Pushy 实现Apns 完成ios 推送

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一.Pushy是什么? 二.使用步骤 1.APNS 推送流程 2 设置相关配置 1.p12 证书准备 2.初始化APNSCl ...

  2. iOS原生推送(APNS)进阶iOS10推送图片、视频、音乐

    代码地址如下: http://www.demodashi.com/demo/13208.html 前言 我们首先要在AppDelegate里面进行iOS的适配,可以参考这篇文章 iOS原生推送(APN ...

  3. TUTK[Kalay][iOS]对接iOS TPNS推送流程

    1.debug版验证流程(调试版) a.改动kalay源码中的TPNSAssistant.m文件,详细请见下图 b.制作对应appid的Development push证书 访问Apple Devel ...

  4. IOS推送详解(一)------APNs

    最近项目需要做IOS推送,在网上了解了下苹果的推送过程以及接口协议. 博文会分几部分来写,先介绍下APNs,然后介绍协议(新的旧的都说下),然后介绍生成证书,最后上代码. APNS IOS推送要比安卓 ...

  5. 苹果 iOS推送 APNS(本人亲测总结)

    文章目录 1.静默推送(发透传消息)总是收不到(iOS静默通知(iOS Silent Notification):需要进一步验证 2.推送的相关方法 3.模拟推送的工具 3.1 在appstore上搜 ...

  6. iOS推送小结--swift语言

    APNS的推送机制 首先我们看一下苹果官方给出的对ios推送机制的解释.如下图 Provider就是我们自己程序的后台服务器,APNS是Apple Push Notification Service的 ...

  7. iOS 推送手机消息背后的技术

    作者:allenzzhao,腾讯  IEG运营开发工程师 消息推送我们几乎每天都会用到,但你知道iOS中的消息推送是如何实现的吗?本文将从推送权限申请,到本地和远程消息推送,再到App对推送消息的处理 ...

  8. 一步一步教你做ios推送

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

  9. 一步一步教你做ios推送 pem证书制作 php推送

    一步一步教你做ios推送 分类: ios2013-03-03 21:48 3385人阅读 评论(8) 收藏 举报 ios推送客户端服务器 最近在研究ios的推送问题,遇到了一些问题,最终整理了一下.放 ...

最新文章

  1. Java 8 Lambda
  2. Windows10选择文件打开方式没有始终允许的解决方案
  3. java mail urlname_javamail收发信件时,服务器,收发方的名称应该怎样设置才有效呢
  4. SAP ABAP实用技巧介绍系列之could not create BAdI implementation
  5. UVA - 10061 How many zero#39;s and how many digits ?
  6. java.util接口_函数接口– Java 8中java.util.function包中的函数接口
  7. 一个简单而又灵活的数据库操作类
  8. chmod命令用于更改文件或目录的所有者_Linux 修改权限命令 chmod 用法示例
  9. 三分钟学会PS小清新调色教程-萧蕊冰
  10. 把音频中的某个人声去掉_怎样去掉音频中的背景音乐 只保留人声?
  11. springboot2整合redis使用lettuce连接池(解决lettuce连接池无效问题)
  12. 关于文案、营销、生活的15条思考!
  13. android 自定义view仿通讯录
  14. 编程之美1.3-翻烙饼问题
  15. Jackson-操作XML
  16. 全球所有国家中英文名称
  17. AutoHotKey使用技巧
  18. 系统及软件迁移至移动硬盘
  19. nfc支持饭卡吗_都2020年了,听说你还在丢饭卡??
  20. 抖音霸屏系统软件 /抖音超级爆店码/抖音霸屏系统源码

热门文章

  1. Linux 练习 - 磁盘存储和文件系统
  2. 消除拖延的方法_拖延很烂—因此,这就是“吃青蛙”提高生产力的方法
  3. SRS 简单高效的实时视频服务器
  4. Gemagic Design X快捷键命令
  5. 力扣765----情侣牵手(C++异或解法)
  6. 钉钉——阿里“打入”产业互联网的尖兵连
  7. FZU-1493-ElGamal数字签名-A^X=B(%C)求x
  8. 2天赚了4个W,手把手教你用Threejs搭建一个Web3D汽车展厅 | 大帅老猿threejs特训
  9. “她时代”展示“她力量”:2022年她力量女性论坛女性消费力即战力
  10. [生成函数阶段性小结][CF891E]Lust