Android中的进程保活 | 世道无情

1. 概述


根据前辈们的经验,如果没有白名单,Android系统要做一个任何情况下都不被杀死的应用几乎是不可能的,但我们可以做一个最大程度不被杀死,如果被杀死可以立即让它在第一时间内复活,那也是ok的。网上的进程常驻也是众说纷纭,这篇文章就总结下Android中进程保活的一些可行性方法,当然这些东西也不是我发明的,我只是在网上查询之后将其写成自己的文章,然后分享出来。

2. 白名单概念?


首先说下什么是白名单?白名单就是把我们自己的应用直接内置到一些手机厂商的手机中,让其手机厂商自带该应用,即就是该app软件

3. 问题?


3.1>:系统为什么会杀死进程?
3.2>:为什么会杀死我们的进程?
3.3>:根据什么规则决定?
3.4>:是一次杀掉多个,还是一个一个杀死?
那么带着这几个问题,我们就继续往下边来看。

4. 分析


4.1>:进程的划分,如下图所示
进程优先级.png
分析上图可以得知,进程被分为5种,按照优先级从高到低:
1>:活动进程

优先级最高,指的是用户正在操作的程序,是前台进程,并且可以操作的;

2>:可见进程

次高优先级,指的是看的见,摸不着,不能直接操作的进程;

3>:服务进程

第三优先级,没有界面,一直运行在后台,优先级不高,当系统内存不足的时会被杀死,当内存再次充裕时会重新再次开启;

4>:后台进程

低优先级,用户按下home或者back键后,程序本身看不到了,但是其实还是在运行的程序;比如Activity调用 onPause()方法,系统可能随时终止它们,回收内存;

5>:空进程

优先级最低,某个进程不包含任何活跃的组件,该进程就会被置为空进程,完全没用,系统会第一个回收空进程。

4.2>:内存阈值

app在返回到后台时,系统并不会kill这个进程的,而是将其缓存起来。打开的进程越多,后台缓存的进程就越多,系统在内存不足时,会根据自身的一套进程回收机制来判断需要kill掉哪些进程,来腾出内存给有需要的app,这套杀死进程回收内存的机制就叫做 Low Memory Killer。怎样去规定内存不足,就是内存阈值,可以使用 cat /sys/module/lowmemorykiller/parameters/minfree 来查看手机的内存阈值;

可以看出上边的6个数字,这些数字的单位就是 page。 1page=4kb,上边的6个数字对应的就是 MB,及对应的是 72,90,108,126,144,180,这些数字就对应的是内存阈值,内存阈值在不同手机上不一样,一旦低于该值,Android便开始顺序关闭进程,也就是说结束优先级最低的进程,即就是最小可用内存小于 180MB (46080*4/1024)。

注意:

进程是有它的优先级,该优先级是根据进程的adj值来反映,它是 Linux内核分配给每个进程的一个值,进程回收机制是根据优先级决定的。
oom_adj越大,占用的物理内存越大,会被最先kill掉,也就是说现在可以 把 进程如何保活变成 如何减小 oom_adj的值,来使应用内存占用最小。

5. 进程保活使用方法


5.1>:开启一个像素的Activity

思想就是:系统一般不会杀死前台进程,所以要使进程常驻,只需要:
打开屏幕的时候关闭 一个像素的Activity;
锁屏的时候开启一个 一个像素的Activity,透明并且没有动画;
做法就是 只需要监听系统的锁屏广播即可,代码如下:

1>:一个像素的Activity:

2>:在屏幕关闭的时候启动 一个像素的SinglePixelActivity ,打开屏幕的时候 finish掉 SinglePixelActivity ,所以需要监听系统锁屏的广播,使用接口形式通知 MainActivity 来 打开或者关闭 SinglePixelActivity ,该监听器代码如下:

3>:在MainActivity中测试:

经过测试,按下back返回键之后,然后锁屏,测试一下 oom_adj的值,发现进程的优先级提高了。

由于需要考虑内存的问题,因为内存占用越多的进程会被最先杀掉,所以需要把上边的 MainActivity中的业务逻辑放在Service中,然后直接在 MainActivity 中开启这个服务就ok,这样进程会更加轻量。

4>:LiveService代码如下:

5>:修改后的MainActivity代码如下:

5.2>:前台服务

微信的进程保活之前也是采用这种方式,其实就是利用 前台Service的漏洞
原理如下:
对于 API level < 18 ,调用 startForeground(ID, new Notification()),发送的是空的 Nofication,图标则不会显示;
对于 API level >= 18 ,在优先级的 KeepLiveService中启动 一个 InnerService,让两个服务同时启动 startFroeground(),且绑定同样的 Id,然后再 停掉 InnerService即可,代码如下:

5.3>:相互唤醒

意思就是如果你手机里边安装了 淘宝、天猫、支付宝等阿里系的 app,那么你打开任意一个 阿里的app之后,有可能就把阿里系的其他 app就给唤醒了。
所以说可以让 QQ、微信、淘宝、天猫、支付宝等app可以保活自己的应用也可以,或者像友盟、信鸽这种 推送的SDK,也有唤醒app的功能。

5.4>:JobScheduler

是一种进程死后复活的一种手段,native进程缺点是费电,原因是感知主进程是否存活有两种方式。在Native进程中通过死循环或者定时器,轮训判断主进程是否存活,如果不存活就拉活,5.0以上不支持。但是JobScheduler可以代替5.0以上 Native进程的方式。这种方式即使用户强制关闭,也能被拉起来,代码如下:

5.5>:粘性服务与系统捆绑服务

捆绑服务很好理解,比如NotificationListenerService,用来监听手机通知的,只要手机收到了通知,NotificationListenerService都能监听到,即使用户把进程杀死,也能重启,所以我们可以把这个进程放到我们的服务中,代码如下:

需要在清单文件中配置

 

代码已上传至github:
https://github.com/shuai999/ProcessDemo.git

作者: RESSRC

个人资源站

发表评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据