APNS,即Apple Push Notification Service苹果推送通知服务,是苹果的服务器。

推送通知可以分为三个阶段:

第一阶段:应用程序把要发送的消息、目的iPhone的标识打包,发给APNS。

第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发送到iPhone。

第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。

1. Push的三个步骤

如下图所示:

(1)Push服务应用程序把要发送的消息、目的iPhone的标识打包,发给APNS;

(2)APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发到iPhone;

(3) iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。

具体如下图5个步骤,无论是iPhone客户端跟APNS,还是Push服务器和APNS都需要通过证书进行连接的:

2. native端代码实现

推送消息时,不同时机点击,代码调用情况:
 
1. 当程序处于关闭状态收到推送消息时,点击图标会调用- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 这个方法,那么消息给通过launchOptions这个参数获取到。

2. 当程序处于前台工作时,这时候若收到消息推送,会调用- (void)application:(UIApplication*)application

didReceiveRemoteNotification:(NSDictionary *)userInfo这个方法。

3. 当程序处于后台运行时,这时候若收到消息推送,如果点击消息或者点击消息图标时,也会调用- (void)application:(UIApplication*)application

didReceiveRemoteNotification:(NSDictionary *)userInfo这个方法。

4. 当程序处于后台运行时,这时候若收到消息推送,如果点击桌面应用图标,则不会调用didFinishLaunchingWithOptions和didReceiveRemoteNotification方法,所以无法获取消息。

(1)注册通知(当然,程序关闭,推送消息时点击图标的逻辑也应该写在这里)

// 1.注册通知
#import <UserNotifications/UserNotifications.h> - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
   if ([[UIDevice currentDevice].systemVersion floatValue] >8.0){
      //iOS8 - iOS10
[[UIApplication sharedApplication] registerForRemoteNotifications];
     [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:
                  UIUserNotificationTypeAlert |       
                  UIUserNotificationTypeSound |
                  UIUserNotificationTypeBadge categories:nil]];
   }else if ([[UIDevice currentDevice].systemVersion floatValue] < 8.0) {
    //iOS8系统以下
    [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeSound];
   }
    
    return YES;
}

补充知识点:

  iOS 程序启动时总会调用application:didFinishLaunchingWithOptions:,其中第二个参数launchOptions为NSDictionary类型的对象,里面存储有此程序启动的原因。

    • 若用户直接启动,lauchOptions内无数据;
    • 若由其他应用程序通过openURL:启动,则UIApplicationLaunchOptionsURLKey对应的对象为启动URL(NSURL),UIApplicationLaunchOptionsSourceApplicationKey对应启动的源应用程序的bundle ID (NSString);
    • 若由本地通知启动,则UIApplicationLaunchOptionsLocalNotificationKey对应的是为启动应用程序的的本地通知对象(UILocalNotification);
    • 若由远程通知启动,则UIApplicationLaunchOptionsRemoteNotificationKey对应的是启动应用程序的的远程通知信息userInfo(NSDictionary);
    • 其他key还有UIApplicationLaunchOptionsAnnotationKey,UIApplicationLaunchOptionsLocationKey,
      UIApplicationLaunchOptionsNewsstandDownloadsKey。

所以,可以根据上面的key将lauchOptions取出来:

//apple push启动
NSDictionary *applePushDic = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
//本地通知启动
UILocalNotification *localNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];

(2)获得Device Token

// 2.获得Device Token
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken{
NSLog(@"regisger success:%@", pToken);
// 注册成功,将deviceToken保存到应用服务器数据库中,因为在写向ios推送信息的服务器端程序时要用到这个
} // 3.获得Device Token失败
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {

  如果总是失败的话,即push总是到didFailToRegisterForRemoteNotificationsWithError:里面。除了我们知道的模拟器不能接受apple push,报的3010错误之外,经常会遇到“Error: Error Domain=NSCocoaErrorDomain Code=3000 "no valid 'aps-environment' entitlement string found for application" ”这个错误。解决步骤主要有以下三步:

  (2.1)确保证书开通了push的功能:

       可以在开发者网站上的App ID下查看,其Development、Distribution是否都已经开通了Push的功能。Development Push是你用Xcode调试时用的Debug使用的,Distribution的Push是正式包使用的。

      一个Bundle ID开通了Development、Distribution的push是要生成对应的两个证书的。此时,正式证书的类型是"Apple Push Services",Development对应的证书的类型是"APNs Development iOS"。你的pp文件后面也要用的是对应的证书文件。

  (2.2)确保配置文件信息正确:

      证书开通了push之后,你的配置文件要使用的是你的对应的证书,对应的app id等,都要对应起来。本地如果重新安装配置文件的话,确保老的删掉后,重新安装,重新在Target》build setting》Provision Profile下选择你刚安装的证书。能重新选择才能确定这里选择的是新的而不是旧的。PS:删除老的provision文件的方法,可以在Xcode》Preference》Accounts》对应的Apple Id,对应的Team》View Details》Provision Profile,然后点击右键就可以选择在finder中查看,可以删除对应的Provision Profile文件了。

  (2.3)确保Xcode的push设置正确:

      Target》Capabilities下面,找到你的Push Notification,确保你的push功能开着。并且"Add the Push Notification feature to your App ID"和"Add the Push Notifications entitlement to your entitlements file"这两个steps是ok的。

(3)处理推送消息

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
//4. 处理推送消息
}

Push:iOS基于APNS的消息推送的更多相关文章

  1. iOS开发如何实现消息推送机制

    一.关于推送通知 推送通知,也被叫做远程通知,是在iOS 3.0以后被引入的功能.是当程序没有启动或不在前台运行时,告诉用户有新消息的一种途径,是从外部服务器发送到应用程序上的.一般说来,当要显示消息 ...

  2. 基于SignalR的消息推送与二维码描登录实现

    1 概要说明 使用微信扫描登录相信大家都不会陌生吧,二维码与手机结合产生了不同应用场景,基于二维码的应用更是比较广泛.为了满足ios.android客户端与web短信平台的结合,特开发了基于Singl ...

  3. .NET向APNS苹果消息推送通知

    一.Apns简介: Apns是苹果推送通知服务. 二.原理: APNs会对用户进行物理连接认证,和设备令牌认证(简言之就是苹果的服务器检查设备里的证书以确定其为苹果设备):然后,将服务器的信息接收并且 ...

  4. Android 基于Netty的消息推送方案之对象的传递(四)

    在上一篇文章中<Android 基于Netty的消息推送方案之字符串的接收和发送(三)>我们介绍了Netty的字符串传递,我们知道了Netty的消息传递都是基于流,通过ChannelBuf ...

  5. Android 基于Netty的消息推送方案之字符串的接收和发送(三)

    在上一篇文章中<Android 基于Netty的消息推送方案之概念和工作原理(二)> ,我们介绍过一些关于Netty的概念和工作原理的内容,今天我们先来介绍一个叫做ChannelBuffe ...

  6. Android 基于Netty的消息推送方案之概念和工作原理(二)

    上一篇文章中我讲述了关于消息推送的方案以及一个基于Netty实现的一个简单的Hello World,为了更好的理解Hello World中的代码,今天我来讲解一下关于Netty中一些概念和工作原理的内 ...

  7. Knative 实战:基于 Kafka 实现消息推送

    作者 | 元毅 阿里云智能事业群高级开发工程师 导读:当前在 Knative 中已经提供了对 Kafka 事件源的支持,那么如何基于 Kafka 实现消息推送呢?本文作者将以阿里云 Kafka 产品为 ...

  8. 基于FCM的消息推送功能

    需求背景 我方项目需要支持客户端消息推送,iOS终端可以借由苹果本身的apns很方便的实现,但是对于Android来说,必须集成第三方的SDK来处理.考虑到项目需要以及成本,我们选择使用谷歌的FCM框 ...

  9. Easy APNs Provider 消息推送测试工具

    1.Easy APNs Provider 简介 Easy APNs Provider 是一款为 iOS.Mac App 提供推送测试的小工具. App Store 下载地址 Easy APNs Pro ...

随机推荐

  1. eclipse配置jdk的src.zip源代码步骤

    MyEclipse配置JDK的源代码的src.zip包很简单.只需要简单的几个步骤. 1.点 “window”-> “Preferences” -> “Java” -> “Insta ...

  2. 16进制ascii码转化为对应的字符,付ipmitool查询硬件信息

    最近工作需要在用ipmitool查询服务器硬件信息.ipmitool查询硬件信息 比如电源,使用命令: 获取PSU0信息:Ipmitool raw 0x3a 0x71 0x00: 获取PSU1信息:I ...

  3. Hotaru's problem(hdu 5371)

    题意:给出一个数字串,询问最长的子串,满足以下要求:将子串平均分为三部分,一三部分相等,一二部分对衬. /* 在manachar的基础上,枚举回文串的中心,再找第三部分. */ #include< ...

  4. Mysql 服务无法启动 1067

    检查my.ini中的

  5. poi导出word、excel

    在实际的项目开发中,经常会有一些涉及到导入导出的文档的功能.apache开源项目之一poi对此有很好的支持,对之前的使用做一些简要的总结. 1,导入jar 为了保证对格式的兼容性,在项目的pom.xm ...

  6. 8-04流程控制语句BEGIN ..END

     流程控制语句: 是用来控制程序流程的语句. 常用的流程控制语句的分类: 顺序结构:BEGIN...END 分支结构: IF ..ELSE 或CASE ..END 循环结构:WHILE 顺序结构 语法 ...

  7. Failed creating java D:/jre6/bin/client/jvm.dll

    Failed creating java D:/jre6/bin/client/jvm.dll 标记一下 坑爹啊! 我特么装了一个64位的eclipse 结果报错 目录下确实有这个文件. 我想说  6 ...

  8. pandas 学习(1): pandas 数据结构之Series

    1. Series Series 是一个类数组的数据结构,同时带有标签(lable)或者说索引(index). 1.1 下边生成一个最简单的Series对象,因为没有给Series指定索引,所以此时会 ...

  9. github page

    使用github page 可以查看仓库中保存的网页的事例 新建gh-pages的分支,然后点击上方的page按钮即可配置相应的链接以及地址 注:默认情况下显示的是当前文件下的index.html文件 ...

  10. 1.2 Quartz 2D 内存管理

    本文并非最终版本,如有更新或更正会第一时间置顶,联系方式详见文末 如果觉得本文内容过长,请前往本人 “简书”   通过 Product -> Analyze 来进行静态分析   可以使用Quar ...