Android系统的保活永远是个令人头疼的问题,在此做一个简单的整理首先上个图
我们先明确一点我们要做保活 就要明白他为什么会被杀死,杀死行为一般分为两种 :
一、OOM-killer
这是基于linux内核的一种Android自身的进程回收
二、用户行为杀死
比如任务简卡栏时的点击一键回收清空所有进程,或者仅仅只操作某个App希望将它彻底杀死
虽然本篇重点在第一种OOM-killer 但是第二种情况想要保活的话也简单的说一下 这种情况下想要不被清理 手段1是引导用户锁定App手段2是让App本身占用某些正在使用中系统资源,比如说用Mediaplayer正在播放音乐。(某些无良App的后台静默播放音乐就是这个道理),但是有正向例子,网易云音乐后台播放声音时 一键清理是不会清理掉的,除非用户手动强行清理它自己
Android进程外保活
Android本身是linux fork出来的一个进程 应用App受到Android的OOM-Killer的控制 所有就有人想到同样用linux fork出来一个跟Andriod同级的进程,检测Android系统是否回收了目标App 如果收到了进行拉活。JNI的方式搞事情这里就简单说一下
Android进程内保活
一、进程保活
说白了就是希望OOM-killer不干掉自己,因此按照其回收规则,拼命的提升自己的优先级,如何把自己的oom_adj值提升 成了这一小章节的主要内容。怎么样让App尽可能的抢占前台可见资源或者Android系统正在使用的系统资源成了重中之重。
- Notification 保活 前台可见的Notification的OOM-ADJ值是2 一个可见的前台通知是非常稳妥的保活手段。
- 前台Service保活,总所周知,一个Service没有自己独立的进程,它一般是作为一个线程运行于它所在的应用进程中,且应用进程名称与包名一致。如果希望指定的组件和应用运行在指定的进程中,就需要通过android:process属性来为其创建一个进程 对API大于18而言 startForeground()方法需要弹出一个可见通知,如果不喜欢,可以开启另一个Service将通知栏移除,核心代码如下
if (Build.VERSION.SDK_INT < 18) {
startForeground(XX_SERVICE_ID, new Notification());//API < 18 ,此方法能有效隐藏Notification上的图标
} else {
Intent innerIntent = new Intent(this, XXService.class);
startService(innerIntent);
startForeground(XX_SERVICE_ID, new Notification());
}
3.循环静默播放一段无声音乐,通过占有Mediaplayer资源,努力让Mediaplayer依附的Activity存活,从而使得进程存活,此方式利用手段国内厂商的rom优化漏洞进行保活,主要用来防止用户从任务栏中一键杀死。
4.一像素,这个大家应该很了解了,将Activity压缩到1像素,从而提升OOM—adj的值原本的后台低优先级的Activity就这么被提升了优先级
5.双进程守护,其实也是个多进程守护,一组捆绑进程一个死了就让存活的进程给拉起来,这种在基于Android只管理主进程不管子进程的骚操作终于在6.0后主进程死亡,从属进程一起被回收而告一段落。
二、死后拉活
- 手机厂商及三方推送及Push拉活,目前的厂商push是有自己单独一个push进程,此push进程内的消息不代表被push进程的激活。
- JobScheduler拉活 (靠谱 系统Api支持)
- 利用系统广播拉活 (不靠谱 系统Api开始大力查杀 较新版的系统已经明确禁止)
- Service 的START_STICKY拉活
- Account保活 利用系统的Account机制,在系统账户内进行注册后会定时接受系统通知,(受到手机厂商的控制,很多手机会出现一直无法生效的情况)很多人说Account可以进行拉活,我测试发现机率极低,因此放在保活方式内,另外我有看到一款测试机的显示上一次的账户同步时间是3年前。。
以上几种拉活方式都很简单,但是需要具体的业务代码做支持,所以不展开聊了,如果大家有什么想法欢迎沟通
另附学习的部分资料