1.前言
- 作为一个非原生App的开发者,对于手机系统的推送机制了解是是非有限的,只有了解清楚这些机制,后期的开发才会少踩很多坑,本文将对推送机制逻辑进行一个简单的梳理与记录
2.推送流程
- 推送流程1.0:后台服务器 -> 推送服务器(第三方) -> 手机App
- 推送流程2.0:后台服务器 -> uni-cloud -> 推送服务器(第三方) -> 手机App
3.推送服务器
- 为什么后台不直接推送消息给手机App,而是要转交给第三方推送服务器呢?这里举两个例子:
- 1.假设有一条消息需要同时推送给10000个人,那么这条消息就有10000个状态,推送成功的人将不再推送,而推送失败的人将会一直持续推送,直到成功为准,所以需要写一套专门的算法来处理这套逻辑
- 2.消息需要推送给具体的某台手机,那么每个人就需要为每台手机分配一个独一无二的标识,根据这个标识定位到目标手机,然后才能进行推送,而给每台手机分配一个独一无二的标识,也需要一套算法
- 3.手机App想要实时接受消息,必须开启一个专门的进程实时在线,这个内嵌在App内部的进程也需要进行开发
- 就像淘宝卖家不会自己组建一个物流团队一样,一般的软件开发者也没必要去开发这套逻辑,第三方软件推送服务商提供专门的推送服务,无论研发能力,产品功能与稳定性都远超自己开发,需要推送时直接选择他们即可
4.推送进程
- 想要接收推送信息,必须让对应的进程保持运行状态,这种进程分两种:App推送进程和系统进程
- App推送进程:App集成推送功能后,就自带这个进程,这个进程会随着App的关闭而关闭,所以他能否生效取决于App是否在线运行,也就所说的"在线推送"。因为是软件内部的进程,所以他接收到信息之后,可以自由处理推送消息,例如,他可以自动创建通知栏(通知消息),也可以在软件内部无声无息的对消息进行处理(透传消息),推送的SDK可以根据消息的数据格式来区分是哪种消息(通知消息,透传消息)
- 系统进程:集成到系统底层,由手机厂家提供,理论上手机是开机状态就不会被关闭,所以这个进程是24小时在线的,当App自己的推送进程关闭后,可以借助他进行推送,也就是所谓的离线推送,但是厂家对推送有要求(需要审核上架,一天只能推送3条等),系统进程只能通过创建通知栏的方式来通知用户有新消息,他无法与App内部直接对接,所以他只支持"推送消息",不支持"透传消息"
5.App的运行状态
- App在线状态:第三方推送服务商的消息能正常推送
- App离线状态:第三方推送服务商无法推送,此时再想推送必须依靠系统进程,手机厂商像小米,华为等都完成了系统级别的推送支持,但是他们各自为阵,需要每个厂家进行对接适配(框架在技术层面已经完成适配,开发者需要自己完成审核,上架等操作)
- App现状1:为了省电,手机系统会对通常后台程序进行清理查杀,很少有App能常驻后台
- App现状2:现在的手机系统严格控制App自启动,链式启动,App无法像之前一样通过流氓手机强制驻留后台
- App现状3:基于上面2点,App只有在前台展示期间,或者刚退回桌面的前几分钟是在线状态,其余时间都是离线状态
6.安卓App如何保持在线状态
- 调整App省电策略:以MIUI为例,长按App图标 => "应用信息" => "省电策略" => "无限制"
- 允许自启动:以MIUI为例,长按App图标 => "应用信息" => "自启动" => "开启"
- 原生安卓系统:手持pda搭载原生安卓系统,此类设备不会杀后台
7.通知消息与透传消息
- 通知消息:在通知栏弹出消息(App自动创建),点击后启动App,App启动后可以拿到相关参数,可根据相关参数来开发对应的逻辑(页面跳转,参数传递,刷新数据等待),离线和在线状态都支持
- 透传消息:App接收到消息后,不创建通知栏,直接在App内部进行处理,App离线状态不支持
8.通知消息与App交互(web控制台)
- 通知消息的发送格式:推送时支持2个字段,标题(title)和内容(content)
- 通知消息的交互行为:消息送达后在通知栏弹出通知,并展示App图标,消息标题和消息内容
- 点击通知栏的后续行为:分3种,启动App,打开网页,打开App页面,且都会触发"click"回调,区别在于收到的参数有区别
- 行为1.启动App:点击通知栏启动App,并触发"click"回调,回调参数只能拿到标题(title)和内容(content)
- 行为2.打开网页:点击通知栏启动App,并触发"click"回调,回调参数只能拿到标题(title)和内容(content),并且打开目标网页
- 行为3.打开应用内特定页面:需要设置intent(不要按官方web控制台的方法来,那个是错误的),点击后启动App,并触发"click"回调,这种方式可以获取到额外的参数"payload"
- 监听通知栏点击的代码
plus.push.addEventListener('click', _handlePushClick)
const _handlePushClick = function(message) {
console.log('_handlePushClick',message)
}
{
"__UUID__": "androidPushMsg170266890",
"title": "测试消息",
"appid": "__UNI__012294A",
"content": "有设备报修",
"payload": {
"title": "测试消息",
"content": "有设备报修"
}
}
- intent的数据格式:复制下面的字串,替换关键信息即可,payload字段支持对象格式,可以携带额外参数,例如要跳转的页面路径等等特殊字符(页面路径,以/开头需要用引号包起来)
intent://io.dcloud.unipush/?#Intent;scheme=unipush;launchFlags=0x4000000;component=ponyiiot.app/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title=测试标题;S.content=测试内容;S.payload={path:'/页面路径',mc:设备名称};end
- 处理额外参数:给"payload"挂载额外参数用于跳转目标页面
const _handlePushClick = function(message) {
//有path参数,进行跳转
if(message.payload.path){
uni.navigateTo({
url: message.payload.path,
fail(err){
console.log(item.name+' 跳转失败')
}
})
}
}
9.透传消息与App交互
- 透传消息的发送格式: 格式可以自定义
- 通知消息的交互行为:透传消息到达后触发 receive 事件,拿到自定义参数后App自由调配代码
plus.push.addEventListener('receive', _handlePushReceive)
- 创建本地通知:接收到透传消息后,可以自由创建本地通知
//创建本地通知
plus.push.createMessage(message.content, message.payload , {title:message.title})
- unipush官方声称符合特定格式的透传将视为通知处理,但是我个人测试无效
{"title": "xxx","content": "xxx","payload": "xxx"}
10.IOS推送
- App在线:触发 receive 事件,不产生系统通知
- App离线:弹出系统通知,点击触发 click 事件
- 因IOS未做测试,以上未经过验证