Android 进程优先级详解 与 进程保活

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011033906/article/details/89455596

保活手段

主要从两个方面考虑:

  • 提供进程优先级,降低进程被杀死的概率
  • 在进程被杀死后,进行拉活

当前业界的Android进程保活手段主要分为 黑、白、灰 三种,其大致的实现思路如下:

  • 黑色保活:不同的app进程,用广播相互唤醒(包括利用系统提供的广播进行唤醒)
  • 白色保活:启动前台 Service
  • 灰色保活:利用系统的漏洞启动前台 Service

黑色保活

所谓黑色保活,就是利用不同的app进程使用广播来进行相互唤醒。举个3个比较常见的场景:

  • 1,开机,网络切换、拍照、拍视频时候,利用系统产生的广播唤醒app
  • 2,接入第三方SDK也会唤醒相应的app进程,如微信sdk会唤醒微信,支付宝sdk会唤醒支付宝。由此发散开去,就会直接触发了下面的 场景3
  • 3,假如你手机里装了支付宝、淘宝、天猫、UC等阿里系的app,那么你打开任意一个阿里系的app后,有可能就顺便把其他阿里系的app给唤醒了。(只是拿阿里打个比方,其实BAT系都差不多)

针对场景1,估计Google已经开始意识到这些问题,所以在最新的Android N取消了 ACTION_NEW_PICTURE(拍照),ACTION_NEW_VIDEO(拍视频),CONNECTIVITY_ACTION(网络切换)等三种广播,无疑给了很多app沉重的打击。

而开机广播的话,记得有一些定制ROM的厂商早已经将其去掉。

针对场景2和场景3,因为调用SDK唤醒app进程属于正常行为,此处不讨论。但是在借助LBE分析app之间的唤醒路径的时候,发现了两个问题:

  • 很多推送SDK也存在唤醒app的功能
  • app之间的唤醒路径真是多,且错综复杂

白色保活

白色保活手段非常简单,就是调用系统 api 启动一个前台的 Service 进程,这样会在系统的通知栏生成一个 Notification,用来让用户知道有这样一个 app 在运行着,哪怕当前的app退到了后台。

灰色保活

灰色保活,这种保活手段是应用范围最广泛。它是利用系统的漏洞来启动一个前台的Service进程,与普通的启动方式区别在于,它不会在系统通知栏处出现一个Notification,看起来就如同运行着一个后台Service进程一样。

这样做带来的好处就是,用户无法察觉到你运行着一个前台进程(因为看不到Notification),但你的进程优先级又是高于普通后台进程的。那么如何利用系统的漏洞呢,大致的实现思路和代码如下:

  • API < 18,启动前台Service时直接传入new Notification();
  • API >= 18,同时启动两个id相同的前台Service,然后再将后启动的Service做stop处理;
public class GrayService extends Service {

    private final static int GRAY_SERVICE_ID = 1001;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (Build.VERSION.SDK_INT < 18) {
            startForeground(GRAY_SERVICE_ID, new Notification());//API < 18 ,此方法能有效隐藏Notification上的图标
        } else {
            Intent innerIntent = new Intent(this, GrayInnerService.class);
            startService(innerIntent);
            startForeground(GRAY_SERVICE_ID, new Notification());
        }

        return super.onStartCommand(intent, flags, startId);
    }

    ...
    ...

    /**
     * 给 API >= 18 的平台上用的灰色保活手段
     */
    public static class GrayInnerService extends Service {

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            startForeground(GRAY_SERVICE_ID, new Notification());
            stopForeground(true);
            stopSelf();
            return super.onStartCommand(intent, flags, startId);
        }

    }
}

微信、qq、支付宝、陌陌 都这样子做了。

进程回收机制

熟悉Android系统的童鞋都知道,系统出于体验和性能上的考虑,app在退到后台时系统并不会真正的kill掉这个进程,而是将其缓存起来。打开的应用越多,后台缓存的进程也越多。在系统内存不足的情况下,系统开始依据自身的一套进程回收机制来判断要kill掉哪些进程,以腾出内存来供给需要的app。

这套杀进程回收内存的机制就叫 Low Memory Killer ,它是基于Linux内核的 OOM Killer(Out-Of-Memory killer)机制诞生。

了解完 Low Memory Killer,再科普一下oom_adj。什么是oom_adj?它是linux内核分配给每个系统进程的一个值,代表进程的优先级,进程回收机制就是根据这个优先级来决定是否进行回收。对于oom_adj的作用,你只需要记住以下几点即可:

  • 进程的oom_adj越大,表示此进程优先级越低,越容易被杀回收;越小,表示进程优先级越高,越不容易被杀回收
  • 普通app进程的oom_adj>=0,系统进程的oom_adj才可能<0

进程优先级

  • 前台进程
  • 可见进程
  • 服务进程
  • 后台进程
  • 空进程

具体可见: https://segmentfault.com/a/1190000006251859

猜你喜欢

转载自blog.csdn.net/u011033906/article/details/89455596