支持多包名推送呼声最高的还是游戏分发,由于游戏分发看中多渠道。因此同一款游戏可能存在不同包名,按照现有的情况,一个包名接入 Push需要给每一个包名申请一个为一个AppId,AppKey。倘若应用包名数量比较小,还可以接受。但是如果渠道过多,就可能出现需要申请几十甚至几百个应用,工作量可想而知。因此多包名推送的需求由此而来。
一 现有方案分析
按照现有的实现方案分析,在不改造现有的推送逻辑情况下,第三方服务端开发者如果需要支持多包名,在推送消息时,需要将组装一次,分别按照包名分发给各个包名的应用,这样模式就是多次消息分发,给开发者造成困扰,同时也浪费推送带宽,增加推送信道资源。如下图:
从上图可以看出:
- 开发者需要单独调用设置各个要推送的包名依次推送【这将开发者开发复杂度】
- 同一类型消息发送次数取决于需要发送的包名的个数【浪费信道资源,同一类型消息发送多遍】
二 优化方案
优化方案主要要解决以下问题
- 一个手机安装多个渠道的apk,尽可能减少服务端发送消息的次数
- 降低服务端发送消息的复杂度,尽量避免使用轮询发送的方式
NOTE: 以下为新的方案设计图
- 服务端
服务端提供接口,用于让开发者设置多包名,推送的时候将开发者设置的包名传递到推送服务
- 客户端
客户端收到多包名推送的请求,校验手机中的各个包名是否存在,如果存在就将消息依次分发给各个应用
NOTE: 此方案的设计思想淡化现在单个应用的单一推送,因为服务端推送时本质还是按照客户端imei下发给各个手机,推送服务在这里需要接管多包名的消息分发逻辑,当消息到达客户端时,由推送服务进行逻辑分发,降低push平台的分发复杂性与开发者接入复杂程度。
三 实现方案
按照优化方案,客户端和服务端需要改造
3.1 推送协议改造
- 目前推送消息格式proto定义如下:
message NotifyBody
{
//指定推送的应用包名
required string app = 1;
// 推送的消息体内容
required string body = 2;
// 扩展字段
optional string ext = 3; //扩展信息(json格式){"ct1":{"pushType":"0"}, "statics":{"taskId":"123456"}, ...}
};
如上现在定义的推送消息体格式,目前app固定代表推送给当前应用的包名。以上也是为了适应单包名推送,body代表现在的通知栏消息格式定义,为了兼容性,我们只能在ext上做文章
- ext 通知栏格式定义如下
需要增加restrictedPackageName,用于传递多包名配置
{
"ctl": {
"pushType": 0, //0:通知栏消息; 1: 透传消息 2: 上报日志指令
"wakeup":0, //透传消息是否强制唤醒应用,仅仅当此消息为透传消息才携带此字段: 1:强制唤醒 0 不强制唤醒
"cached": 0, //0:不缓存消息; 1: 缓存通知栏消息
"cacheNum":10 //通知栏消息最大缓存数量
},
"statics": {
"taskId": "41159", // 任务taskID
"time": "1475118843" // 任务创建时间
"pushExtra":0 //是否上报push extra 信息 , 0 不上报,1 上报,如果没有该字段默认上报
},
"restrictedPackageName": ["com.meizu.upspushdemo","com.meizu.upspushdemoxm"]
}
- 精简字段
{
"ctl": {
"pushType": 0, //0:通知栏消息; 1: 透传消息 2: 上报日志指令
"wakeup":0, //透传消息是否强制唤醒应用,仅仅当此消息为透传消息才携带此字段: 1:强制唤醒 0 不强制唤醒
"cached": 0, //0:不缓存消息; 1: 缓存通知栏消息
"cacheNum":10 //通知栏消息最大缓存数量
},
"statics": {
"taskId": "41159", // 任务taskID
"time": "1475118843" // 任务创建时间
"pushExtra":0 //是否上报push extra 信息 , 0 不上报,1 上报,如果没有该字段默认上报
},
"rpn": { "com.meizu.upspushdemo":0,
"com.meizu.upspushdemoxm":1
}, //记录用户选择的多包名,如果用户填写了多包名,此字段必须把用户所有设置的多包名全部传递过来,不管透传还是通知栏
"srpn":0 //1代表支持,0 代表不支持多包名,此字段主要控制消息是否只传递给主包名,是否上报反订阅需要校验该手机是否安装其他子包名应用
}
3.2 服务端改造
服务端在请求推送时,填写ext字段时,增加restrictedPackageName
字段,用于向手机推送服务传递多包名配置,此外推送填写的包名始终是主包名packageName
3.3 客户端改造
- 旧版本兼容性
- 现象:如果主包名不存在,只推送其他包名,此功能将失效
- 原因:如果多包名配置推送到旧版的推送服务,即是无法解析restrictedPackageName,多包名配置失效,但是如果当前手机安装了主包名应用还是可以收到消息
- 新版功能
客户端改造完成之后可以解析服务端发送的restrictedPackageName
,进而进行消息转发
3.3 订阅与反订阅逻辑
由于多报名订阅使用的是同一套AppId
和AppKey
,因此现有的订阅方式需要更改
-
订阅时上报当前应用的包名
-
pushId生成逻辑
由于现在pushid生成逻辑是imei+appid,现有情况如果不同包名在同一手机获取的pushid是一致的,为了区分最好根据包名区分
-
卸载失效逻辑
当其中一个应用别卸载,需要反订阅此包名,这里可能需要高级反订阅接口
待解决问题
- 数据上报问题
-
多渠道问题
一般情况下同一个手机安装多个不同包名的相同应用情况比较少,例如同一款游戏在不同应用商店上架就会存在多包名,如果它们分别通过魅族应用商店安装在flyme上,通过小米应用商店安装在MiUI上,魅族的推送是在非flyme上是无法生效的,这时候只能依靠各个不同厂商的推送,也就是我们现在要做的统一推送平台,实现不同通道转发。
-
结论
因此最总我们要解决的是在不同flyme手机通过不同渠道下载的应用进行消息分发.