推送定义:在任何时间地点服务端向客户端推送一条消息,如果客户端在线或者下次上线,就能接收到该消息。通常想到的实现方式是:轮询、tcp长连,其目的都是让服务端和客户端之间时刻保持在线状态对于客户端而言,轮询:无非是写个线程按某种配置的时间间隔无限循环去请求服务端是否有新的消息,当有新的消息,就提醒给用户tcp长连:与服务端建立tcp长连,这样服务端就可以直接给客户端发送消息了,当前市面上基本上是以此种方式居多上面两种方式都是比较消耗资源的,而这里我们使用的是另外的一种方式来实现的,如MobPushudp无连接:其实现基本原理为,客户端创建socket并向服务端发送udp包,服务端接收到请求连接的udp包之后,将客户端id与ip和端口号进行绑定,当要向某个客户端id发送消息时,找到其对应的ip和端口号,然后将消息组装成udp包发送即可,其大致流程如下:.
而对于客户端需要解决的如下几个问题:
如何维护客户端id与路由之间的绑定关系;如何延长客户端的在线状态(app保活) 客户端性能考虑下面将针对这几点进行逐步介绍
维护客户端与路由的绑定关系这里我们需要了解一下NAT,所谓NAT就是,在局域网内部网络中使用内部地址,而当内部节点要与外部网络进行通讯时,就在网关处,将内部地址替换成公用地址,从而在外部公网上正常使用。所以当发送udp包到服务器时,服务器拿到的ip和端口其实是客户端在路由上映射的ip和端口,所以我们需要维护路由上的映射表,这时就需要定期发送心跳包,以保证路由上的映射关系不会被清除掉。
维护心跳包主要作用是防止NAT超时, 和探测连接是否断开,并根据实际情况进行重连操作,其流程如下:
网络监测当网络切换和变化时,会导致映射关系失效,所以我们需要做相应的监测和重连监听网络变化,当网络类型变化或者断开后重新连接上时,进行重连定期监测ip地址变化,如果监测到ip地址有变化时,则进行重连APP保活
app保活是一个老生常谈的话题,经过广大开发者多年累积与筛选,互联网上相关文章层出不穷,目前看来不算什么硬梗,大多都按套路出行,这里也套路套路当应用退到后台时,为了确保推送通道能够正常使用而不被系统回收,通常会做一些进程保活和拉活的策略,大体分为以下几类:
利用系统Service机制拉活将 Service 设置为 START_STICKY,利用系统机制在 Service 挂掉后自动拉活
如下两种情况无法拉活:1.Service 第一次被异常杀死后会在5秒内重启,第二次被杀死会在10秒内重启,第三次会在20秒内重启,一旦在短时间内 Service 被杀死达到5次,则系统不再拉起。2.进程被取得 Root 权限的管理工具或系统工具通过 forestop 停止掉,无法重启。经测试,在绝大多数手机任务进程中,手动杀掉进程后,是不会自动重启的(符合情况2)
设置进程优先级当进程退到后台后,系统在回收资源时,会根据进程优先级,进行资源回收,优先级越高越晚被回收,所以尽可能地提高service进程的优先级,可以在一定程度上保障其在后台时不被系统回收
进程按照重要性分为如下5类:1.前台进程(Foreground process)2.可见进程(Visible process)3.服务进程(Service process)4.后台进程(Background process)5.空进程(Empty process)一般的后台进程进程属于第4类,我们可以通过setForeground将service提升到2,但是这种方案必须与一条可见的通知绑定在一起,而这种体验显然不能被用户接受当然我们可以通过new Notification()的方式设置一个空的通知,与之绑定,但只在4.3以下版本才有效,如下:
神奇的开发者们发现了一种通过多实现一个TmpService,在MainService和TmpService两个service中同时发送具有相同 ID 的 Notification,然后干掉TmpService,这时Notification会自动消失,而MainService的优先级已经被提升到2了,从而达到了目的。缺陷是:需要开发者在manifest多配置一个service,可能在不久的将来也会被官方更新掉,不建议采纳。
利用系统广播拉活该方式是通过AndroidManifest.xml 注册一些特定的系统广播方式,来拉活进程,但是这种方式在高版本中已经被官方封掉了,所以也成了一堆没必要的配置
当然我们可以在代码中添加了相关的系统广播注册、同时在监听进程死掉时发送的广播,测试在某些低版本的手机上有效
使用AlarmManager
使用AlarmManager定时发送心跳、定时检查ip变化
但是经测试当系统休眠时,AlarmManager也停止了工作,且在不同sdk版本上需要采用不同的set方式,如下:
领取专属 10元无门槛券
私享最新 技术干货