那些年,我们一起走过的iOS推送的坑

4,005 阅读8分钟

本文由信鸽工程师uwei提供。

文章提要

本文针对iOS推送接入过程中遇到的一个实际案例,提出了iOS推送排查问题的思路,在解决该问题的基础上,更给出了通用的iOS推送自测的检查路径。
文末提供了一种基于腾讯移动推送(信鸽)的自测工具,欢迎试用与反馈。

问题背景

对于互联网APP的产品运营来说,由于我们的用户是不可见的,有时候甚至是在身边的陌生人就在用我们的产品,但是我们却有一种近在眼前,远在天边的感觉, 物理上的隔离成为了天生的屏障,特别是当产品需要做一个线上有时效性的活动的时候,我们是多么希望用户都坐在我们面前,以便我们可以随时通知到关于活动的事情。而互联网的运营人员的手段方法多种多样,但是消息推送一直绝对是产品运营的一个必须且重要的手段,消息推送让我们的用户与我们之间摆脱了看不见摸不着的尴尬局面。不管我们的用户在哪里,只要他们联网,消息推送能拉近用户与我们之间的距离,即使远在天边,但是秒级触达,感觉好像尽在身边。

可以说,现在的APP们,90%都有推送的刚需。而市面上现在已经有很多的第三方推送工具,集成第三方推送工具无疑是一件相对轻松的任务。
但不正确的集成姿势,或者某些错误的配置,常常会导致推送无法正常使用。
比如,
1.Xcode开发环境中关于推送的配置不正确
2.推送证书设置错误或者是证书过期失效

那么,集成推送需要注意些什么
集成之后,怎样确认自己是否正确集成了远程消息推送呢?

坑:iOS 10推送失败

相信iOS开发的同学对下图来说是比较眼熟的:

以上图片就是Xcode不同版本中关于推送的配置是不同的,表现如上,但是不同点具体在哪儿呢?

使用Xcode7.3以上版本打包app,导出iPA(这是一个压缩的文件夹),在mac系统中,鼠标右键,使用系统自带Archive Utility工具解开,在进入app所在的Payload文件夹,选择app,点击右键,选择Show Package Contents,进入App包中,可以找到两个文件

embedded.mobileprovision(配置App签名信息)
archived-expanded-entitlements.xcent (配置App权限功能,例如远程推送,App Group等)

使用如下命令
security cms -D -i embedded.mobileprovision
可以查看App的签名信息,其中关于推送的部分如下图

但是关于archived-expanded-entitlements.xcent文件,在不同的Xcode版本中,文件内容是不同的,具体看下图

可以发现:

在使用Xcode7.3.1版本进行打包开启了远程推送的工程的时候,工程中并不会自动创建Target-entitlements文件,进而archived-expanded-entitlements.xcent文件中也就不会有aps-environment键值对的信息。

在使用Xcode8.3.2版本进行打包开启了远程推送的工程的时候,工程中会自动创建Target-entitlements文件,进而archived-expanded-entitlements.xcent文件中也就会有aps-environment键值对的信息。

由此可见Xcode的版本更新对推送的配置是有更改的,这个配置的变化,导致有些App即使集成了远程推送,但是在iOS10上却收不到推送。

坑:问题回溯

具体案例如下——

问题描述:
某 iOS app在接入信鸽SDK 集成推送功能时,遇到在iOS 10 以下版本可以正常推送,但是在iOS 10的版本中,收不到推送消息。

具体现象:
然后将iOS10的设备连接到Xcode,在Xcode中打开连接的设备的控制台,启动某游戏App,在输出的log中,发现了下面输出:

Apr 21 17:53:53 uwei SpringBoard(UserNotificationsServer)[53] 
<Notice>: No valid 'aps-environment' entitlement string found for application 'com.tencent.dragonnest': 
(null). Notifications will not be delivered.
Apr 21 17:53:53 uwei dragon[3644] <Notice>: JoyYou-TencentMSDK ::: Register remote notifications failed with error: 
Error Domain=NSCocoaErrorDomain Code=3000 "no valid 'aps-environment' entitlement string found for application"
UserInfo={NSLocalizedDescription=no valid 'aps-environment' entitlement string found for application}

调查路径——

第一步
先确认在iOS 10以下操作系统中是否正常,
在一台iOS 8的越狱手机上,抓取到了device token,定向推送消息,可以正常收到。
在iOS 9的设备上,使用账号登录,反查device token,可以看到登录的账号下是有device toekn的,然后使用定向推送,可以正常收到推送消息。
在iOS 10.3.1的设备上,从操作同iOS9的一致,后台显示没有绑定到device token。反复下载重试,结果一样。

第二步,验证包

  1. 检查AppStore中的包是否存在问题(我们不能保证我们上传的包没有经过Apple的二次改修,事实上Apple会修改我们上传的iPA文件)

    在本地使用iTunes,从AppStore下载某游戏App的最新包,解开包中的文件,找到了archived-expanded-entitlements.xcent文件,打开查看,


发现文件中缺少aps-environment的键值对,而这正好符合与iOS 10设备的控制台看到的log相符:

No valid 'aps-environment' entitlement string found for application 'com.tencent.dragonnest'
而配置了远程通知的app,在app包中凡是拥有archived-expanded-entitlements.xcent这个文件的,文件内容中必须要有以下键值对才能正确使用远程推送
<key>aps-environment</key>
<string>production</string>
而正确的内容应该如下:(举例)

  1. 检查提交Apple审核的iPA包,打开包中embedded.mobileprovision,archived-expanded-entitlements.xcent的文件,查看其中的内容
    使用以下命令打开第一个文件:
    security cms -D -i embedded.mobileprovision > embeded.plist


这个文件中存在关于推送的签名信息,说明当前App是配置了推送证书的。

2.2. 使用文本工具打开 archived-expanded-entitlements.xcent,内容是


与从AppStore中下载的安装包中的文件是一致的,说明Apple并没有做额外的处理

由此可以得出结论:
某游戏App在打包的时候,生成的包关于推送的配置存在问题

引入原因:
Unity里面放了一份entitlements文件,导出到XCode的时候没有被识别到,所以每次XCode都生成一个新的entitlements,导致部分数据丢失(aps-environment键值对)

解决办法:
手动在entitlements文件中添加aps-environment键值对

坑:问题结论

建议如果在工程代码不存在IDE版本兼容问题的要求,请使用新版本Xcode进行配置打包,然后在根据文档中提到的方法检查iPA包。

延伸:如何检查iOS推送

最后简单介绍iOS APNs的机制,让我们了解消息推送的整体流程,

第一步如下图:

  1. App使用注册API注册APNs远程推送,如果App已经注册过,并且App指定的token没有发生变化,系统会立即返回给App已经存在的token,直接执行第四步
  2. 当需要生成一个新的token时,APNs会使用在设备中的证书来创建,使用一个token key来加密token,然后返回到设备
  3. 系统通过application:didRegisterForRemoteNotificationsWithDeviceToken: 回调函数下发设备token到App
  4. 一旦App接收到device token,在回调方法中,使用信鸽SDK中的接口,将这个token发送XG服务器。

第二步
当使用前端网页创建全量推送的时候,XG后台将根据指定的APP,将(推送的内容+在当前这个App下所拥有的token+App指定的证书)作为参数,发送推送请求到APNs,
APNs解密token和token key,以校验请求的有效性,以及推送的目标设备,如果APNs判断请求是合法的,之后就会向指定设备发送通知消息。
如下图:

整个APNs消息的推送流程,可以粗略概括为下图:


那么通过以上的介绍,推送出现问题的可能就可以归纳为以下:

  1. 开发环境中关于推送开关选项,推送权限的文件配置不正确
  2. 推送证书设置错误或者是证书过期失效等
  3. device-token 未获取到,或者是获取到了device token,但是发送给XG服务器的姿势不正
  4. 用户设备关闭了消息推送,或者是设备的网络连接有问题
  5. Apple或者是XG服务器不稳定

再延伸:推送诊断

针对iOS平台的推送集成,信鸽iOS开发团队提供了【推送诊断工具】,可以在信鸽官网中【应用列表】->【应用配置】->【信鸽推送助手】
希望通过以上介绍,能够让团队在使用推送技术的路上,少踩坑,少走弯路,多一点了解,多一点高效。

欢迎访问信鸽官网联系我们。或通过以下方式:
商务合作请联系邮箱:data@tencent.com
技术业务请联系邮箱:dtsupport@tencent.com