APP消息推送(APP Push)解决方案-服务端工作逻辑和实现
2017-07-10 18:33
519 查看
一、APP 推送概述:
App推送消息是我们常见的一种app消息提醒方式。我们的实现需要第三方的支持,实现方式是后台通过接口将Push请求发送至第三方,第三方实现在App所在设备上的推送。
二、APP推送后台处理逻辑:
在与推送平台交互时,后台需要向第三方发送两部分信息,推送目标终端标示+推送内容1、推送目标终端标示:
APP推送需要定位目标终端,也就是说要给那台设备进行推送,简单的情况下,单设备推送,我们需要拿到一个终端ID的概念,用于定位目标设备,
注:不同渠道中使用的单设备ID方式也不尽相同,以下用TokenID来表示这个终端ID的概念。
而实际推送渠道中往往还有自定义的功能,比如通过打标签的方式将TokenID进行划分,达到批量差异化的效果。
2、推送内容:
即指通过API接口参数的定义终端上收到的Push消息的内容和格式。其中IOS的推送消息在展示上区别于安卓的一点是没有title,title的部分只能是默认的APP名称,而安卓的部分虽然默认值也是APP名称,但是也支持自定义title。
三、后端实现:
通过上述的处理逻辑可得知,后端首先需要登记客户端的TokenId,然后保持TokenID的有效性更新,然后在需要发送APP推送时拿到用户的有效TokenID,然后使用TokenID和已有的内容信息通过API与三方Push服务交互,完成推送。
即后端的实现分为两部分:
1、TokenID的登记
2、App Push API的调用
注:以下示例中有两个元素为本项目的特殊情况:
其中product_id是因为当前项目中客户端同时有多个版本,不同版本需要推送独立处理,但在同一张表内统一记登记;
而login_id跟member_id同时存在是因为当前系统中存在共享账户的情况,一般账号账户一对一的情况login_id和member_id是绑定的,不需要同时重复登记。
1、TokenID的登记:
以下是现项目使用的TokenID登记表结构:/*==============================================================*/ /* Table: sys_app_push_token */ /*==============================================================*/ create table sys_app_push_token ( record_id int(11) not null auto_increment, login_id int(11), member_id int(11), push_token varchar(200), visit_device int(4) comment '3:Android;4:IOS', product_id varchar(20) default '0' comment '', push_channel int(4) default 1 comment '1:IOS信鸽,2:华为,3:小米,4:极光', nstatus int(4) not null default 0 comment '状态:0:申请中;1:生效;2:失效;3:删除;4:历史记录', create_userid int(11) not null default 0, create_time varchar(20) character set utf8 not null default "", edit_userid int(11) not null default 0, edit_time varchar(20) character set utf8 not null default "", this_remark text, description text, create_ordernum varchar(30) character set utf8 comment '记录创建时的流水号', last_ordernum varchar(30) character set utf8 comment '记录最后一次编辑时的流水号', primary key (record_id) ) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci auto_increment = 10000 row_format = COMPACT; alter table sys_app_push_token comment 'app推送token表'; /*==============================================================*/ /* Index: Index_1 */ /*==============================================================*/ create index Index_1 on sys_app_push_token ( record_id );
以下是APP上传TokenID接口上传参数列表:
注:其中,推送渠道绝对在做Push时使用哪家API,参数的判定交由客户端进行处理,后端直接登记判定结果。
以下是TokenID登记接口处理方法
@Transactional(readOnly=false) public boolean uploadMemberPushTokenEnt(TrainVansContext trainVansContext) { try { //check already data trainVansContext.getTrainVansRequest().put("login_id", TrainVansUtils.getMV(trainVansContext.getTrainVansRequest(), "login_login_id")); // get All memberRelation trainVansContext.getTrainVansRequest().put("relation_type", TrainVansUtils.getMV(trainVansContext.getTrainVansRequest(), "visit_role")); List<Map<String,Object>> memberRelationList = SpringContextHandler.getBean(MemberService.class).getRelateMemberListByLoginId(trainVansContext); for(Map<String,Object> memberRelateMap : memberRelationList){ // trainVansContext.getTrainVansRequest().put("member_id", TrainVansUtils.getMV(memberRelateMap, "member_id")); Map tokenMap = SpringContextHandler.getBean(AppPushService.class).getPushTokenMapByLoginMap(trainVansContext.getTrainVansRequest()); //disable already data if(tokenMap != null){ if(!TrainVansUtils.getMV(tokenMap, "push_token").equals(TrainVansUtils.getMV(trainVansContext.getTrainVansRequest(), "push_token"))){ // trainVansContext.getTrainVansRequest().put("record_id", TrainVansUtils.getMV(tokenMap, "record_id")); if(!SpringContextHandler.getBean(AppPushService.class).updateDiabledThePushToken(trainVansContext)){ throw new RuntimeException("TranVans_Operate_Exception"); } //insert new data if(!SpringContextHandler.getBean(AppPushService.class).insertPushTokenRecord(trainVansContext)){ throw new RuntimeException("TranVans_Operate_Exception"); } } }else{ //insert new data if(!SpringContextHandler.getBean(AppPushService.class).insertPushTokenRecord(trainVansContext)){ throw new RuntimeException("TranVans_Operate_Exception"); } } } return true; } catch (Exception e) { TrainVansUtils.setRetInfo(trainVansContext, "10005001","Register TokenID Error"); e.printStackTrace(); throw new RuntimeException("TranVans_Operate_Exception"); } }
注:方法外部有一个关于对应本账号的对账户列表的遍历,遍历中的处理部分为TokenID的登记处理操作。
2、APP Push API 的调用
推送渠道:APP推送不仅仅要求在APP打开状态时或者后台运行时进行消息推送,更多的场景是在移动终端关闭APP的场景下进行消息推送,
渠道的优劣无非在于两个维度,送达率和送达效率。
其中安卓推送的渠道较为杂乱,其中华为和小米提供的PUSH服务对于自平台的移动终端支持的较为完善,而没有厂商提供PUSH服务的终端只能通过
第三方服务来进行对接。
对于现有的这些渠道进行如下总结:
1、IOS:信鸽推送,这个推送在我门公司中经历了三个项目,推送效果稳定。API接入也方便,是IOS端的不二选择。
2、Android-华为:华为自平台。
3、Android-小米:小米自平台。
4、Android-其他:目前使用的是“极光推送”。在理想状态下送达率和送达效率表现很好,但并不如以上三家渠道稳定。
在进行调用时可根据之前定义的push_channel分发给各自的渠道,各渠道的具体对接请各自查看官网,API都很完善。
相关文章推荐
- 用JPUSH极光推送实现服务端向安装了APP应用的手机推送消息(C#服务端接口)
- 用JPUSH极光推送实现服务端向安装了APP应用的手机推送消息(C#服务端接口)
- APP消息推送机制的实现(PUSH)
- 用JPUSH极光推送实现服务端向安装了APP应用的手机推送消息(C#服务端接口)
- 解析php做推送服务端实现ios消息推送
- iPhone消息推送机制(Push)实现及通过.net应用程序发送消息给ios应用程序
- 使用pushlet实现消息服务端推送至客户端
- php做推送服务端实现ios消息推送
- Android中利用App实现消息推送机制的代码
- pushlet实现服务端推送消息到浏览器
- [Erlang 0106] Erlang实现Apple Push Notifications消息推送
- 基于MQTT实现Android消息推送(Push)(2)
- iPhone消息推送机制(Push)实现及通过.net应用程序发送消息给ios应用程序
- pushlet实现服务端推送消息到浏览器
- 关于消息推送的补充,主要介绍服务端的实现,包含object c 版本 c 版本 java 版本 php 版本 (转)
- 实现一个简单的服务端推送方案-实例篇Push
- Grails 中使用 grails-events-push 实现 ajax/comet/websocket 消息推送
- iPhone消息推送机制(Push)实现及通过.net应用程序发送消息给ios应用程序
- android中push机制实现:搭建XMPP协议,实现自主推送消息到手机
- Android中利用App实现消息推送机制的代码