iOS Push详述,了解一下?

2023-11-17

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~

本文由WeTest质量开放平台团队发表于云+社区专栏

作者:陈裕发, 腾讯系统测试工程师

商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处。

原文链接:http://wetest.qq.com/lab/view/380.html

WeTest 导读


本文主要对iOS Push的在线push、本地push及离线(远程)push进行梳理,介绍了相关逻辑,测试时要注意的要点以及相关工具。小小的Push背后蕴藏着大大的逻辑!


Push种类

一、在线push


在线push:当用户在线(APP在前台)时,收到的状态栏的消息提醒,称为在线push。这个功能与苹果系统无关,是我们自己的APP开发的一种功能,该push与设置中是否打开“通知”无关。

这里以iOS Qzone为例,当APP在前台时,自己发的说说被点赞了,收到的在线push如下:

img1.png

              Qzone在线push 

二、离线(远程)push


离线push:当APP在离线(kill掉进程、切到后台、锁屏)时,收到的消息提醒,称为离线push。离线push是需要经过苹果的APNs服务器才可以推送到某台设备的某个APP上的,这是和本地push的本质区别。push与设置中是否打开“通知”有关。

这里最简单的以大家常用的手机QQ为例,当APP在后台、锁屏或者被kiil了进程时,收到了消息:

img2.png

   离线push 

1、静默push

静默push用的场景不较少,这里只做简要介绍。

首先我们看看离线(远程)push与静默push的区别:

普通离线(远程)push:收到推送后(有文字有声音),点开通知,进入APP后,才执行-- (void)application:(UIApplication didReceiveRemoteNotification:(NSDictionary fetchCompletionHandler:(void result))handler )application )userInfo (^)(UIBackgroundFetchResult

静默push:收到推送(没有文字没有声音),不用点开通知,不用打开APP,就能执行(void)application:(UIApplication )application)userInfo didReceiveRemoteNotification:(NSDictionary fetchCompletionHandler:(void (^)(UIBackgroundFetchResultresult))handler,用户完全感觉不到。

所以静默push又被我们称做 Background Remote Notification(后台远程推送)。静默推送是在iOS7之后推出的一种推送方式。它与其他推送的区别在于允许应用收到通知后在后台(background)状态下运行一段代码,可用于从服务器获取内容更新。

三、本地push


本地push:本地推送和远程推送的功能是一样的,都是要提醒用户去做某些事情。但是和远程推送不同的就是本地推送是不需要设备联网的,而远程推送是必需要设备联网的,因为只有联网状态下,才能和苹果的APNs服务器建立长连接,从而推送消息。本地推送是由App自己设定的,并且发送给安装此App的这台设备,属于一对一的对应关系。比较典型的应用是闹钟类似的场景。该push与设置中是否打开“通知”有关。

最容易看到本地push的场景,可以直接在手机设置一个计时器,计时器时间到了就会弹出本地push:

img3.png

         本地push

img4.png

由于本地push原理和作用相对于在线push和离线push都更为简单明了,下文主要介绍在线push和离线push。

本地push实现

一、 iOS10以前本地push弹出方式


试验过iOS10以前的本地push方法在iOS10+的系统也能使用,不过可能有些参数不生效。

1、立即展示( iOS10以前)

本地push稍微简单,有两种方式可以调用,一种是presentLocalNotificationNow方法,立即展示本地push:

img5.png

2、延迟展示( iOS10以前)

另一种是用scheduleLocalNotification方法按计划来弹本地推送:

img6.png

如果使用这种方法,需要对推送的时间进行设置,举个例子,设为5秒后:

img7.png

二、设置本地push内容( iOS10以前)


img8.png

其中alertBody是消息内容锁屏与不锁屏时效果如下:

img9.png

     本地push效果

applicationIconBadgeNumber是消息数量,我们可以看到这里设置为66:

img10.png

      消息数

三、处理本地push ( iOS10以前)


1、 App没有启动情况下处理本地push

这种情况下,当点击通知时,会启动App,而在App中,开发人员可以通过实现AppDelegate中的方法:- (BOOL)application:(UIApplication)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions,然后从lauchOptions中获取App启动的原因,若是因为本地通知,则可以App启动时对App做对应的操作,比方说跳转到某个画面等等。

img11.png

2、App运行在后台及前台

上面的2种情况的处理基本一致, 不同点只有当运行再后台的时候,会有弹窗提示用户另外一个App有通知,对于本地通知单的处理都是通过AppDelegate的方法:- (void)application:(UIApplication )application didReceiveLocalNotification:(UILocalNotification *)notification来处理的。

img12.png

四、iOS10以后本地push弹出方式


iOS10以后,本地通知可以由使用 UNUserNotificationCenter来管理。

创建方法:

img13.png

接下来需要需创建一个包含待通知内容的 UNMutableNotificationContent 对象:

img14.png

在iOS上可以通过以下几种触发器来触发本地push:

● UNCalendarNotificationTrigger 传送本地通知的日期和时间。

● UNTimeIntervalNotificationTrigger 传递本地通知之前必须过期的时间。

● UNLocationNotificationTrigger 用户必须达到的地理位置才能提供本地通知。

● UNPushNotificationTrigger 表示通知是从Apple推送通知服务发送的对象。

假如以时间间隔(TimeInterval)来触发,则设置触发器代码为:

img15.png

推送本地push的代码为:

img16.png

在线、离线(远程)push流程

一、在线push流程


在线push相对简单,因为是内部实现,具体流程如上面所示。

1、判断app是否在线

此处可以根据APP自身的后台策略如上一次与后台交互的时间等方法来判断APP是否在线或者离线。认为在线,会发送在线push,否则,发送离线push。

2、在线push特点

● 在线push有以下几个特点:

● 不需要经过苹果APNs。

● 需要自己实现长链接。

● 代码在app内部实现。

二、离线(远程)push流程


img17.png

离线push流程

主要流程为:

● 服务器端将消息先发送到苹果的APNs

● 由苹果的APNs将消息推送到客户的设备端

● 由iOS系统将接收到的消息传递给相应的App。

简而言之离线push是苹果系统的行为,与app状态无关,能够直接推送到指定手机的指定app。

在进一步了解离线push前,我们有必要先了解几个名词。

1、离线push名词解释

—APNs

APNs:Apple Push Notification service(苹果推送通知服务)。

APNs主要用于以下场景:当用户主动杀掉 APP,或者 APP 进入后台超过约定时长时,APP会被kill,这样保障了前台 APP 的流畅性,也延长了手机的使用时长,获得了较好的用户体验,但是这也意味着,服务器无法主动和用户交互(如推送实时消息等),所以苹果推出了 APNs,允许设备和服务器分别与苹果的推送通知服务器保持长连接状态。

关于APNs的更新有以下几点

● iOS 8以后,APNs推送的字节是2k,iOS8以前是256字节

● iOS 9以后APNs支持HTTP/2协议栈,优化长连接,具有标准的HTTP返回和管道复用技术

● iOS 10以后,推送的字节是4k,APNs可根据推送消息的唯一标示符查询某条消息是否被用户阅读,可更新某一推送消息,而不用发重读的多条消息

关于APNs更全面的介绍可以看官方文档:

https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html#//apple_ref/doc/uid/TP40008194-CH8-SW1

—payload

什么是payload?对于每一条发送给APNs的推送消息,都包含一个payload,通常是组成了一个JSON的Dictionary,这其中必不可少的是aps属性,它对应的value也是一个Dictionary,包含一些但不限于以下内容:标题、副标题、内容、附件、category等,如

img18.png

—device token

什么是device token?我们看一下官方的简介:

device token: APNs uses device tokens to identify each unique app and device combination. It also uses them to authenticate the routing of remote notifications sent to a device.(device token是APNs用于区分识别每个iOS设备和设备上不同app的一个标识符,还可以用于APNs通过它将推送消息路由到指定设备上)

即:device token里包含了device id和bundle id的信息,但是device id和bundle id不会确定唯一的device token。

但是,这里有个坑,查资料得知,iOS8及之前的iOS系统,对于同一部手机,如果卸载后重装APP的话,device token是不会变的,在token变了以后,老的token,就被认为是无效了,苹果不会对这部分无效的token推送。但是,对iOS9及以后的iOS系统,对于同一部手机,卸载后重装APP的device token是会发生变化的,而且老的token不会无效,还可以正常推送,这应该是苹果的一个bug,但是苹果也没有修复这个问题,所以这个需要开发者自己来解决,否则容易出现一个app收到多个push的问题。官方的说法是:

To protect user privacy, do not use device tokens to identify user devices. Device tokens change when the user updates the operating system and when a device’s data and settings are erased. As a result, apps should always request the current device token at launch time.(即此举为了保护用户隐私,device token会在更新系统、擦除设置重置后变化,在一定时间后会过期)

2、离线push详细流程

知道了以上概念后我们重新来看一下离线(远程)push的详细流程:

img19.png

    离线push详细流程
  1. 首先是应用程序注册消息推送。

  2. iOS跟APNS Server要deviceToken。应用程序接受deviceToken。

  3. 应用程序将deviceToken发送给PUSH服务端程序。

  4. 服务端程序向APNS服务发送消息。

  5. APNS服务将消息发送给iPhone应用程序。

值得注意的是,当由于用户反复卸载重装程序(虽然概率很小)等原因导致多个device Token指向同一台设备的同一个app,又把多个device Token发给APNs时,用户就会收到多条push。苹果APNs是不会对多个device Token是否指向同一台设备的同一个app做校验的,所以需要后台来做去重等处理保证用户不会收到多条push。

三、对离线(远程)push的响应


1、iOS 7以上对离线(远程)push时的响应

iOS 7以上关于接受离线push有两个函数

img20.png

那么这两个函数有什么区别呢?其实这两个方法都是用来处理离线push的。

差别就是,如果app在前台是收到离线(远程)push,那么就会调用

img21.png

相对的,如果在后台或者杀进程情况下,点击收到的离线push,那么就会调用,如果没有实现

img22.png

则会调用

img23.png

若实现了前者,就只调用前者。

2、iOS 10以上对离线(远程)push的响应

iOS10对push的处理主要增加了两个方法

img24.png

其中前者是对APP在前台时收到push时的处理,后者是点击push进入APP执行的函数。

用得比较多的是后者,我们可以举个例子,点击push进入APP后如何获取push的消息、角标、标题等内容:

img25.png

iOS 10关于push的一些新特性

iOS10新增的UserNotifications框架,主要有了这样几方面的更新:

● 用UserNotifications框架替换了原先与通知相关的接口,通知文字可分为title、subtitle和body三部分,通知可携带附件

● 系统在展示通知之前,可以唤起app附带的service extension,并且允许它改动通知的内容

● 用户在对通知右滑查看、下拉或者3d touch的时候,通知会展开,展开后页面的布局可以由app附带的content extension来决定

一、push的多样性


iOS10以前的push只有文字,甚至没有标题。

iOS10以后的push更加多样化,可以有主标题,副标题,甚至还有附件,这里以我司的腾讯新闻为例(有标题,内容,和附件):

img26.png

 腾讯新闻push

3D touch点入详情以后:

img27.png

   腾讯新闻push详情

这里我们惊奇的发现,除了可以携带图片这样的附件、push还能展开详情以外,进入详情以后,下面还多了“打开”、“收藏”、“不感兴趣”这些选项,这里就涉及到以下iOS10的新特性。

二、push携带附件


因为payload有大小限制,所以如果remote notification想要携带附件,那么payload上只能带上如附件下载地址之类的信息,等通知到达客户端后由service extension下载附件到本地,然后在初始化UNNotificationAttachment对象时传入附件在本地的URL。

img28.png

初始化UNNotificationAttachment对象时,可以传入option参数。这里的option参数可以强制指定附件的类型,可以选择是否展示缩略图,以及缩略图截取自附件的哪一帧、哪一部分。

目前iOS10通知只将几种格式的图片、音频和视频作为附件,附件的大小也有一定限制,具体可以看官方文档中的限制说明。

关于附件的更加详细的说明,可以参考官方文档:

https://developer.apple.com/documentation/usernotifications/unnotificationattachment?language=objc

三、携带action的通知


上面提到的“打开”、“收藏”、“不感兴趣”这些选项其实就是push携带的action,其实从iOS8开始,通知已经可以携带action了。而在iOS10中,通知的action被放在了更明显的位置,与action相关的接口也有了很大变化。

决定一个通知应该有哪些action呢?在payload中,这是由category字段决定的。如果我们希望一个通知能携带若干个action,我们就需要将若干个action和一个category绑定起来。通知到达前端后,系统会根据category的名字来决定要给这个通知展示哪些action:

img29.png

怎么得知用户选了哪个action并做出相应操作呢?这需要给UNUserNotificationCenter指定一个delegate:

img30.png

然后在delegate的类中实现

img31.png

**方法:**通过response.notification.request.content.categoryIdentifier和response.actionIdentifier就可以得知用户选择的action了。

四、改变push内容


这里主要讲应用的比较多的离线(远程)push的改变push方法

1、改变本地push内容

本地push,只要request的id一样,那么就可以更新推送:

更新的例子:

img31.png

img32.png

此外,还有删除所有推送等,都在UNUserNotificationCenter.h中实现。

2、改变离线(远程)push内容

目前远程push只支持更新push内容,更新需要通过新的字段apps-collapse-id来作为唯一标示。方法是在HTTP/2 请求头中使用相同的apns-collapse-id,这样收到同样的apns-collapse-id的push时,push内容便会更新。

使用场景:比较容易理解的一个场景就是球赛比分,比如现在是1:0,如果变成1:1的话,只需要刷新原来的新闻,这样用户就不会因为同一场比赛收到多条push。

五、两个extension


有两个与push相关的extension,可能我们会好奇这两个extension有什么不同,为什么需要两个?它们分别实现什么功能呢?

img33.png

    push相关extension

1、notification service extension

给app添加notification service extension后,系统会在收到通知后唤醒它,并允许它修改通知的内容,之后再展示这个通知。

service extension只对remote notification起作用,local notification是无法唤起它的。

如果想要让系统唤起service extension的话,payload必须符合这样几个条件:

  1. 必须增加mutable-content字段并为1,这表示允许客户端修改这个通知:

payload(举例)如下:

img34.png

2)这个通知必须展示一个alert,如果只是一个修改badge的通知的话,是不会唤起service extension的

3)静默推送是不能唤起service extension的,所以payload中不能有”content-available” : 1字段

所以,通过这个notification service extension,你可以在接收到推送之后、展示推送之前处理一些事情,比如说更新一下推送内容,或者在后台做一些其他事情。

2、notification content extension

另一项notification content extension用于完全自定义推送展开后的视图。上面腾讯新闻的展开后的视图就是通过这个notification content extension实现的。

依然以腾讯新闻为例子:

img35.png

      展开界面

这里Notification Content Extension大展拳脚的地方,在这里可以自定义绘制不同的内容,将希望展现给用户的额外信息可以加载这里。

下半部分的notification action的实现就是在上面提到的“携带action的通知”。

测试要点

img36.png

Q&A

Q:离线push,支持角标(badge)在本地角标数值上+1这样的操作吗?

A:不支持。如果是自己实现push服务的话,需要自己的后台将角标值badge发送个APNs服务器,有些APP使用第三方push SDK除外。

Q:如果重复收到离线push,可能是什么情况

A:

1)iOS9之后卸载重装后生成新的deviceToken,后台对多个deviceToken都发送了push

2)后台对注销了的账号也发送了push。

总而言之一般是后台的逻辑出现了问题,而不是APNs服务器出现问题。

Q:直接卸载APP,还能收到离线push吗?

A:不会收到。直接卸载APP,虽然后台不知道APP被卸载了,仍然会对之前的账号发送push,但是由于手机上没有对应APP,所以并不会收到push。

Q:为什么有时候全新安装APP就立马有红点角标?

A:这是因为卸载该APP时有红点角标。每个 APP 的角标都是存在 iOS 手机系统里的,开发无法修改,所以此时卸载前有角标,重新安装也会有角标。但是,APP 卸载之后超过一天的时间再重装,那么角标就会被系统清空,届时也不会有新安装的 APP 就有角标的情况存在。

相关工具

Knuff离线push工具下载链接:https://github.com/KnuffApp/Knuff/releases

使用方法也比较简单

img37.png

比如我的payload输入如下:

img38.png

得到的应该是有“Knuff测试”文字,和角标数变为999,我们可以看下结果,与预料是一致的:

img39.png

     预期结果

有了这个工具也更加方便了我们的iOS push的调试。

参考资料iOS推送之远程推送(iOS Notification Of Remote Notification):https://www.jianshu.com/p/4b947569a548玩转 iOS 10 推送 —— UserNotifications Framework(合集):https://www.jianshu.com/p/f57e2045f711用iOS10 UserNotifications框架来接收remote notification:https://www.jianshu.com/p/b6be6310f866iOS10推送通知进阶(Notification Extension):https://www.jianshu.com/p/78ef7bc04655

相关阅读
系统负载能力浅析
搭建公众号自动回复功能
【每日课程推荐】机器学习实战!快速入门在线广告业务及CTR相应知识

此文已由作者授权腾讯云+社区发布,更多原文请点击

搜索关注公众号「云加社区」,第一时间获取技术干货,关注后回复1024 送你一份技术课程大礼包!

海量技术实践经验,尽在云加社区

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS Push详述,了解一下? 的相关文章

  • 公司的电脑为什么卡——因为缺少工程师文化

    点击一键订阅 云荐大咖 专栏 获取官方推荐精品内容 学技术不迷路 最近在给一些公司做技术培训时 发现不少公司还面临这些老问题 腰疼的椅子 卡顿的电脑 小尺寸显示器 24 英寸 不能查资料的网络 导致研发效率低下 员工满意度低 离职率高 公司
  • 移动端表格组件

    最近在vue开发移动端过程中 需要用到表格展示 经过多方面对比感觉这个不错 https www csdn net tags Mtjacg4sOTk1NDctYmxvZwO0O0OO0O0O htmlhttps www csdn net ta
  • mongodb如何实现数组对象求和

    原本地址 mongodb如何实现数组对象求和 mongodb在计算集合数组值时候 我们通常会想到使用 group与 sum 但是如果是数组里面多个json对象 并且还需要根据条件过滤多个对象的内容该如何处理 现在让我们来实现它 假设mong
  • java.awt.Color类

    Color类概述 Color是用来封装颜色的 支持多种颜色空间 默认为RGB颜色空间 每个Color对象都有一个alpha通道 值为0到255 代表透明度 当alpha通道值为255时 表示完全不透明 当alpha通道值为0时 表示完全透明
  • Lottie动画概述,文末有彩蛋

    原生的动画效果有时候写起来会非常的复杂 要考虑到很多兼容和效果 Lottie动画专门为了解决这种烦恼而产生的 注 不仅是Lottie可以做到 另外一种库也可以做到将动画分成一帧一帧展示 它就是 android gif drawable 库
  • Flutter状态管理Provider,简单上手

    学习Flutter一段时间了 偶然看到大家都说状态管理 多数人都是用redux 对于一个Android开发人员来说之前根本没接触过 于是开始了解redux 之后又了解闲鱼推出的fish redux 然后又看到Vadaski发表的一系列关于F
  • IOS高访新浪微博界面(讲解如何自定义UITableViewCell,处理@#链接 特殊字符)

    在开发过程中 有好多应用都会嵌入新浪微博的界面 今天整理一下代码 首先看界面效果图 Demo下载地址 http download csdn net detail rhljiayou 6760745 思路 首先放一个UITableView 自
  • 客户端无法连接腾讯云服务器Redis

    一 问题 使用Redis Desktop Manager 昨天可以连接上Redis服务器 今天却不可以 二 解决方案 1 确保IP地址 端口号 输入密码正确 1 1 redis conf 文件中port 1 2 redis conf文件中r
  • iOS逆向工程之App脱壳

    本篇博客以微信为例 给微信脱壳 砸壳 在iOS逆向工程中是经常做的一件事情 因为从AppStore直接下载安装的App是加壳的 其实就是经过加密的 这个 砸壳 的过程就是一个解密的过程 未砸壳的App是无法在Class dump Hoppe
  • TVP新书上架

    新书速递 近期 在腾讯云 TVP 联合出书计划中 腾讯云 TVP 山金孝老师推出了新书 融合 产业数字化转型的十大关键技术 融合 产业数字化转型的十大关键技术 作者 山金孝 李琦 中译出版社 内容简介 数字经济已成为高质量发展的新引擎 数字
  • 高防cdn和高防服务器的区别,有什么不一样

    CDN通俗的理解就是网站加速 可以解决跨运营商 跨地区 服务器负载能力过低 带宽过少等带来的网站打开速度慢等问题 一个网站的服务器性能比较差 负载能力有限 优势面临突发流量 招架不住 直接导致服务器奔溃 网站打不开 CDN 跟 高防服务器
  • sharedPreferences

    sharedpreferences 共享参数 也是保存数据的一种方法 通常用于持久化数据 定期更新保存数据 类似ajax的定时刷新 示例代码 主要来源于黑马教程 如下 import java util Timer import java u
  • web移动端布局的那些事儿

    原文地址 github com HuJiaoHJ bl web移动端布局范畴很广 其中比较基础的几个话题 移动端适配 1px border 基础布局 本文主要分享这三个话题 一 移动端适配 提起移动端适配 大家想到的肯定是rem flexi
  • Compile Options--编译选项

    目的 其主要作用是用于调试跟踪和测试 主要包含 MT TASK MT ZDO FUNC and other MT compile options LCD SUPPORTED LCD SUPPORTED DEBUG BLINK LEDS 且看
  • IOS开发系列——异步绘制专题

    异步绘制专题 1 图片处理 1 1 编辑图片的几个方法 第一种 先用UIImage对象加载一张图片 然后转化成CGImageRef放到CGContext中去编辑 第二种 用CGImageCreate函数创建CGImageRef 然后把CGI
  • iOS App打包上架详细流程

    一 前言 作为一名iOS开发者 把辛辛苦苦开发出来的App上传到App Store是件必要的事 但是很多人还是不知道该怎么上传到App Store上 下面就来详细讲解一下具体流程步骤 二 准备 一个已付费的开发者账号 可分为 账号类型分为个
  • iOS自动布局——Masonry详解

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由鹅厂新鲜事儿发表于云 社区专栏 作者 oceanlong 腾讯 移动客户端开发工程师 前言 UI布局是整个前端体系里不可或缺的一环 代码的布局是设计语言与用户视觉感受沟通的桥梁
  • 探究Xcode New Build System对于构建速度的提升

    在Xcode9发布的时候 Apple在Build System上提供了新版本的构建系统 New Build System 具体可见WWDC2017 不过令人失望的是 该新特性的讲解很简短 短到只在一页PPT上露脸 在这短短的时间里 苹果讲述
  • 【腾讯云云上实验室】个人对腾讯云向量数据库的体验心得

    目录 前言 Tencent Cloud VectorDB概念 使用初体验 腾讯云向量数据库的优势 应用场景有哪些 未来展望 番外篇 腾讯云向量数据库的设计核心 结语 前言 还是那句话 不用多说想必大家都能猜到 现在技术圈最火的是什么 非人工
  • 腾讯云用centos还是ubuntu系统好?

    腾讯云服务器提供了多种操作系统选择 包括 CentOS Ubuntu Windows Server 等 用户可以根据自己的需求和习惯选择适合的操作系统 通常比较推荐安装centos 7 x版本的系统 但在 CentOS 和 Ubuntu 之

随机推荐