目录
- 一、进程的一些基本常识
- 二、如何保活
- 三、如何拉活
- 四、总结
一、进程的一些基本常识
Low Memory Killer
- 系统出于体验和性能上的考虑,app在退到后台时系统并不会真正的kill掉这个进程,而是将其缓存起来。
- 打开的应用越多,后台缓存的进程也越多。
- 在系统内存不足的情况下,系统开始依据自身的一套进程回收机制来判断要kill掉哪些进程,以腾出内存来供给需要的app, 这套杀进程回收内存的机制就叫 Low Memory Killer。
进程优先级
官网说明 何时杀死进程
内存阈值在不同的手机上不一样,一旦低于该值,Android便会杀死对应优先级的进程,例如,当可用内存小于180MB(46080),就杀死空进程。
上图中的数字分别对应为:
18432:前台进程大小
23040:可见进程
27648:服务进程
32256:后台进程
36864:contentProvider
46060:空进程
阈值的单位是4KB
如何判断进程的优先级
- 通过oom_adj值,判断进程的优先级
- 不同手机的oom_adj 值可能不一样
- 目标:值变低,优先级变高
二、如何保活
1. Activity 1像素保活
原理: 手机关闭屏幕时,偷偷创建一个Activity,让应用成为前台进程;打开屏幕时,关闭该Activity。
缺点: 存在一个Activity不够干净。同时也需要在锁屏后才能提权。
Activity 1像素保活主要代码:
2、前台 Service 保活
原理: 启动一个前台服务,从而拉高整个应用的优先级。
缺点: API >=26 后暂时没有方式能够隐藏通知
三、如何拉活
1、广播拉活
在发生特定系统事件时,系统会发出广播,通过在 AndroidManifest 中静态注册对应的广播监听器,即可在发生响应事件时拉活。
但是从android 7.0开始,对广播进行了限制,而且在8.0更加严格https://developer.android.google.cn/about/versions/oreo/background.html#broadcasts
可静态注册广播列表:
https://developer.android.google.cn/guide/components/broadcast-exceptions.html
“全家桶”拉活
有多个app在用户设备上安装,只要开启其中一个就可以将其他的app也拉活。比如手机里装了手Q、QQ空间、兴趣部落等等,那么打开任意一个app后,其他的app也都会被唤醒。
2、Service系统机制拉活
START_STICKY:
“粘性”。如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
START_NOT_STICKY:
“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
START_REDELIVER_INTENT:
重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
START_STICKY_COMPATIBILITY:
START_STICKY的兼容版本,但不保证服务被kill后一定能重启。
只要 targetSdkVersion 不小于5,就默认是 START_STICKY。
但是某些ROM 系统不会拉活。并且经过测试,Service 第一次被异常杀死后很快被重启,第二次会比第一次慢,第三次又会比前一次慢,一旦在短时间内 Service 被杀死4-5次,则系统不再拉起。
3、账户同步拉活
手机系统设置里会有Account帐户一项功能,任何第三方APP都可以通过此功能将我们自己的APP注册到这个Account帐户中,并且将数据在一定时间内同步到服务器中去。系统在将APP帐户同步时,自动将未启动的APP进程拉活,
系统账号同步机制拉活步骤:
- 继承Service并在内部继承实现用于返回Binder的AbstractAccountAuthenticator
- 在res/xml/文件夹下定义将要显示在Account列表的资源
- 在清单文件中配置AuthenticationService
- 创建App的账户
- 创建账户同步Service
- 告知系统我们的Account需要进行同步服务
- 完整的清单配置文件和MainActivity代码
优点:系统唤醒,比较稳定
缺点:时间不能把控
4、 JobScheduler 进程拉活APP
JobScheduler允许在特定状态与特定时间间隔周期执行任务。可以利用它的这个特点完成保活的功能,效果即开启一个定时器,与普通定时器不同的是其调度由系统完成。
同样在某些ROM可能并不能达到需要的效果
5、双进程守护
双进程守护的思想就是,两个进程共同运行,如果有其中一个进程被杀,那么另一个进程就会将被杀的进程重新拉起,相互保护,在一定的意义上,维持进程的不断运行。
双进程守护的两个进程,一个进程用于我们所需的后台操作,且叫它本地进程,另一个进程只负责监听着本地进程的状态,在本地进程被杀的时候拉起,于此同时本地进程也在监听着这个进程,准备在它被杀时拉起,我们将这个进程称为 远端进程。
由于在 Android 中,两个进程之间无法直接交互,所以我们这里还要用到 AIDL (Android interface definition Language ),进行两个进程间的交互。
操作步骤
- 新建AIDL文件(可配置方法)
- 新建本地service和远端service
- 绑定并监听onServiceDisconnected方法,拉起另一进程
四、总结
没有一种方式是能够保证你的应用一直存活在内存中的,但是能延长时间也很不错了。
系统会优先杀死占用内存多的应用,所以想让自己的应用活的更久,还可以从性能上去优化,让其尽可能少的占用内存。