Android 如何进行进程保活

如题所述

第1个回答  2022-06-29
每一个 Android 应用启动后至少对应一个进程,有的是多个进程,而且主流应用中多个

进程的应用比例较大

对于任何一个进程,我们都可以通过 adb shell ps|grep <package_name>的方式来查看

它的基本信息

Android 中的进程跟封建社会一样,分了三流九等,Android 系统把进程的划为了如下

几种(重要性从高到低),网上多位大神都详细总结过(备注:严格来说是划分了 6 种)。

场景:

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

状态。

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

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

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

5.某个进程持有一个 BroadcastReceiver,并且该 BroadcastReceiver 正在执行其onReceive()方法。用户正在使用的程序,一般系统是不会杀死前台进程的,除非用户强制停止应用或者系统内存不足等极端情况会杀死。

场景:

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

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

用户正在使用,看得到,但是摸不着,没有覆盖到整个屏幕,只有屏幕的一部分可见进程

不包含任何前台组件,一般系统也是不会杀死可见进程的,除非要在资源吃紧的情况下,

要保持某个或多个前台进程存活

场景

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

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

场景:

在用户按了"back"或者"home"后,程序本身看不到了,但是其实还在运行的程序,

比如 Activity 调用了 onPause 方法系统可能随时终止它们,回收内存

场景:

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

上面是进程的分类,进程是怎么被杀的呢?系统出于体验和性能上的考虑,app 在退到

后台时系统并不会真正的 kill 掉这个进程,而是将其缓存起来。打开的应用越多,后台缓存的进程也越多。在系统内存不足的情况下,系统开始依据自身的一套进程回收机制

来判断要 kill 掉哪些进程,以腾出内存来供给需要的 app, 这套杀进程回收内存的机制

就叫 Low Memory Killer。那这个不足怎么来规定呢,那就是内存阈值,我们可以使用

cat /sys/module/lowmemorykiller/parameters/minfree 来查看某个手机的内存阈值。

其实系统在进程回收跟内存回收类似也是有一套严格的策略,可以

自己去了解,大概是这个样子的,oom_adj 越大,占用物理内存越多会被最先 kill 掉,OK,那么现在对于进程如何保活这个问题就转化成,如何降低 oom_adj 的值,以及如

何使得我们应用占的内存最少。

据说这个是手 Q 的进程保活方案,基本思想,系统一般是不会杀死前台进程的。所以要

使得进程常驻,我们只需要在锁屏的时候在本进程开启一个 Activity,为了欺骗用户,

让这个 Activity 的大小是 1 像素,并且透明无切换动画,在开屏幕的时候,把这个 Activity

关闭掉,所以这个就需要监听系统锁屏广播,我试过了,的确好使,如下。

如果直接启动一个 Activity,当我们按下 back 键返回桌面的时候,oom_adj 的值是 8,

上面已经提到过,这个进程在资源不够的情况下是容易被回收的。现在造一个一个像素

的 Activity。

为了做的更隐藏,最好设置一下这个 Activity 的主题,当然也无所谓了

在屏幕关闭的时候把 LiveActivity 启动起来,在开屏的时候把 LiveActivity 关闭掉,所以

要监听系统锁屏广播,以接口的形式通知 MainActivity 启动或者关闭 LiveActivity。

现在 MainActivity 改成如下

按下 back 之后,进行锁屏,现在测试一下 oom_adj 的值

果然将进程的优先级提高了。

但是还有一个问题,内存也是一个考虑的因素,内存越多会被最先 kill 掉,所以把上面

的业务逻辑放到 Service 中,而 Service 是在另外一个 进程中,在 MainActivity 开启这

个服务就行了,这样这个进程就更加的轻量,

OK,通过上面的操作,我们的应用就始终和前台进程是一样的优先级了,为了省电,

系统检测到锁屏事件后一段时间内会杀死后台进程,如果采取这种方案,就可以避免了

这个问题。但是还是有被杀掉的可能,所以我们还需要做双进程守护,关于双进程守护,

比较适合的就是 aidl 的那种方式,但是这个不是完全的靠谱,原理是 A 进程死的时候,

B 还在活着,B 可以将 A 进程拉起来,反之,B 进程死的时候,A 还活着,A 可以将 B

拉起来。所以双进程守护的前提是,系统杀进程只能一个个的去杀,如果一次性杀两个,

这种方法也是不 OK 的。

事实上

那么我们先来看看 Android5.0 以下的源码,ActivityManagerService 是如何关闭在应用

退出后清理内存的

在应用退出后,ActivityManagerService 不仅把主进程给杀死,另外把主进程所属的进

程组一并杀死,这样一来,由于子进程和主进程在同一进程组,子进程在做的事情,也

就停止了。所以在 Android5.0 以后的手机应用在进程被杀死后,要采用其他方案。

这种大部分人都了解,据说这个微信也用过的进程保活方案,移步微信 Android 客户端

后台保活经验分享,这方案实际利用了 Android 前台 service 的漏洞。

原理如下

对于 API level < 18 :调用 startForeground(ID, new Notification()),发送空的

Notification ,图标则不会显示。

对于 API level >= 18:在需要提优先级的 service A 启动一个 InnerService,两个服务

同时 startForeground,且绑定同样的 ID。Stop 掉 InnerService ,这样通知栏图标即

被移除。

public class KeepLiveService extends Service{

public static final int NOTIFICATION_ID=0x11; 

public KeepLiveService() {

}

@Override

public IBinder onBind(Intent intent){

throw new UnsupportedOperationException("Not yet implemented");

 }

 @Override 

public void onCreate() {

 super.onCreate(); //API 18 以下,直 接发 送 Notification 并 将 其 置 为 前 台

if(Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN_MR2){

startForeground(NOTIFICATION_ID,new Notification()); 

} else { //API 18 以上,发送 Notification 并将其置为前台后,启动 InnerService

Notification.Builder builder=new Notification.Builder(this);

builder.setSmallIcon(R.mipmap.ic_launcher);

startForeground(NOTIFICATION_ID, builder.build());

 startService(new Intent(this, InnerService.class));

 }

 }

 public class InnerService extends Service{

 @Override public IBinder onBind(Intent intent) {

 return null;

 } 

@Override public void onCreate() {

 super.onCreate(); //发送与 KeepLiveService中 ID 相同的 Notification,然后将其取消并取消自己的前台显示

 Notification.Builder builder = new Notification.Builder(this);

builder.setSmallIcon(R.mipmap.ic_launcher);startForeground(NOTIFICATION_ID,

builder.build());

new Handler().postDelayed(new Runnable() { 

@Override public void run() { 

stopForeground(true);

 NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

manager.cancel(NOTIFICATION_ID); 

stopSelf();

 }

 },

100);

 }

 }

 }

在没有采取前台服务之前,启动应用,oom_adj 值是 0,按下返回键之后,变成 9(不

同 ROM 可能不一样)

相互唤醒的意思就是,假如你手机里装了支付宝、淘宝、天猫、UC 等阿里系的 app,

那么你打开任意一个阿里系的 app 后,有可能就顺便把其他阿里系的 app 给唤醒了。

这个完全有可能的。此外,开机,网络切换、拍照、拍视频时候,利用系统产生的广播

也能唤醒 app,不过 Android N 已经将这三种广播取消了。

如果应用想保活,要是 QQ,微信愿意救你也行,有多少手机上没有 QQ,微信呢?或

者像友盟,信鸽这种推送 SDK,也存在唤醒 app 的功能。

拉活方法

JobSheduler是作为进程死后复活的一种手段,

native进程方式最大缺点是费电,Native

进程费电的原因是感知主进程是否存活有两种实现方式,在 Native 进程中通过死循环

或定时器,轮训判断主进程是否存活,当主进程不存活时进行拉活。其次 5.0 以上系统

不支持。 但是 JobSheduler 可以替代在 Android5.0 以上 native 进程方式,这种方式即

使用户强制关闭,也能被拉起来,亲测可行。

JobSheduler@TargetApi(Build.VERSION_CODES.LOLLIPOP) 

public class MyJobService extends JobService {

 @Override

 public void onCreate() {

 super.onCreate();

 startJobSheduler();

 }

public void startJobSheduler() { 

try {

 JobInfo.Builder builder = new JobInfo.Builder(1,new ComponentName(getPackageName(), MyJobService.class.getName()));

builder.setPeriodic(5); builder.setPersisted(true); JobScheduler jobScheduler =(JobScheduler)

this.getSystemService(Context.JOB_SCHEDULER_SERVICE);

jobScheduler.schedule(builder.build());

}

catch

(Exception ex)

{ ex.printStackTrace(); } }

 @Override 

public boolean onStartJob(JobParameters jobParameters) {

 return false; 

} @Override public boolean onStopJob(JobParameters jobParameters) { 

return false; 

}

 }

这个是系统自带的,onStartCommand 方法必须具有一个整形的返回值,这个整形的返

回值用来告诉系统在服务启动完毕后,如果被 Kill,系统将如何操作,这种方案虽然可

以,但是在某些情况 or 某些定制 ROM 上可能失效,我认为可以多做一种保保守方案。

1.START_STICKY

如果系统在 onStartCommand 返回后被销毁,系统将会重新创建服务并依次调用

onCreate 和 onStartCommand(注意:根据测试 Android2.3.3 以下版本只会调用

onCreate 根本不会调用 onStartCommand,Android4.0 可以办到),这种相当于服务

又重新启动恢复到之前的状态了)。

2.START_NOT_STICKY

如果系统在 onStartCommand 返回后被销毁,如果返回该值,则在执行完

onStartCommand 方法后如果 Service 被杀掉系统将不会重启该服务

3.START_REDELIVER_INTENT

START_STICKY 的兼容版本,不同的是其不保证服务被杀后一定能重启。

4.相比与粘性服务与系统服务捆绑更厉害一点,这个来自爱哥的研究,这里说的系统服务

很好理解,比如 NotificationListenerService,NotificationListenerService 就是一个监听

通知的服务,只要手机收到了通知,NotificationListenerService 都能监听到,即时用户

把进程杀死,也能重启,所以说要是把这个服务放到我们的进程之中,那么就可以呵呵



所以你的应用要是有消息推送的话,那么可以用这种方式去欺骗用户。

Android进程保活主流方案
以下是几种常见的保活策略:1. 1像素保活利用透明的OnePieceActivity,通过熄屏广播来提升进程优先级。在AndroidManifest.xml中配置Activity和接收器,KeepAliveManager负责管理保活Activity的生命周期。在一些设备上,如一加6T(Android 10),熄屏时可以拉起该Activity,但在切换应用后,保活效果可能受限制。2...

Android 如何进行进程保活
在应用退出后,ActivityManagerService 不仅把主进程给杀死,另外把主进程所属的进 程组一并杀死,这样一来,由于子进程和主进程在同一进程组,子进程在做的事情,也 就停止了。所以在 Android5.0 以后的手机应用在进程被杀死后,要采用其他方案。 这种大部分人都了解,据说这个微信也用过的进程保活方案,移步微信 Android...

Android常见的保活方式
首先,"1像素保活"是通过监听屏幕开闭、网络切换和短信等事件,启动一个仅显示一个透明像素的Activity,保持应用前台服务状态,提高进程优先级,避免被轻易杀死。其次,"前台Service"是一种直接策略,像网易云音乐那样,即使切换到后台,音乐播放器也会使用前台Service运行。但18版本后,用户会收到提示,这时...

Android中的保活机制
(1)START_STICKY:如果Service所在的进程,在执行了onStartCommand方法后,被清理了,那么这个Service会被保留在已开始的状态,但是不保留传入的Intent,随后系统会尝试重新创建此Service。(2)START_NOT_STICKY:如果Service所在的进程,在执行了onStartCommand方法后,被清理了,则系统不会重新启动此Service...

如何让一个应用程序一直在后台运行
1、保活手段 1 业界保活手段:黑色保活,灰色保活,白色保活 2 黑色保活:1 不同的APP进程,用广播相互唤醒,包括利用系统广播进行唤醒 2 常见手段:1 开机,网络切换,拍照,拍视频等利用系统广播唤醒APP 此场景Google已经意识到,在Android N 取消了 拍照,视频,网络切换的广播 2 接入第三方的SDK...

Android中“强制停止”和广播保活的一个小坑
一直以来,使用广播进行Android进程的保活就是一种常规的保活方法,本着用事实说话的原则,我做了一个实验:我在5台不同品牌的手机上重复了相同的实验,结果一致。由此,似乎可以得出结论——广播保活不靠谱。当然如果这个实验就这么结束了,那也太短了,男人可不能短,接着看。后来我看到了这篇文章 论...

应用闪退分析与 uniapp 安卓原生插件开发
针对问题,采用Android实现进程保活方案,开发一个Android原生插件,尝试提升应用的后台优先级。遵循uniapp文档,配置环境、创建module、实现插件功能。通过启动前台服务方案,修改AndroidManifest.json注册服务并添加权限,实现后台保活效果。查看应用后台时的oom_adj值变小,解决了拍照闪退问题。应用后台保活功能...

如何提高推送的到达率
其实也就是我们常说的 进程保活 ,可以创建一个幽灵进程进行保活操作,也可以直接用应用主进程进行保活,用这个进程中建立TCP连接,保证其存活的最大时长。方案主要以下几种:注意: 保证移动端在线确实能有效的提高推送的到达率,但是需要注意频繁的唤醒应用会导致应用耗电量的增加,所以要把握一定的度...

如何提PUSH的达到率?
这个思路也只适用于国产安卓手机,所谓“进程保活”,就是利用不同App进程使用系统广播进行相互唤醒,算是一种“黑科技吧”,举3个场景:场景一:开机、切换网络、拍照、拍视频的时候,可以利用系统产生的广播唤醒App。(不过貌似Android N已经将这几种广播取消了)场景二:通过第三方SDK唤醒相应App进程,...

面试android高级开发工程师具备哪些技能
链接: https:\/\/pan.baidu.com\/s\/1TQKM90iW35Ps11PXektV9A ?pwd=em2q 提取码: em2q 《Android高薪之路:Android程序员面试宝典》取材于各大IT公司面试真题,所给出的试题尽可能地覆盖了Android应用开发的各个方面,而且大多数试题都有解析部分,读者可以通过这部分更深入地理解试题中所包含的技术内容...

相似回答
大家正在搜