项目背景:
之前做过iOS原生的远程推送,这次趁着公司的项目研究ionic项目推送,本想着两天就可以完事,但是ionic项目相对于iOS原生的远程推送有点复杂,不过大多都是满足我们的业务,但是iOS原生的推送已经较之前的API有很大变化,这边文章原本可以提前一周完成,由于这段时间私事笔记慢了一周和笔友见面,在这过程中遇到很多坑,在此记录下。看多很多博客都是乱写,很多只是copy别人的只会误导我们,所以我觉得自己很有必要在此将最新的信息分享给有心人。 OK,接下来,我们进入主题:
项目目录:
1、合适ionic项目推送技术预研、选型
2、iOS apns证书配置、合成aws(亚马逊消息服务需要的推送p12文件、后端推送provider需要)
2.1 了解 apns 远程推送
2.2 这里明确预生产和生产环境
2.3 这里先讲下 production 证书的配置过程
2.4 测试device 配置
3、iOS客户端初始化、接受处理code
最终效果: 点击进入详情
1、合适ionic项目推送技术预研、选型
极光: 支持iOS、Android(收费版才支持:华为、小米、魅族的推送sdk)、winphone
友盟:支持iOS、Android(免费支持:华为、小米、魅族的推送sdk)、winphone
apns: 只适合iOS推送
腾讯个推:收费
综上信息: 选择两套方案,有人会纳闷为什么iOS、Android都不用友盟,但是后台说业务简单他们集成anps更简单,所以最终使用两套方案。
2、iOS apns证书配置、合成aws(亚马逊消息服务需要的推送p12文件、后端推送provider需要)
老实这一步重要性: ✨✨✨✨✨
2.1 了解 apns 远程推送
2.1.1什么是远程推送?
苹果提供的一项给终端设备推送消息的服务
为何使用远程推送?
当用户打开应用程序的通知中心之后,苹果远程推送服务器就能把消息推送到装有该应用的设备上,具有强制性、实时性的特点,并且用户无需打开应用都能收到推送的消息。
三、远程推送原理
说到远程推送不得不说下下面这张图,下面这张图把远程推送的过程大致描述勾画了一遍,在此解析一下下图。
WechatIMG52.jpeg
Snip20170705_169.png
名词解释:
Provider:消息提供者,一般是我们的后台服务器或者第三方推送服务器后台
APNs(Apple push notification server):苹果的远程推送服务器,可以说是消息中转站,需要发送给iOS客户端的消息统一发往苹果的APNs服务器
notification:需要推送给iOS客户端(iPhone或者是iPad)上的消息
Client App:客户端App,一般是安装在iPhone或者是iPad上的应用程序(App)
deviceToken:是唯一的由APNs根据设备和App来生成的一串数据,那么在以下三种情况下会发生改变:
①同一个设备上重新安装同一款应用
②同一个应用安装在不同的设备上
③设备重新安装了系统,同一个应用对应的deviceToken也会改变
An app-specific device tokenisglobally uniqueandidentifies one app-device combination. 释义:deviceToken是device是App和device结合的唯一编码Upon receiving a device tokenfromAPNsinyour app, itisyour responsibility to open a network connection to your provider.释义:在你的设备上接到来自于APNs的deviceToken之前,你应该或者有责任先打开provider和APNs之间的网络连接Itisalso your responsibility,inyour app, to then forward the device token alongwithany other relevant data you want to send to the provider.释义:你依然应该在你的App上将deviceToken连同其他需要的数据发给你的后台服务器(provider)When the provider later sends remote notification requests to APNs, it must include the device token, alongwiththe notification payload. For more on this, see [APNs Overview](链接已贴出如下)释义:当后台服务器稍后发送了远程通知请求给APNs的时候,应当包含deviceToken和远程推送消息内容Never cache device tokensinyour app; instead, get themfromthe system when you need them. 释义:永远不要缓存deviceToken在你的应用上,而是需要的时候就从APNs系统获取APNs issues a new device token to your app when certain events happen. 释义:当某些事件发生的时候APNs会发送一个新的deviceToken到你的AppThe device tokenisguaranteed to be different,forexample, when a user restores a devicefroma backup, when the user installs your app on a new device,andwhen the user reinstalls the operating system. 释义:deviceToken是确保不一样的,比如说以下情况:当一个用户在同一个设备上重新安装同一个应用或者将应用装在不同的设备上;或者用户重装手机系统都会导致deviceToken的不一样Fetching the token, rather than relying on a cache, ensures that you have the current device token neededforyour provider to communicatewithAPNs.释义:直接获取deviceToken而不是依靠缓存的deviceToken,这样确保你的后台服务器和APNs通信的时候用的是当前有效的deviceTokenWhen you attempt to fetch a device token but it hasnotchanged, the fetch method returns quickly.释义:当你尝试去获取deviceToken但是这个deviceToken并没有改变,那么这个获取就会很快。
图意理解:
目的意图:我们需要给我们的App推送一条消息(活动促销类信息,提醒用户升级等信息等)给我们用户,让用户了解应用的最新信息。一般出于用户留存的考虑。
图解流程:消息提供者(Provider)将消息发送给苹果远程推送服务器(APNs),苹果远程推送服务器(APNs)再将消息推送给装有该应用的设备。
详细流程:(以今日头条为例)
在今日头条App的AppDelegate的didFinishLaunchingWithOptions方法中注册远程推送通知,此时只要iOS设备正常联网能够访问到外网,iOS设备默认就会和APNs建立长连接,就会把iOS设备的UDID(Unique Device Identifier:唯一设备标识码,用来标识唯一一台苹果设备)和今日头条的Bundle Identifier通过长连接发送给APNs服务器,然后苹果通过这两个的值根据一定的加密算法得出deviceToken,并将deviceToken返回给iOS设备。(注:APNs服务器会留有UDID+Bundle Identifier+deviceToken的映射表)
实现UIApplicationDelegate代理中的有关于注册远程通知的相关方法,包括注册成功、注册失败、对接收到通知的处理等。
如果注册成功,实现注册成功的代理方法,就能够接收到deviceToken,并将deviceToken发送给今日头条服务器,今日头条服务器将此deviceToken存储在数据库中(一般如果是及时通讯类应用那么还会与用户的账号进行映射)。
如果注册失败,那么实现注册失败的协议方法,处理失败后的事情(包括发送给今日头条服务器注册失败等)。
今日头条服务器接收到deviceToken之后,就可以根据这些deviceToken向APNs发送推送一条新闻简要消息。
APNs接收到deviceToken和新闻简要消息之后,根据deviceToken查找映射表找到对应的UDID和Bundle Identifier,根据UDID找到唯一一台苹果设备,再在找到的苹果设备上根据Bundle Identifier找到唯一的应用(此处为今日头条),然后推送消息。
当设备接收到消息的时候,如果今日头条在前台也就是用户正在使用今日头条,那么不会在设备上方弹出横幅(如果使用了音效,还会触发音效的播放),直接调用我们实现的UIApplicationDelegate中的接收消息的方法。反之如果今日头条在后台或者未运行时就会在设备的上方弹出横幅(如果使用了音效,还会触发音效的播放),点击横幅才会触发调用我们实现的UIApplicationDelegate中的接收消息的方法,这个时候你直接点击应用图标进来是不会调用的。
2.2 明确预生产和生产环境:
sandbox(预生产环境-》 ; Apple Development IOS Push Services:xxxx)
production(生产环境 :Apple Push Services:xxxxx)
注: 配置的 appid -> certification->Provisioning Profiles 一定要对应
2.3 这里先讲下 production 证书的配置过程
第一步: 创建 appid 如果已经有自己项目的app ID不用创建 这里加入生成的 app ID:com.xxx.xxx (关于生成app ID: 不要选择通用的 * 就可以 )
第二步: 找到你的app ID 点击edit后 分别创建 开发环境、生产环境的推送证书 创建过程需要电脑的的根证书 没有的打开钥匙串 点击电脑顶部工具栏 证书助理生成一个
创建成功后在证书目录下会看到: APNs Development ios (开发环境推送证书) 、Apple Push Services (生产环境)
注: 推送证书就算生成完毕,但是要注意 你之前开发证书、发布证书的根在推送证书一定要对应,建议本地钥钥匙串里的证书都删除重新生成、不要不在意,基本上推送都在这出问题。
2.4 合成aws 需要的p12 这一步是我卡的地方
步骤:
1、进入电脑的钥匙串找到 生产环境的推送证书 Apple Push Services: com.xxx.xxx
2、生成 private_key.p12
生成过程: 需要输入名字和密码 假设生成的是 appstore_production_push_key.p12
3、将第2步生成的appstore_production_push_key.p12 转化为 appstore_production_push_key.pem 过程需要输入密码、确认密码
使用指令:openssl pkcs12 -nocerts -out appstore_pruduction_push_key.pem -in appstore_pruduction_push_key.p12
4、将苹果开发平台下载的 appstore_production_push.cer 转化为 appstore_production_push.pem格式 (appstore_production_push: 我的苹果正式环境的证书的名字,你的可以自定义)
使用指令: openssl x509 -in appstore_production_push.cer -inform DER -out appstore_production_push.pem -outform PEM
5、 将 appstore_production_push_key.pem 和 appstore_production_push.pem 生成 后台需要的p12文件 (包含 bounle id cer 配置文件)
使用指令:openssl pkcs12 -export -in appstore_production_push.pem -inkey appstore_pruduction_push_key.pem -certfile CertificateSigningRequest.certSigningRequest -name "appstore_production_identity" -out appstore_production_identity.p12
注: 如果输入完密码后出现 unable load to certifications 可以不用加载本地请求证书 去掉; -certfile CertificateSigningRequest.certSigningRequest
最终使用指令:openssl pkcs12 -export -in appstore_production_push.pem -inkey appstore_pruduction_push_key.pem -name "appstore_production_identity" -out appstore_production_identity.p12
6、最终将生成的 appstore_production_identity.p12 和 appstore_production_push.cer 发给运维、他们负责将p12文件给 aws (亚马逊消息服务)
2.4 device配置 进行推送测试
开发推送,和后台测试基本都是正式环境、对于iOS测试、正式测试难不成要我们每一次和后台推送provider调试都拍app store包吗,而且app store拍好后不能装到非越狱手机,显然apple大公司这样不是太坑了吗,他们建议我们使用adhoc模式。
补充打包模式:
1.Save for iOS App Store Deployment
保存到本地 准备上传App Store 或者在越狱的iOS设备上使用
2.Save for Ad Hoc Deployment
保存到本地 准备在账号添加的可使用设备上使用(具体为在开发#者账户下添加可用设备的udid),该app包是发布证书编译的(The app will be codesignedwith the distribution certificate.)
3.Save for Enterprise Deployment
这种主要针对企业级账户下 准备本地服务器分发的app
4.Save for Development Deployment
针对内部测试使用,主要给开发者的设备(具体也为在开发者账户下添加可用设备的udid)。 该app包是开发证书编译的(The app will be codesignedwith your development certif
作者:不一样的尘埃
adhoc模式要在账号添加的可使用设备上使用,所以我们要先添加的我们测试设备:
点击右上角的加号:
添加你设备的名字、uuid 即可注测添加。
3、iOS客户端初始化、接受处理code
3.1工程配置:
1、确认Target的Identify和Signing:
这里的Bundle Identifier 就是上面我提到我们本篇文章例子 com.xxx.xxx
team: 一定要和 Bundle Identifier 一致; 不一致自己去apple.decelopment.com 去创建,就是证书这一步很关键、
2、xcode8 后 推送 需要在工程里代开
勾选完 push notifications 后 iOS原生的工程会自动会生成 Entitlements-Release.plist(生产环境) Entitlements-Debug.plist(测试环境)
注: ionic项目build好的iOS项目可能不再物理目录,需要你打开platform->ios->就可以生成的 Entitlements-Release.plist(生产环境) 但是我的Entitlements-Release.plist未空 坑我很长时间 最后证明需要我们手动加上 ape-environment-> production 即可 不然release 时候拿不到devicetoken ✨✨✨✨✨
客户端的代码,网上一大堆自己百度,我的这几步只要完成基本没有大问题,真的不知道加我qq 我单独发 2963542803
需求技术:
@1 : 远程获取到devicetoken 发到js层 js层要做用户绑定 和 解绑操作 ;
@2: 收到远程通知点击横条进去详情页;
@3: 启动推送的时机
解决方法及思路:
@1、@2 : 使用ionic插件 cordova-plugin-broadcaster 现在3.3.1 实现ionic工程和iOS源码通讯 ionic2官网里 有他的使用方法 解决devicetoken ionic获取不到的问题 、iOS远程通讯点击和推送消息传递
@3: 自己写一个推送插件 在 ionic 项目执行完 platform.readly后执行注册远程推送 编写代码参考:https://www.jianshu.com/p/2c8cf1ccf625