文档章节

iOS远程推送

zh_iOS
 zh_iOS
发布于 2016/07/14 18:54
字数 2341
阅读 428
收藏 8

    最近在做基于环信的及时通讯项目,项目中必不可少的用到了远程推送功能,在我解决推送问题的过程中遇到了一些坑,同时也获得了不少的经验. 在个人理解以及查阅资料的基础上将远程推送相关的知识总结如下:

一.远程推送的原理

在码代码时我们不应该只看到屏幕,还应该看到屏幕后面的东西. 为了更好的理解远程推送,首先我们需要了解其原理.

iOS app大多都是基于C/S模式开发的,也就是 客户端/服务器模式,客户端也就是我们用来安装app的手机,服务器是为客户端提供数据用的.因为也被称为Provider . 这种模式存在一个问题,那就是当app处理Terminate状态时,两者之间是无法进行通讯的.为了解决这个问题 苹果所提供的一套服务称之为Apple Push Notification service,就是我们所谓的APNs。

  1. 推送消息传输路径: Provider-APNs-Client App

    我们的设备联网时(无论是蜂窝联网还是Wi-Fi联网)都会与苹果的APNs服务器建立一个长连接(persistent IP connection),当Provider推送一条通知的时候,这条通知并不是直接推送给了我们的设备,而是先推送到苹果的APNs服务器上面,而苹果的APNs服务器再通过与设备建立的长连接进而把通知推送到我们的设备上。而当设备处于非联网状态的时候,APNs服务器会保留Provider所推送的最后一条通知,当设备转换为连网状态时,APNs则把其保留的最后一条通知推送给我们的设备;如果设备长时间处于非联网状态下,那么APNs服务器为其保存的最后一条通知也会丢失。Remote Notification必须要求设备连网状态下才能收到。

    2.deviceToken的生成

    当一个App注册接收远程通知时,系统会发送请求到APNs服务器,APNs服务器收到此请求会根据请求所带的key值生成一个独一无二的value值,也就是所谓的deviceToken,而后APNs服务器会把此deviceToken包装成一个NSData对象发送到对应请求的App上。然后App把此deviceToken发送给我们自己的服务器,就是所谓的Provider。Provider收到deviceToken以后进行储存等相关处理,以后Provider给我们的设备推送通知的时候,必须包含此deviceToken。

这个时候你可能会问deviceToken到底是什么?有什么用?为什么是独一无二的?

  • 是什么:deviceToken其实就是根据注册远程通知的时候向APNs服务器发送的Token key,Token key中包含了设备的UDID和App的Bundle Identifier,然后苹果APNs服务器根据此Token key编码生成一个deviceToken。deviceToken可以简单理解为就是包含了设备信息和应用信息的一串编码。
  • 有什么用:上面提到Provider推送消息的时候必须带有此deviceToken,然后此消息就根据deviceToken(UDID + App's Bundle Identifier)找到对应的设备以及该设备上对应的应用,从而把此推送消息推送给此应用。
  • 唯一性:苹果APNs的编码技术和deviceToken的独特作用保证了他的唯一性。唯一性并不是说一台设备上的一个应用程序永远只有一个deviceToken,当用户升级系统,系统重刷,应用删除再安装的时候deviceToken是会变化的。

二.App应用远程推送

    1.注册推送通知

// 这里我们用的是极光推送 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
       if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
        //可以添加自定义categories
        [APService registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge |
                                                       UIUserNotificationTypeSound |
                                                       UIUserNotificationTypeAlert)
                                           categories:nil];
    } else {
        //categories 必须为nil
        [APService registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
                                                       UIRemoteNotificationTypeSound |
                                                       UIRemoteNotificationTypeAlert)
                                           categories:nil];
    }
}

    2.注册成功之后将 deviceToken传到服务器

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    // Required
    [APService registerDeviceToken:deviceToken];
}

    3.处理收到的远程推送消息

-(void)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo 

在上面的两个方法中处理收到的远程推送消息

    当App收到远程推送消息时,app不会有任何回调 ,只有用户手动点击通知栏里的通知(或者是收到通知时的弹窗)才会触发以上两个回调方法 .

  • 当app从Terminate(关闭状态) -->前台 , 此时会走第一个方法 此时 launchoptions 不为空 (平时点击app进入前台时也会调用这个方法不过此时的launchoptions为空) .  可以通过判断 launchoptions 是否为空判断是否收到了远程通知 ,然后再对通知的内容进行处理 ,比如说根据推送内容的不同跳转到不同的页面 等等...
  • 当app从后台-->前台, 此时调用第二个方法 ,在这个方法中根据推送通知的内容进行相应的处理 

    需要注意的是:如果当app处于前台时收到了远程推送通知,也会调用第二个方法,但是不会显示通知,因此在这个方法里需要我们判断程序是处于后台还是前台,并选择是否对通知进行处理.

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{

    //在这里需要判断是否在前台
    UIApplicationState state = [[UIApplication sharedApplication] applicationState];
    if (state == UIApplicationStateActive) {// 程序在前台
        // ...
    } else { // 程序在后台通过点击通知消息唤醒
        //
    }
}

iOS7之前苹果是不持之多任务的,iOS7之后开始支持多任务即App可在后台做一些更新UI、下载数据的操作等。若要接收到远程推送的时候要在后台做一些事情则需要把后台远程推送模式打开。

    设置后台模式方法项目对应TARGETS-Capabilities-Background Modes-Remote Notifications具体设置方法如下图

此方法不论App处于前台还是后台状态,收到远程推送消息的时候都会立即调用此方法。此方法需要配置后台模式并且在推送负载中必须有content-available此key值,对应的value值为1.

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo 
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {

    // 在此方法中一定要调用completionHandler这个回调,告诉系统是否处理成功

    UIBackgroundFetchResultNewData, // 成功接收到数据
    UIBackgroundFetchResultNoData,  // 没有接收到数据
    UIBackgroundFetchResultFailed   // 接受失败
    if (userInfo) {
        completionHandler(UIBackgroundFetchResultNewData);
    } else {
        completionHandler(UIBackgroundFetchResultNoData);
    }
}

三.远程推送负载内容

    远程通知负载的大小根据Provider使用的API不同而不同。当使用HTTP/2 provider API时,负载最大为4096bytes,即4kB;当使用legacy binary interface时,负载最大为2048bytes,即2kB。当负载大小超过规定的负载大小时,APNs会拒绝发送此消息。

    每一条通知的消息都会组成一个JSON字典对象,其格式如下所示,示例中的key值为苹果官方所用key。自定义字段的时候注意一定要避开这些key值。

{
     "aps" : {  
         "alert"              :              {   // string or dictionary
            "title"          :   "string"
            "body"           :   "string",
            "title-loc-key"  :   "string or null"
            "title-loc-args" :   "array of strings or null"
            "action-loc-key" :   "string or null"
            "loc-key"        :   "string"
            "loc-args"       :   "array of strings"
            "launch-image"   :   "string"
         },
          "badge"             :    number,
          "sound"             :    "string"
          "content-available" :    number;
          "category"          :    "string"
     },
}

aps:推送消息必须有的key

alert:推送消息包含此key值,系统就会根据用户的设置展示标准的推送信息
badge:在app图标上显示消息数量,缺少此key值,消息数量就不会改变,消除标记时把此key对应的value设置为0
sound:设置推送声音的key值,系统默认提示声音对应的value值为default
content-available:此key值设置为1,系统接收到推送消息时就会调用不同的回调方法,iOS7之后配置后台模式
category:UIMutableUserNotificationCategory's identifier 可操作通知类型的key值

title:简短描述此调推送消息的目的,适用系统iOS8.2之后版本
body:推送的内容
title-loc-key:功能类似title,附加功能是国际化,适用系统iOS8.2之后版本
title-loc-args:配合title-loc-key字段使用,适用系统iOS8.2之后版本
action-loc-key:可操作通知类型key值,不详细叙述
loc-key:参考title-loc-key
loc-args:参考title-loc-args
launch-image:点击推送消息或者移动事件滑块时,显示的图片。如果缺少此key值,会加载app默认的启动图片。

    当然以上key值并不是每条推送消息都必带的key值,应当根据需求来选择所需要的key值,除了以上系统所提供的key值外,你还可以自定义自己的key值,来作为消息推送的负载,自定义key值与aps此key值并列。如下格式:

{
    "aps" : {
        "alert" : "您有一条新的好友推荐",
        "badge" : 2,
        "sound" : "happy"
    },
    "Id"   : 222,               //  自定义key值
    "type" : "myType"        //  自定义key值
}

      推送是为了把我们好的资源以及最精彩内容 推送给用户,熟练并且恰当的使用APNs可以及时通知用户最新动态,提高app的活跃用户量.这次对远程推送的研究让我对它的运用更加熟练了.

    内容如果纰漏,欢迎指正.

参考:

http://www.jianshu.com/p/4b947569a548

http://www.cocoachina.com/bbs/read.php?tid-290239-uid-441468-page-1.html

© 著作权归作者所有

下一篇: MVVM介绍
zh_iOS
粉丝 27
博文 80
码字总数 36662
作品 0
石景山
程序员
私信 提问
iOS 10 的推送 User Notifications Framework

介绍 User Notifications Framework 是苹果在 WWDC 2016 推出的。iOS 10 中以前杂乱的和通知相关的 API 都被统一了,现在开发者可以使用独立的 UserNotifications.framework 来集中管理和使用...

佳妮
2018/10/30
38
1
《小印记》iOS源码分享--极光推送实践篇

笔者这几天刚完成《小印记》的推送功能,今天特分享一下在做的过程中实际解决的问题。如果读者学到了有用的东西,希望能前往App Store下载《小印记》支持一下笔者,谢谢! 《小印记》iOS源码...

_子墨
2017/03/21
133
2
Phonegap各类商业插件

【Phonegap商业插件服务】[目前插件已经支持到Phonegap最新版本] 1.phonegap-百度社会化分享-andriod插件 v2.0 【该插件支持微信分享和朋友圈分享,qq好友分享,微博分享】 2.phonegap百度社...

夜澜小雨
2015/07/15
1K
0
iOS Push详述,了解一下?

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由WeTest质量开放平台团队发表于云+社区专栏 作者:陈裕发, 腾讯系统测试工程师 商业转载请联系腾讯WeTest获得授权,非商业...

腾讯云加社区
2018/10/26
0
0
JPush APNs iOS通知推送支持 badge +1

JPush APNs Notification badge 支持 +1 的功能上线了,这对 iOS 推送通知非常有意义。 大量的 iOS 应用使用 JPush iOS 来推送通知,并且经常有群发的动作,即广播或者Tag推送。 在不支持 ba...

极光推送
2015/01/29
6.5K
2

没有更多内容

加载失败,请刷新页面

加载更多

Taro 兼容 h5 踩坑指南

最近一周在改造 公羊阅读🐏 Taro 版本适配 h5 端,过程中改改补补,好不酸爽。 本文记录📝遇到的问题,希望为有相同需求的哥们👬节约点时间。 Taro 版本:1.3.9。 client_mobile_taro...

dkvirus
今天
4
0
Spring boot 静态资源访问

0. 两个配置 spring.mvc.static-path-patternspring.resources.static-locations 1. application中需要先行的两个配置项 1.1 spring.mvc.static-path-pattern 这个配置项是告诉springboo......

moon888
今天
3
0
hash slot(虚拟桶)

在分布式集群中,如何保证相同请求落到相同的机器上,并且后面的集群机器可以尽可能的均分请求,并且当扩容或down机的情况下能对原有集群影响最小。 round robin算法:是把数据mod后直接映射...

李朝强
今天
4
0
Kafka 原理和实战

本文首发于 vivo互联网技术 微信公众号 https://mp.weixin.qq.com/s/bV8AhqAjQp4a_iXRfobkCQ 作者简介:郑志彬,毕业于华南理工大学计算机科学与技术(双语班)。先后从事过电子商务、开放平...

vivo互联网技术
今天
19
0
java数据类型

基本类型: 整型:Byte,short,int,long 浮点型:float,double 字符型:char 布尔型:boolean 引用类型: 类类型: 接口类型: 数组类型: Byte 1字节 八位 -128 -------- 127 short 2字节...

audience_1
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部