进程保活方案探究
1、进程分类
前台进程、可见进程、服务进程、后台进程、空进程(概念请百度,此处忽略)
2、Android进程回收策略
Android对于内存的回收,主要依靠LowMemoryKiller来完成,是一种根据oom_adj阈值级别触发相应力度的内存回收机制。
oom_adj值越小,表示进程优先级越高。
可以cat proc/xxx/oom_adj查看各进程的oom_adj值,xxx表示进程pid,可以通过ps命令查看
3、提高进程优先级的方案
3.1利用一个1像素的Activity提升优先级
3.1.1. 方案设计思想
监控手机锁屏、解锁事件,在屏幕锁屏时启动1个像素的 Activity,在用户解锁时将 Activity 销毁掉。注意该 Activity 需设计成用户无感知。
通过该方案,可以使进程的优先级在屏幕锁屏时间由4提升为最高优先级1。
3.1.2. 方案适用范围
适用场景: 本方案主要解决第三方应用及系统管理工具在检测到锁屏事件后一段时间(一般为5分钟以内)内会杀死后台进程,已达到省电的目的问题。
适用版本: 适用于所有的 Android 版本。
3.1.3. 方案具体实现
定义 Activity,并设置 Activity 的大小为1像素
3.2利用Notification提升优先级
注:微信、支付宝等就使用的是该方案,故此设备管理平台将会采取该方案
3.2.1. 方案设计思想
Android 中 Service 的优先级为4,通过 startForeground 接口可以将后台 Service 设置为前台 Service,使进程的优先级由4提升为2,从而使进程的优先级仅仅低于用户当前正在交互的进程,与可见进程优先级一致,使进程被杀死的概率大大降低。
3.2.2. 方案实现挑战
从 Android2.3 开始调用 startForeground 将后台 Service 设置为前台 Service 时,必须在系统的通知栏发送一条通知,也就是前台 Service 与一条可见的通知时绑定在一起的。
对于不需要常驻通知栏的应用来说,该方案虽好,但却是用户感知的,无法直接使用。
3.2.3. 方案挑战应对措施
通过实现一个内部 Service,在 核心服务CoreService 和其内部 InnerService 中同时发送具有相同 ID 的 Notification,然后将内部 InnerService Kill掉。随着内部 Service 的结束,Notification 将会消失,但系统优先级依然保持为2。
3.2.4. 方案适用范围
适用于目前已知所有版本。
3.2.5. 方案具体实现
略
- 进程死后拉活方案
4.1可以监听系统时钟广播
此方案对于需要和服务器一直保持长连接的场景不适用,故此再次不做描述。
4.2 利用系统Service机制自动拉活
4.2.1方案设计
将 Service 设置为 START_STICKY,利用系统机制在 Service 挂掉后自动拉活
4.2.2 方案适用场景
如下两种情况无法拉活:
Service 第一次被异常杀死后会在5秒内重启,第二次被杀死会在10秒内重启,第三次会在20秒内重启,一旦在短时间内 Service 被杀死达到5次,则系统不再拉起。
进程被取得 Root 权限的管理工具或系统工具通过 force stop 停止掉,无法重启。
Ps:有空需要验证尝试下
还有其他一些方案,个人认为不是很适用,故此不在此分享,有高见的欢迎补充
另外,无论采取何种方案保活,只要用户从设置中应用管理界面都可以强行Kill掉该应用,并且Kill掉不会起来。
我个人目前采取的方案是在这里过滤掉我们想要保活的进程,如下:
- 从已下载和全部列表过滤
packages\apps\Settings\src\com\android\settings\applications\ApplicationsState.java
- 从正在运行的进程列表中过滤
packages\apps\Settings\src\com\android\settings\applications\RunningState.java