要点
1、程序被杀的原因
2、系统回收程序机制
3、提高程序存活率的方法探究
程序被杀的原因
(1)程序在后台内存不足时被杀,或者后台存活程序数量被限制
(2)程序被第三方管理软件清理,比如360、CleanMaster
(3)程序被用户手动清理,比如小米自带的系统一键清理、手机设置里应用管理器的ForceClose
系统回收程序机制
Android程序运行机制
Android是一个多任务系统,启动运行一个程序是有一定的时间开销的,因此为了加快运行速度,当你退出一个程序时,Android并不会立即杀掉它,这样下次再运行该程序时,可以很快的启动
当系统中保留的程序越来越多时,内存会越来越少。low memory killer就是在系统内存低于某个阈值时,开始清理一些内存程序,保证有一定的内存空闲。
low memory killer
Android 的Low memory killer是基于linux的OOM(out of memory) 规则改进而来的。 OOM通过一些比较复杂的评分机制,对进程进行打分,然后将分数高的进程判定为bad进程,杀死并释放内存。OOM只有当系统内存不足的时候才会启动检查,而Low memory killer 则是定时进行检查。
释放的规则
Low memory killer根据两个原则,进程的重要性和释放这个进程可获取的空闲内存数量,来决定释放的进程
(1)进程的重要性,由oom_adj决定,查看方法:ps |grep 包名,/proc/pid/oom_adj,在系统中位置是/sys/module/lowmemorykiller/parameters/adj
名称 |
值 |
含义 |
内存阈值(以4K为单位) (具体值与手机相关) |
NATIVE_ADJ |
-17 |
Native 进程(不被系统管理) |
|
SYSTEM_ADJ |
-16 |
系统进程 |
|
CORE_SERVER_ADJ |
-12 |
系统核心服务 |
|
PERSISTENT_SERVICE_ADJ |
-11 |
关联着系统或persistent进程,比如telephony |
|
FOREGROUD_APP |
0 |
前台程序,可以理解为你正在使用的程序 |
1536 |
VISIBLE_APP |
1 |
用户可见的程序 |
2048 |
SECONDARY_SERVER |
2 |
后台服务 |
4096 |
BACKUP_APP_ADJ |
3 |
备份进程 |
|
HOME_APP |
4 |
HOME,就是主界面 |
5120 |
SERVICE_ADJ |
5 |
服务进程 |
|
HOME_APP_ADJ |
6 |
Home进程 |
|
HIDDEN_APP |
7 |
被隐藏的程序 |
5632 |
SERVICE_B_ADJ |
8 |
B List 中的Service |
|
CACHED_APP_MIN_ADJ |
9 |
不可见进程 |
|
CONTENT_PROVIDER |
14 |
内容提供者 |
6144 |
EMPTY_APP |
15 |
空程序,既不提供服务,也不提供内容 |
|
(2)进程内存,在相同的oom_adj条件下,内存越大,优先被清理掉。在系统目录/sys/module/lowmemorykiller/parameters下cat minfress可以查看各个进程类型的斩首阈值
提高程序存活率的方法探究
1、Service相关方法
(1) 在service的onStartCommand中返回START_STICKY
(2) 在service的onDestroy中启动自己,正常走onDestroy方法才有效
(3) 配置serviceandroid:persistent=“true”,这个需要系统签名才可以
2、提升优先级
(1) 启动前台service:利用系统的漏洞来启动一个前台的Service进程,与普通的启动方式区别在于,它不会在系统通知栏处出现一个Notification,看起来就如同运行着一个后台Service进程一样。这样做带来的好处就是,用户无法察觉到你运行着一个前台进程(因为看不到Notification),但你的进程优先级又是高于普通后台进程的
(2) 锁屏时开启一个像素的Activity,解锁时关闭这个页面,达到用户无感。把进程提升为可见进程
这种方法,用户强制杀掉程序以及第三方软件清理后,都无法启动。
3、拉起程序
(1)监听广播事件,检测进程是否存活,然后拉起。比如:开机广播、网络变化、屏幕亮灭、屏幕解锁、文件挂载、电源连接。 广播接收器被管理软件、系统软件通过“自启管理”等功能禁用的场景无法接收到广播,从而无法自启。
系统广播事件不可控,只能保证发生事件时拉活进程,但无法保证进程挂掉后立即拉活。
(2)跨进程bind一个service之后,如果被bind的service挂掉,bind他的service会把他拉起来。这种方法,被清理后,都启动不了
(3)使用闹钟定时器,定时唤醒。使用AlarmManager,这种方法耗电,而且被强制杀掉后,没有机会再起来
(4)接入第三方推送,第三方推送会有群体拉起功能。比如极光推送、个推推送,只要手机里打开了已经接入这些推送的程序,则会唤醒所有接入同一个推送的程序。BAT系的大厂,都有这种相互唤醒的机制,比如打开支付宝,会有淘宝、UC浏览器等的推送过来
(5)厂商白名单。大厂会跟大的手机厂商合作,把需要守护的进程加到系统进程级别,被杀后也可以立即起来。
(6)利用Native进程拉活。
有两种实现方案,一种是循环监听主进程是否存活,一旦被杀则启动,这种方式非常耗电,不推荐。
第二种方案是:在主进程中创建一个监控文件,并且在主进程中持有文件锁。在拉活进程启动后申请文件锁将会被堵塞,一旦可以成功获取到锁,说明主进程挂掉,即可进行拉活。由于 Android中的应用都运行于虚拟机之上,Java层的文件锁与 Linux层的文件锁是不同的,要实现该功能需要封装 Linux层的文件锁供上层调用。
这种方法不受强制关闭的影响,5.0以下版本有效,5.0版本以后系统对Native进程加强了管理,无效
(7) 利用 JobScheduler拉活:Android5.0以上版本提供了 JobScheduler接口,系统会定时调用该进程以使应用进行一些逻辑操作,可以尝试
(8)利用账号同步机制拉活。android系统里有一个账户系统,设置一个自己的账户,android会定期唤醒账户更新服务,首先要设置一个账户才行。用户会在账户系统中看到一个不认识的账号
(9)GCM推送(Google Cloud Messaging)谷歌云消息,类似苹果的Apns服务。但是国行手机基本上缺少系统组件,并且网络限制连接不上GCM服务器。国外用户可以接入
(10)手机大厂的推送,比如小米推送,华为推送
主要对策:
1、 以上方法能试的都给试试
2、 小米华为推送接入
3、 国外的接入GCM
4、 减少内存使用,降低被杀风险
5、 拆分进程
参考阅读
http://www.cnblogs.com/imstudy/p/5674480.html Android后台保活实践总结:即时通讯应用无法根治的“顽疾”
http://www.infoq.com/cn/articles/wechat-android-background-keep-alive#anch135151 微信Android客户端后台保活经验分享
http://blog.csdn.net/marswin89/article/details/48015453 Android进程常驻(1)----开篇
http://zhoujianghua.com/2015/07/28/black_technology_in_alipay/ 支付宝后台不死的黑科技
http://www.jianshu.com/p/63aafe3c12af# 关于 Android进程保活,你所需要知道的一切