Android进程保活调研

概述

1.1 编写目的

本文只是我在学习过程中的记录。

本文档旨在对Android的进程保活方案进行调研,避免android程序因系统资源紧张或用户主动去清理应用而导致的程序被系统杀死,导致“行啊”无法实时的接收最新的消息推送和通知。

调通过研目,了解系统为什么会杀掉进程,杀的为什么是我的进程,这是按照什么标准来选择的,是一次性干掉多个进程,还是一个接着一个杀,保活套路一堆,如何进行进程保活才是比较恰当以及实现思路。

1.2 名词解释

进程保活

保证应用程序服务不被系统杀死。

1.3参考文档

文章参考:http://blog.csdn.net/u013263323/article/details/56285475
本文中有部分内容摘自参考文档

第2章 了解进程

2.1 初步了解

Android应用启动后至少对应一个进程,有的是多个进程,而且主流应用中多个进程的应用比例较大。

手机进程查看.png

2.2 进程划分

2.2.1 前台进程

用户正在使用的程序,一般系统是不会杀死前台进程的,除非用户强制停止应用或者系统内存不足等极端情况会杀死。

场景

某个进程持有一个正在与用户交互的Activity并且该Activity正处于resume的状态。

某个进程持有一个Service,并且该Service与用户正在交互的Activity绑定。

某个进程持有一个Service,并且该Service调用startForeground()方法使之位于前台运行。

某个进程持有一个Service,并且该Service正在执行它的某个生命周期回调方法,比如onCreate()、 onStart()或onDestroy()。

某个进程持有一个BroadcastReceiver,并且该BroadcastReceiver正在执行其onReceive()方法。

2.2.2 可见进程

用户正在使用,看得到,但是摸不着,没有覆盖到整个屏幕,只有屏幕的一部分可见进程不包含任何前台组件,一般系统也是不会杀死可见进程的,除非要在资源吃紧的情况下,要保持某个或多个前台进程存活施。

场景

拥有不在前台、但仍对用户可见的 Activity(已调用 onPause())。

拥有绑定到可见(或前台)Activity 的 Service

2.2.3 服务进程

在内存不足以维持所有前台进程和可见进程同时运行的情况下,服务进程会被杀死。

场景

某个进程中运行着一个Service且该Service是通过startService()启动的,与用户看见的界面没有直接关联。

2.2.4 后台进程

系统可能随时终止它们,回收内存。

场景

在用户按了"back"或者"home"后,程序本身看不到了,但是其实还在运行的程序,比如Activity调用了onPause方法

2.2.5 空进程

场景

某个进程不包含任何活跃的组件时该进程就会被置为空进程,完全没用,杀了它只有好处没坏处,第一个干它。

2.3 内存阈值

进程是怎么被杀的呢?

系统出于体验和性能上的考虑,app在退到后台时系统并不会真正的kill掉这个进程,而是将其缓存起来。打开的应用越多,后台缓存的进程也越多。在系统内存不足的情况下,系统开始依据自身的一套进程回收机制来判断要kill掉哪些进程,以腾出内存来供给需要的app, 这套杀进程回收内存的机制就叫 Low Memory Killer。那这个不足怎么来规定呢,那就是内存阈值,我们可以使用cat /sys/module/lowmemorykiller/parameters/minfree来查看某个手机的内存阈值。

image.png

注意这些数字的单位是page. 1 page = 4 kb.上面的六个数字对应的就是(MB): 72,90,108,126,144,180,这些数字也就是对应的内存阀值,内存阈值在不同的手机上不一样,一旦低于该值,Android便开始按顺序关闭进程. 因此Android开始结束优先级最低的空进程,即当可用内存小于180MB(46080*4/1024)。

读到这里,你或许有一个疑问,假设现在内存不足,空进程都被杀光了,现在要杀后台进程,但是手机中后台进程很多,难道要一次性全部都清理掉?当然不是的,进程是有它的优先级的,这个优先级通过进程的adj值来反映,它是linux内核分配给每个系统进程的一个值,代表进程的优先级,进程回收机制就是根据这个优先级来决定是否进行回收,adj值定义在com.android.server.am.ProcessList类中,这个类路径是${android-sdk-path}\sources\android-23\com\android\server\am\ProcessList.java。oom_adj的值越小,进程的优先级越高,普通进程oom_adj值是大于等于0的,而系统进程oom_adj的值是小于0的,我们可以通过cat /proc/进程id/oom_adj可以看到当前进程的adj值。

image.png

看到adj值是0,0就代表这个进程是属于前台进程,我们按下Back键,将应用至于后台,再次查看

image.png

adj值变成了8,8代表这个进程是属于不活跃的进程,你可以尝试其他情况下,oom_adj值是多少,但是每个手机的厂商可能不一样,oom_adj值主要有这么几个,可以参考一下。

image.png

根据上面的adj值,其实系统在进程回收跟内存回收类似也是有一套严格的策略,可以自己去了解,大概是这个样子的,oom_adj越大,占用物理内存越多会被最先kill掉,OK,那么现在对于进程如何保活这个问题就转化成,如何降低oom_adj的值,以及如何使得我们应用占的内存最少。

第3章 进程保活方案

3.1 网上方案总结

3.1.1 开启一个像素Activity

在锁屏的时候在本进程开启一个Activity,为了欺骗用户,让这个Activity的大小是1像素,并且透明无切换动画,在开屏幕的时候,把这个Activity关闭掉,所以这个就需要监听系统锁屏广播。

image.png

我们的应用就始终和前台进程是一样的优先级了,为了省电,系统检测到锁屏事件后一段时间内会杀死后台进程,如果采取这种方案,就可以避免了这个问题,但是还是有被杀掉的可能。

Android5.0以下:

Process.killProcessQuiet(pid);

Android5.0以后:

Process.killProcessQuiet(app.pid);

Process.killProcessGroup(app.info.uid, app.pid);

应用退出后,ActivityManagerService不仅把主进程给杀死,另外把主进程所属的进程组一并杀死,这样一来,由于子进程和主进程在同一进程组,子进程在做的事情,也就停止了。

3.1.2 相互唤醒

相互唤醒的意思就是,假如你手机里装了支付宝、淘宝、天猫、UC等阿里系的app,那么你打开任意一个阿里系的app后,有可能就顺便把其他阿里系的app给唤醒了。这个完全有可能的。此外,开机,网络切换、拍照、拍视频时候,利用系统产生的广播也能唤醒app,不过Android N已经将这三种广播取消了。

3.1.3 JobSheduler机制保活

JobSheduler是作为进程死后复活的一种手段,native进程方式最大缺点是费电, Native 进程费电的原因是感知主进程是否存活有两种实现方式,在 Native 进程中通过死循环或定时器,判断主进程是否存活,当主进程不存活时进行拉活。其次5.0以上系统不支持。 但是JobSheduler可以替代在Android5.0以上native进程方式,这种方式即使用户强制关闭,部分厂商手机(如:华为)也能被拉起来,但AndroidN失效。

3.1.4 粘性服务&与系统服务捆绑

这个是系统自带的,onStartCommand方法必须具有一个整形的返回值,这个整形的返回值用来告诉系统在服务启动完毕后。Service的onStartCommand方法里返回 STATR_STICK,onDestory中start自启(准确的将算不上进程拉活,只能算service自启,force_stop后不能正常拉活)。

3.1.5 监听第三方app开放的静态广播

需要大量反编译app去找开放的静态广播,而且不保证长期有效,可能第三方开放广播在版本升级时改为私有广播,如果自己公司有多个app,可广播互相拉起。

3.2 NDK+Socket通过fork实现进程保活方案

实现进程守护实际是守护app的主要服务,当app主进程被系统kill时,主要服务也会杀死,守护进程将其唤醒。

实现原理图:

原理图.png

第4章 进程保活方案(NDK)实现

4.1 代码实现

4.1.1 模拟推送服务

image.png

4.1.2 客户端服务端实现

image.png

4.1.3 通过fork开启守护进程

image.png

4.1.4 通过socket实现客户端服务端绑定,实现关键服务守护

实现原理

image.png

image.png

代码实现

开启服务端,读取客户端状态


image.png
image.png
image.png

image.png

客户端进程

image.png

4.1.5 测试结果

程序运行:

image.png

通过adb命令kill掉宿主进程

ps查看存活进程

image.png

虽然守护进程存活但不能唤醒主服务。

Android M运行日志:

image.png

主进程服务被杀死,守护进程存活,但无法拉起宿主进程。

Android N运行日志:

image.png

Android N无法通过fork实现保活,并且导致安装时客户端服务端链接超时导致App崩溃。在Android N保活很难,基本上没什么软件能绝对的保活,用户杀掉app后禁止后台自动唤起,用什么办法都没用。

第5章 进程保活方案调研结果

未能实现真正意义上的进程保活。

光从保活这一点来说,绑定一个像素activity和循环一个无声的声音这种方法比较好,但是对用户来说太流氓了,不推荐。 对于有硬性需求的,可以引导用户加入白名单。至于推送, 可以尝试集成多个推送方案,小米,华为等都有推送sdk,在对应手机上可以确保收到消息, 然后像百度这种是多app公用通道的,也就是手机中有一个使用百度推送的app被允许后台启动,就能让其他app收到推送。随着Android版本的不断更新及国内厂商对ROM的不断优化,如何最大可能的对进程保活,是Android一道需要长期学习/钻研的学问,也是Android开发者不得不面对的问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335