APNS的推送机制

与Android上我们自己实现的推送服务不一样,Apple对设备的控制很严格。消息推送的流程必需要经过APNs:

这里 Provider 是指某个应用的Developer,当然假设开发人员使用AVOS Cloud的服务,把发送消息的请求托付给我们,那么这里的Provider就是AVOS Cloud的推送服务程序了。

上图能够分为三步:

第一步:AVOS Cloud推送服务程序把要发送的消息、目的设备的唯一标识打包,发给APNs。

第二步:APNs在自身的已注冊Push服务的应用列表中,查找有对应标识的设备。并把消息发送到设备。

第三步:iOS系统把发来的消息传递给对应的应用程序,而且依照设定弹出Push通知

为了实现消息推送,有两点很重要:

1,App的推送证书

要能够完整实现一条消息推送,须要我们在App ID中打开Push Notifications,须要我们准备好Provisioning Profile和SSL证书。而且一定要注意Development和Distribution环境是须要分开的。最后。把SSL证书导入到AVOS Cloud平台。就能够尝试远程消息推送了。详细的操作流程能够參考我们的使用指南:iOS推送证书设置指南

2,设备标识DeviceToken

知道了谁要推送,或者说要推送给哪个App之后,APNs还须要知道推到哪台设备上,这就是设备标识的作用。获取设备标识的流程例如以下:

第一步:App打开推送开关。用户要确认TA希望获得该App的推送消息

第二步:App获得一个DeviceToken

第三步:App将DeviceToken保存起来,这里就是通过[AVInstallation saveInBackground]将DeviceToken保存到AVOS
Cloud

第四步:当某些特定事件发生。开发人员托付AVOS Cloud来发送推送消息。这时候AVOS Cloud的推送server就会给APNs发送一则推送消息,APNs最后消息送到用户设备

推送相关的几个概念

消息类型

一条消息推送过来,能够有例如以下几种表现形式:

  • 显示一个alert或者banner。展现详细内容
  • 在应用icon上提示一个新到消息数
  • 播放一段声音

    开发人员能够在每次推送的时候设置。在推送达到用户设备时开发人员也能够选择不同的提示方式。

    本地消息通知

    iOS上有两种消息通知,一种是本地消息(Local Notification),一种是远程消息(Push Notification,也叫Remote Notification),设计这两种通知的目的都是为了提醒用户,如今有些什么新奇的事情发生了。吸引用户又一次打开应用。

    本地消息什么时候实用呢?譬如你正在做一个To-do的工具类应用。对于用户增加的每个事项,都会有一个完毕的时间点,用户能够要求这个To-do应用在事项过期之前的某一个时间点提醒一下TA。

    为了达到这一目的。App就能够调度一个本地通知,在时间点到了之后发出一个Alert消息或者其它提示。

    我们在处理推送消息的时候。也能够综合运用这两种方式。

    代码里面怎样实现推送

    首先,我们要获取DeviceToken。

    App须要每次启动的时候都去注冊远程通知——通过调用UIApplication的registerForRemoteNotificationTypes:方法,传递给它你希望支持的消息类型參数就可以,比如:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    // do some initiale working
    ... [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];
    return YES;
    }

    假设注冊成功,APNs会返回给你设备的token。iOS系统会把它传递给app delegate代理——application:didRegisterForRemoteNotificationsWithDeviceToken:方法,你应该在这种方法里面把token保存到AVOS
    Cloud后台。比如:

    - (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSLog(@"Receive DeviceToken: %@", deviceToken);
    AVInstallation *currentInstallation = [AVInstallation currentInstallation];
    [currentInstallation setDeviceTokenFromData:deviceToken];
    [currentInstallation saveInBackground];
    }

    假设注冊失败,application:didFailToRegisterForRemoteNotificationsWithError:方法会被调用,通过NSError參数你能够看到详细的出错信息,比如:

    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"注冊失败,无法获取设备ID, 详细错误: %@", error);
    }

    请注意,注冊流程须要在app每次启动时调用。这并不不会带来额外的负担。由于iOS操作系统在第一次获得了有效的device token之后,会本地缓存起来,以后app再调用registerForRemoteNotificationTypes:的时候会立马返回,并不会再进行网络请求。另外。app层面不应该对device token进行缓存,由于device token也有可能变化——假设用户重装了操作系统。那么APNs再次给出的device token就会和之前的不一样,又或者是,用户restore了原来的backup到新的设备上,那么原来的device
    token也会失效。

    其次,我们要处理收到消息之后的回调

    我们能够设想一下消息通知的几种使用场景:

    1,在app没有被启动的时候,接收到了消息通知。这时候操作系统会依照默认的方式来展现一个alert消息。在app icon上标记一个数字,甚至播放一段声音。

    2,用户看到消息之后。点击了一下actionbutton或者点击了应用图标

    假设actionbutton被点击了,系统会通过调用application:didFinishLaunchingWithOptions:这个代理方法来启动应用。而且会把notification的payload数据传递进去。

    假设应用图标被点击了。系统也一样会调用application:didFinishLaunchingWithOptions:这个代理方法来启动应用,唯一不同的是这时候启动參数里面不会有不论什么notification的信息。

    演示样例代码例如以下:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    // do initializing works
    ... if (launchOptions) {
    // do something else
    ... [AVAnalytics trackAppOpenedWithLaunchOptions:launchOptions];
    } [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound]; return YES;
    }

    3,假设远程消息发送过来的时候。app正在执行。这时候会发生什么呢?

    app代理的application:didReceiveRemoteNotification:方法会被调用,同一时候远程消息中的payload数据会作为參数传递进去。

    演示样例代码例如以下:

    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    if (application.applicationState == UIApplicationStateActive) {
    // 转换成一个本地通知,显示到通知栏,你也能够直接显示出一个alertView。仅仅是那样稍显aggressive:)
    UILocalNotification *localNotification = [[UILocalNotification alloc] init];
    localNotification.userInfo = userInfo;
    localNotification.soundName = UILocalNotificationDefaultSoundName;
    localNotification.alertBody = [[userInfo objectForKey:@"aps"] objectForKey:@"alert"];
    localNotification.fireDate = [NSDate date];
    [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
    } else {
    [AVAnalytics trackAppOpenedWithRemoteNotificationPayload:userInfo];
    }
    }

    常见问题FAQ

    我能推送长消息吗

    不能,APNs限制了每一个notification的payload最大长度是256字节,超长的消息是不能发送的。

    推送怎么加声音提醒

    消息推送是能够指定声音的。譬如你能够对正面的反馈使用欢快的声音,对负面的反馈使用低沉一点的声音,都能够达到别出心裁让人眼前一亮的目的。

    你须要先放一些aiff、wav或者caf音频文件到app的资源文件里。然后在推送的时候指定不同的音频文件名称就能够了。

    推送的Badge是怎么回事

    推送并不一定会导致应用图标上红色数字添加,是否显示这一数字,显示成多少。都取决于开发人员自己。

    在发送推送消息的时候,我们能够选择是否递增这一数字;假设不选择这一项。那么消息推送并不会导致应用图标上红色数字的出现。



    好。如今问题来了。这个数字假设搞出来了,怎么让它消失掉呢?

    事实上我们仅仅须要在不论什么时候设置 UIApplication.applicationIconBadgeNumber 属性为0,就能够让这个数字消失掉。

    一般我们会选择在应用启动的时候(application:didFinishLaunchingWithOptions:方法中)。或者干脆一点,在应用每次被切换到前台的时候(applicationWillEnterForeground:方法中),调用这一行代码。就可以立马清除掉Badge数字了。

    AVOS Cloud平台发出去的通知格式到底是什么样子的

    对于每一条推送消息。都包括一个payload,一般是组成了一个JSON的Dictionary,这当中不可缺少的是aps属性,它相应的value也是一个Dictionary,包括以下一些内容:

  • alert消息(文本或Dictionary)
  • 应用图标上的红色数字
  • 播放的声音文件名称

    在由推送激活的app打开事件中,application:didFinishLaunchingWithOptions:的options參数就是这个大的Dictionary对象。

    {
    aps = {
    alert = "hello, everyone";
    badge = 2;
    sound = default;
    };
    }

    这里要注意的时alert部分。它的值能够是一个String(文本消息),也能够是一个JSON的Dictionary。当它是文本消息的时候,系统就会把这些文字显示到一个alertview中;假设它也是由一个JSON Dictionary组成的话。其格式例如以下:

  • body
  • action-loc-key
  • loc-key
  • loc-args
  • launch-image

    body部分就是alertView中将要展现出来的文本消息,loc-属性主要是用来实现本地化消息,launch-image仅仅是app主bundle里的一个图片文件的名称。一般来说我们不指定这一属性。

    怎样显示本地化的消息

    有两种办法能够实现推送消息的本地化:

    1,在推送的payload中使用loc-key和loc-args来指定进行本地化,这样Provider方仅仅须要依照统一的格式来发送就可以。消息的解析和组装则由client来完毕。

    2。假设推送的payload里面不包括loc-key/loc-args信息。那么Provider方就须要自己做本地化处理,然后给不同的device发送不同的消息。为了做到这一点,还须要app在上传device token的时候也把用户的语言设置信息传回来。

    眼下,由于AVOS Cloud主要就是瞄准中国大陆市场和海外中文用户。所以我们在推送上还不提供多语言支持。

    应用该怎么响应推送消息

    上面说的处理流程。仅仅能简单展示一下远程消息,激活用户让他们又一次回到app中来。可是有时候。我们希望带给用户更好的使用体验。譬如假设我们告诉用户:张三刚刚评论了你的照片。这时候用户假设点击actionbutton进入app。我们是展示详细的评论页面为好,还是展示通常的启动页面然后让用户自己去找张三的评论好?我想负责任的开发人员都会选择前者:)

    要做到灵活响应不同类型的通知消息,我们须要在通知的payload中添加很多其它信息,而不能只唯独alert出来的文字信息。

    对于AVOS Cloud消息推送平台来讲。就须要开发人员使用更高级功能的JSON格式。譬如我们发送这种json字符串

    {"action":{"type":4},"alert":"hello, everyone”} 终于在app内会收到这种UserInfo Dictionary:

    {
    action = {
    type = 4;
    };
    aps = {
    alert = "hello, everyone";
    badge = 4;
    };
    }

    “hello, everyone”会显示到alertView中,可是整个Dictionary会通过launchOptions传递给application: didFinishLaunchingWithOptions: 方法,这样我们在程序里面就能够对不同的消息实现不同的跳转了。

  • http://blog.csdn.net/kylinbl/article/details/6729369

  • 细说 iOS 消息推送的更多相关文章

    1. iOS 消息推送(APNs) 傻瓜式教程

      也可以去我的简书页面查看这篇文章 首先: 1.做iOS消息推送需要真机测试 2.做iOS消息推送需要有付费的开发者账号 是否继续看帖? 先学习一下相关的知识吧! 因为中途可能会遇到一些问题,这篇文章或 ...

    2. Ios 消息推送

      手把手教你做iOS推送 http://www.cocoachina.com/industry/20130321/5862.html http://www.cnblogs.com/cdts_change ...

    3. (转)iOS消息推送机制的实现

      原:http://www.cnblogs.com/qq78292959/archive/2012/07/16/2593651.html iOS消息推送机制的实现 iOS消息推送的工作机制可以简单的用下 ...

    4. 【iOS】iOS消息推送机制的实现

      iOS消息推送的工作机制可以简单的用下图来概括: Provider是指某个iPhone软件的Push服务器,APNS是Apple Push Notification Service的缩写,是苹果的服务 ...

    5. iOS消息推送机制

      iOS消息推送的工作机制可以简单的用下图来概括: Provider是指某个iPhone软件的Push服务器,APNS是Apple Push Notification Service的缩写,是苹果的服务 ...

    6. (转)iOS消息推送机制中pem文件的生成

      转自:http://2015.iteye.com/blog/1567777 以前写了一篇文章:iOS消息推送机制的实现,这篇文章中生成的是p12文件,但是php是用的pem文件,生成的方法和p12文件 ...

    7. [置顶] 手把手教你iOS消息推送证书生成以及Push消息

      iOS推送消息是许多iOS应用都具备的功能,今天在给应用加推送功能,在生成证书的过程中,发生了各种令人蛋痛的事.下面就把步骤拿出来分享下: iOS消息推送的工作机制可以简单的用下图来概括: Provi ...

    8. 了解iOS消息推送一文就够:史上最全iOS Push技术详解

      本文作者:陈裕发, 腾讯系统测试工程师,由腾讯WeTest整理发表. 1.引言 开发iOS系统中的Push推送,通常有以下3种情况: 1)在线Push:比如QQ.微信等IM界面处于前台时,聊天消息和指 ...

    9. 【转】iOS消息推送实现过程记录

      客户端代码:链接地址 服务器代码:链接地址  链接地址 这里记录下iOS消息推送实现的全过程 首先,申请秘钥. 之后进入链接地址开发者,当然你得有啊!!!!! 点击这里 如图: 下面实现创建推送证书( ...

    随机推荐

    1. 再谈CLR查找和加载程序集的方式

      原文:再谈CLR查找和加载程序集的方式 这是一个老问题,以前也有朋友写过一些文章介绍,但可能还不是很全面.我也多次被人问到,这里结合案例再次谈谈,希望对大家有所帮助. 本文范例代码可以通过这里下载 h ...

    2. 金融项目java开发_BigDecimal(解决计算精度问题)

      当使用double进行商业运算时,double计算会丢失精度.可以使用BigDecimal进行计算. import java.math.BigDecimal; import org.junit.Tes ...

    3. HDU——T 2818 Building Block

      http://acm.hdu.edu.cn/showproblem.php?pid=2818 Time Limit: 2000/1000 MS (Java/Others)    Memory Limi ...

    4. HDU 4183Pahom on Water(网络流之最大流)

      题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4183 这题题目意思非常难看懂..我看了好长时间也没看懂..终于是从网上找的翻译. .我就在这翻译一下吧 ...

    5. js实现小时钟,js中Date对象的使用?

      介绍一下js中Date对象的使用 dateObj = new Date() dateObj = new Date(dateValue) dateObj = new Date(year,month,da ...

    6. Entity Framework之Model First开发方式

      一.Model First开发方式 在项目一开始,就没用数据库时,可以借助EF设计模型,然后根据模型同步完成数据库中表的创建,这就是Model First开发方式.总结一点就是,现有模型再有表. 二. ...

    7. Coderfroces 864 E. Fire(01背包+路径标记)

      E. Fire http://codeforces.com/problemset/problem/864/E Polycarp is in really serious trouble — his h ...

    8. SQL一列的合并连起来

      CREATE TABLE #temp( ID INT, name NVARCHAR(max), age int, address ) ) insert into #temp select ID, na ...

    9. docker升级&加速器配置

      默认使用yum或者apt安装的docker版本较老,可以通过以下方式进行升级: 1.卸载旧版本 [root@CentOS702 ~]# centos 7.3卸载docker[root@CentOS70 ...

    10. Debounce 和 Throttle【转载】

      在处理诸如 resize.scroll.mousemove 和 keydown/keyup/keypress 等事件的时候,通常我们不希望这些事件太过频繁地触发,尤其是监听程序中涉及到大量的计算或者有 ...