0. 前言
目前市面上的应用,貌似除了微信和QQ都会比较担心被用户或者系统厂商杀死的问题。Android 进程拉活包括两个层面:(1)提供进程优先级,降低进程被杀死的概率。(2)在进程被杀死后,进行拉活。本文下面就从这两个方面做一下总结。
1. 提高进程优先级方面
1.1 进程优先级介绍
Android 系统将尽量长时间地保持应用进程,但为了新建进程或运行更重要的进程,需要清除旧进程来回收内存。为了确定保留或终止哪些进程,系统会根据进程中正在运行的组件以及这些组件的状态,将每个进程赋予“重要性”。必要时系统会首先消除重要性最低的进程以回收系统资源。进程的重要性从高到低可以划分为以下五级:
(1)前台进程(Foreground process),即用户当前操作所必需的进程,通常数量不多。举例如下:
//拥有用户正在交互的 Activity(已调用 onResume())
//拥有某个 Service,后者绑定到用户正在交互的 Activity
//拥有正在“前台”运行的 Service(服务已调用startForeground())
//拥有正执行一个生命周期回调的 Service(onCreate()、onStart() 或 onDestroy())
//拥有正执行其 onReceive() 方法的BroadcastReceiver
(
2
)可见进程
(Visible process)
,
没有任何前台组件、但仍会影响用户在屏幕上所见内容的进程
。举例如下:
//拥有不在前台、但仍对用户可见的 Activity(已调用 onPause())
//拥有绑定到可见(或前台)Activity 的 Service
(3)服务进程(Service process),尽管服务进程与用户所见内容没有直接关联,但是它们通常在执行一些用户关心的操作(例如在后台播放音乐或从网络下载数据)。举例如下:
//正在运行通过 startService() 方法启动的服务,且不属于上述两个更高类别进程的进程
(
4
)后台进程
(Background process)
,
后台进程对用户体验没有直接影响,系统可能随时终止它们
。通常会有很多后台进程在运行,因此它们会保存在
LRU
列表中,以确保包含用户最近查看的
Activity
所在进程最后一个被终止。举例如下:
//对用户不可见的 Activity 的进程(已调用 Activity的onStop() 方法)
(
5
)空进程
(Empty process)
,
保留这种进程的的唯一目的是用作缓存,以缩短下次在其中运行组件所需的启动时间
。
为使总体系统资源在进程缓存和底层内核缓存之间保持平衡,系统往往会终止这些进程。举例如下:
//不含任何活动应用组件的进程
1.2 如何提高 进程优先级
1.2.1 利用Activity提升权限
本方案针对的是某些工具或应用会在检测到锁屏事件后会杀死后台进程,(已达到省电的目的问题)。因此本方案可以监控手机锁屏解锁事件,在屏幕锁屏时启动1个像素的 Activity,在用户解锁时将 Activity 销毁掉。通过该方案,可以使进程的优先级在屏幕锁屏时间提升为最高优先级。
具体实现方案如下:首先定义 Activity,并设置 Activity 的大小为1像素:
其次,从 AndroidManifest 中通过如下属性,避免 Activity 在 RecentTask 中的显示:
最后,控制 Activity 为透明:
Activity 启动与销毁时机的控制:
1.2.2 后台Service设置为前台Service
通过 setForeground可以将后台Service设置为前台Service,使进程的优先级由4提升为2,使进程被杀死的概率大大降低。
但是从Android2.3开始调用setForeground将后台Service设置为前台Service时,必须在系统的通知栏发送一条通知,也就是说前台 Service 与一条可见的通知是绑定在一起的。解决方案的话,可以增加一个内部Service,在Service和它内部的Service中,同时发送具有相同ID 的 Notification,然后再将这个内部Service结束掉。随着内部 Service 的结束,通知将会消失,但系统优先级依然保持为2。具体实现如下:
2. 进程死后拉活方面
2.1 利用系统广播拉活
在发生特定系统事件时,系统会发出响应的广播,通过在Manifest中静态注册对应的广播监听器,即可在发生响应事件时拉活。常用的用于拉活的广播事件包括:
2.2 利用系统Service机制拉活
在service的onStartCommand方法里返回STATR_STICK,系统会重新创建这个服务并且调用onStartCommand()方法,当然了它不会重新传递Intent对象。
但是这种方案有弊端:
(1)Service 第一次被异常杀死后会在5秒内重启,第二次被杀死会在10秒内重启,第三次会在20秒内重启,一旦在短时间内Service被杀死达到5次,则系统不再拉起。
(2)如果我们的进程被取得Root 权限的管理工具强制停止(forestop)后也无法重启。
2.3 覆写Service的onDestroy方法
这种方案针对的是在设置里面,对正在运行的应用点击关闭,会走onDestroy方法,可以在这里可以把自己启动起来。
但是如果被取得Root权限的管理工具强制停止(forestop)的话,压根不会走到onDestory这个方法。
2.4 利用Native守护进程拉活
原理就是,在Android中所有进程和系统组件的生命周期受ActivityManagerService的统一管理。但是通过Linux 的fork机制创建的进程是Native进程,生命周期不受Android的管理。在Native守护进程中监控主进程的存活,当主进程挂掉后,在Native进程中立即对主进程进行拉活。
该方案主要适用于 Android5.0 以下版本的手机,并且不受 强制停止的影响。
对于Android5.0 以上手机,系统杀死进程的时候,不仅把主进程给杀死了,另外把主进程所属的进程组一并杀死,因此native进程可能会被杀死,但是这种情况不一定就拉不活。因为这其实是一个系统依次杀死进程的时间与拉活逻辑执行时间赛跑的问题,如果可以跑的比系统逻辑快,依然可以有效拉起。
记得网上有人做过实验,该结论在某些 Android 5.0 以上机型是成立的。该方案中的几个重要问题补充如下:
2.4.1 Native 进程中如何感知主进程死亡
(1)在 Native 进程中通过死循环或定时器,轮询判断主进程是否存活,当主进程不存活时进行拉活。但是缺点也很明显,就是轮询判断逻辑会非常耗电。
(2)具体判断主进程存活的方案是,在主进程中创建一个监控文件,并且在主进程中持有文件锁。在拉活进程启动后就去申请这个文件锁,然后就将会被堵塞,一旦拉活进程可以成功获取到锁,说明主进程挂掉,即可进行拉活。
由于Java 层的文件锁与 Linux 层的文件锁是不同的,需要封装Linux层的文件锁供上层调用。
2.4.2 Native 进程中如何拉活主进程
在Native 进程进行拉活的时候,本质上是通过am命令进行拉活。(通过指定“–include-stopped-packages”参数拉活主进程被forestop的情况)
2.5 利用JobScheduler机制拉活
Android5.0以上提供了一个叫JobScheduler的接口,可以把它理解成是一个操作系统层面的全局定时器,而不是像Alarm一样是以APP为界限的。它会定时唤醒进程,使应用进行一些逻辑操作。该方案在 Android5.0 以上版本中不受 forcestop 影响,被强制停止的应用依然可以被拉活,在 Android5.0 以上版本拉活效果非常好。仅在小米手机可能会出现有时无法拉活的问题。
2.6 利用帐号同步机制拉活
Android系统里有一个帐号系统,系统会通过账户同步机制,定期进行帐号的同步,我们可以自己设定同步的事件间隔。当系统发起更新后进行进程的拉活。
这个方案适用于除Android 7.0以外所有的 Android 版本,包括被 forestop 掉的进程也可以进行拉活。
但是这个方案弊端太多了:
(1)在7.0上系统对帐号同步做了一些变动。
(2)从用户角度来说,用户会在系统设置里的账户列表上看到一个不认识的账户;而且某些手机比如note3需要手动设置账户。
(3)从设备商角度看,同步的事件间隔是有限制的,最短1分钟,见源码,而且各种国产机怎么改的源码我们未知,是不是都能用仍然未知;
(4)从Google的角度来看,Google提供这个机制是让用于同步账户信息,必须联网,不联网则无法同步。
添加账号和设置同步周期的代码如下:
该方案需要在 AndroidManifest 中定义账号授权与同步服务。
2.7 推送拉活
根据终端不同,在小米手机(包括 MIUI)接入小米推送、华为手机接入华为推送,可以作为拉活方案的有效补充。
2.7 终极武器——客户粘性
为什么QQ、微信这些应用推送服务不会被杀死呢,是因为手机厂商不让它死,如果一个人买了个手机然后收不到QQ消息,估计这款手机就卖不出去了。
这就是客户粘性带来的效益,应用的客户粘性越高,就越有可能出现在手机厂商进程保活的白名单里。
感谢:
http://dev.qq/topic/57ac4a0ea374c75371c08ce8
http://blog.csdn/yyh352091626/article/details/50542554
http://blog.csdn/two_water/article/details/52126855
更多推荐
Android开发——Android进程保活招式大全
发布评论