Android 进程保活系列:(二)利用 Notification 提升权限

前一篇文章 —— Android 进程保活系列:(一)利用 Activity 提升权限 讲到了利用前台的 Activity 保证系统管家不会杀死我们的应用。这只是一种讨巧的技术手段,并没有利用系统的漏洞。今天要说的方法适用性非常广,应用间互不干扰,不存在像是我开启一像素 Activity 把你盖住,然后你我争夺焦点的问题。

在实践之前还是先看看别人家的应用,比如腾讯新闻。adb shell 下输入

dumpsys activity services com.tencent.news
Android 进程保活系列:(二)利用 Notification 提升权限_第1张图片
腾讯新闻前台 Service

看一下控制台的输出,顾名思义 PushService 应该是推送服务,ServiceRecord 指明了它是前台服务。我们看一下它的 oom_adj 的值:

ps | grep com.tencent.news
cat /proc/25890/oom_adj
进程优先级

没错,PuseService 的优先级是 2,属于可感知进程,一般不会被杀死。下面有个关于 oom_adj 的说明。

Android 进程保活系列:(二)利用 Notification 提升权限_第2张图片
oom_adj 说明

其中红色部分代表比较容易被杀死的 Android 进程(OOM_ADJ >= 4),绿色部分表示不容易被杀死的 Android 进程,其他表示非 Android 进程(纯 Linux 进程)。在 Lowmemorykiller 回收内存时会根据进程的级别优先杀死 OOM_ADJ 比较大的进程,对于优先级相同的进程,则进一步受到进程所占内存和进程存活时间的影响。

下面就来亲身实践一下。利用系统的漏洞开启前台服务,提升进程的优先级。这里有两个思路:

  • 思路一:API < 18,启动前台 Service 时直接传入new Notification();
  • 思路二:API >= 18,同时启动两个id相同的前台 Service,然后再将后启动的 Service 做 stop 处理;
 // 要开启前台的 service
@Override
public int onStartCommand(Intent intent, int flags, int startId) {      
    if (Build.VERSION.SDK_INT < 18) {
        startForeground(SERVICE_ID, new Notification());    
    } else {        
        startForeground(SERVICE_ID, new Notification());        
        Intent sendIntend = new Intent(this, ChannelService.class);        
        startService(sendIntend);    
    }
    return super.onStartCommand(intent, flags, startId);
}

// 为开启前台 service 服务的傀儡 service
@Override
public int onStartCommand(Intent intent, int flags, int startId) {     
    startForeground(DaemonService.SERVICE_ID, new Notification());    
    stopForeground(true);    
    stopSelf();    
    return super.onStartCommand(intent, flags, startId);
}

这样就完成了,我们再次用 shell 命令验证一下。

Android 进程保活系列:(二)利用 Notification 提升权限_第3张图片
自己的前台服务

没错,它已经是前台服务了,用户看不见摸不着的前台服务,系统是不会轻易杀死该服务的,可以放心大胆地搞事情啦~~

项目地址:AndroidKeepPractive

参考链接:
  • 关于 Android 进程保活,你所需要知道的一切
  • 【腾讯Bugly干货分享】Android 进程保活招式大全

你可能感兴趣的:(Android 进程保活系列:(二)利用 Notification 提升权限)