当前位置: 首页>职业发展> 正文

【软件干货】Android应用进程如何保活?

2025-09-20134

1.Android应用进程保活方法介绍

在Android应用程序中,为了保证应用的正常运行和稳定性,有时需要对应用进程进行保活。以下是一些实现进程保活的方法:

1、使用前台服务(ForegroundService):将服务调用startForeground()方法,并传入一个通知对象,将该服务置于前台运行状态。这样可以使得该服务的优先级更高,从而减少被系统杀死的概率。

2、使用JobScheduler:使用setPeriodic()方法可以让应用程序周期性地执行任务,从而避免长时间占用CPU资源,setPersisted(true)方法则表示当设备重启后,该任务仍然需要继续执行。

3、使用AlarmManager:使用这个API可以让应用程序在指定的时间间隔内执行任务。例如,可以设置一个闹钟,每隔一段时间唤醒应用程序并执行一些操作。

4、使用守护进程:启动一个后台守护进程,监控应用程序的状态并在应用程序被杀死时重新启动它,使用守护进程需要申请额外的权限。

5、使用双进程保活:启动两个相互绑定的进程,在其中一个进程被杀死时,另一个进程可以重新启动它。

6、使用WorkManger:这是目前比较新的保活机制,用于取代JobScheduler。

需要注意的是,为了避免滥用和浪费系统资源,Android系统不断升级后,已经严格限制应用程序使用过多的后台资源和保活机制。

2.JobScheduler用法简介

JobScheduler是系统服务,由系统负责调度第三方应用注册的JobScheduler,定时完成指定任务。

在应用中创建一个JobService服务,JobService需要APILevel21以上才可以使用,该服务注册时必须声明_JOB_SERVICE权限:

!--JobScheduler拉活--serviceandroid:name="."android:enabled="true"android:exported="true"android:permission="_JOB_SERVICE"/service

通常使用JobScheduler需要以下几个步骤:

1、获取JobScheduler对象:通过Binder机制获取该JobScheduler系统服务;

//创建JobSchedulerJobSchedulerjobScheduler=(JobScheduler)(_SCHEDULER_SERVICE);

2、指定JobScheduler任务信息JobInfo:绑定任务ID,指定任务的运行组件,也就是之前创建并注册的JobService,最后要设置该任务在重启后也要执行;

//第一个参数指定任务ID//第二个参数指定任务在哪个组件中执行//setPersisted方法需要_BOOT_COMPLETED权限//setPersisted方法作用是设备重启后,依然执行JobScheduler定时任务=(10,newComponentName((),())).setPersisted(true);

3、设置时间信息:7.0以下的系统可以设置间隔,7.0以上的版本需要设置延迟执行,否则无法启动;

//7.0以下的版本,可以每隔5000毫秒执行一次任务if(__){(5_000);}else{//7.0以上的版本,设置延迟5秒执行//该时间不能小于方法获取的最小值(5_000);}

4、开启定时任务;

//开启定时任务(());

5、7.0以上的特殊处理,由于在7.0以上的系统中设置了延迟执行,需要在JobService的onStartJob方法中再次开启一次JobScheduler任务执行,也就是重复上述1~4执行,这样就实现了周期性执行的目的;

publicclassKeepAliveJobServiceextsJobService{@OverridepublicbooleanonStartJob(JobParametersparams){("KeepAliveJobService","JobServiceonStartJob开启");if(_INT=_){//如果当前设备大于7.0,延迟5秒,再次执行一次startJob(this);}returnfalse;}}
3.WorkManager用法简介

WorkManager是适合用于持久性工作的推荐解决方案,它可处理三种类型的持久性工作:

1、立即执行:必须立即开始且很快就完成的任务,可以加急。

2、长时间运行:运行时间可能较长(有可能超过10分钟)的任务。

3、可延期执行:延期开始并且可以定期运行的预定任务。

通常使用WorkManager需要以下几个步骤:

1、将依赖项添加到应用的文件中;

2、定义工作:工作使用Worker类定义,doWork()方法在WorkManager提供的后台线程上异步运行。如需为WorkManager创建一些要运行的工作,则需扩展Worker类并替换doWork()方法;

publicclassXxxWorkerextsWorker{publicXxxWorker(@NonNullContextcontext,@NonNullWorkerParametersparams){super(context,params);}@OverridepublicResultdoWork(){//Dotheworkherexxxxx();//Indi();}}

3、创建WorkRequest:定义工作后,必须使用WorkManager服务进行调度该工作才能运行;

WorkRequestxxxWorkRequest=().build();

4.将WorkRequest提交给系统:需要使用enqueue()方法将WorkRequest提交到WorkManager;

(myContext).enqueue(uploadWorkRequest);

在定义工作时要考虑要考虑下面常见的需求:

1、调度一次性工作还是重复性工作;

2、工作约束条件是怎样的,例如要求连接到Wi-Fi网络或正在充电;

3、确保至少延迟一定时间再执行工作;

4、设置重试和退避策略;

5、输入数据如何传递给工作等等。

4.双进程保活

双进程保活的方式就是在运行了一个主进程之外,还运行了一个“本地前台进程”,并绑定“远程前台进程”,“远程前台进程”与“本地前台进程”实现了相同的功能,代码基本一致,这两个进程都是前台进程,都进行了提权,并且互相绑定,当监听到绑定的另外一个进程突然断开连接,则本进程再次开启前台进程提权,并且重新绑定对方进程,以达到拉活对方进程的目的。

双进程保活的实现步骤如下:

1、定义AIDL接口IMyAidlInterface,每个服务中都需要定义继承的Binder类,作为进程间通信的桥梁(这是个默认的AIDL接口),监听进程的连接断开;

//Declareanynon-defaulttypesherewithimportstatementsinterfaceIMyAidlInterface{/***Demonstratessomebasictypesthatyoucanuseasparameters*andreturnvaluesinAIDL.*/voidbasicTypes(intanInt,longaLong,booleanaBoolean,floataFloat,doubleaDouble,StringaString);}

2、实现一个判定服务运行工具:

;;;;;;publicclassServiceUtils{/***判定Service是否在运行*@paramcontext*@return*/publicstaticbooleanisServiceRunning(Contextcontext,StringserviceName){if((serviceName))returnfalse;ActivityManageractivityManager=(ActivityManager)(_SERVICE);//最多获取200个正在运行的=(200);//遍历当前运行的Service信息,如果找到相同名称的服务,说明某进程正在运行for(:infos){if(((),serviceName)){returntrue;}}returnfalse;}}

3、定义一个用于本地与远程连接的类:

classConnectionimplementsServiceConnection{@OverridepublicvoidonServiceConnected(ComponentNamename,IBinderservice){//服务绑定成功时回调}@OverridepublicvoidonServiceDisconnected(ComponentNamename){//再次启动前台进程startService();//绑定另外一个远程进程bindService();}}

4、定义一个本地前台服务类:

;;;;;;;;;;;;;_MIN;/***本地前台服务*/publicclassLocalForegroundServiceextsService{/***远程调用Binder对象*/privateMyBindermyBinder;/***连接对象*/privateConnectionconnection;/***AIDL远程调用接口*其它进程调与该RemoteForegroundService服务进程通信时,可以通过onBind方法获取该myBinder成员*通过调用该成员的basicTypes方法,可以与该进程进行数据传递*/{@OverridepublicvoidbasicTypes(intanInt,longaLong,booleanaBoolean,floataFloat,doubleaDouble,StringaString)throwsRemoteException{//通信内容}}@OverridepublicIBinderonBind(Intentintent){returnmyBinder;}@OverridepublicvoidonCreate(){();//创建Binder对象myBinder=newMyBinder();//启动前台进程startService();}privatevoidstartService(){if(_INT=_){//startForeground();//创建通知通道NotificationChannelchannel=newNotificationChannel("service","service",_NONE);();(_PRIVATE);NotificationManagerservice=(NotificationManager)getSystemService(_SERVICE);//正式创建(channel);=(this,"service");Notificationnotification=(true).setSmallIcon(_launcher).setPriority(PRIORITY_MIN).setCategory(_SERVICE).build();//开启前台进程,API26以上无法关闭通知栏startForeground(10,notification);}elseif(_INT=__BEAN_MR2){startForeground(10,newNotification());//API18~25以上的设备,启动相同id的前台服务,并关闭,可以关闭通知startService(newIntent(this,));}elseif(___BEAN_MR2){//将该服务转为前台服务//需要设置ID和通知//设置ID为0,就不显示已通知了,但是oom_adj值会变成后台进程11//设置ID为1,会在通知栏显示该前台服务//8.0以上该用法报错startForeground(10,newNotification());}}/***绑定另外一个服务*LocalForegroundService与RemoteForegroundService两个服务互相绑定*/privatevoidbindService(){//绑定另外一个服务//LocalForegroundService与RemoteForegroundService两个服务互相绑定//创建连接对象connection=newConnection();//创建本地前台进程组件意图IntentbindIntent=newIntent(this,);//绑定进程操作bindService(bindIntent,connection,BIND_AUTO_CREATE);}@OverridepublicintonStartCommand(Intentintent,intflags,intstartId){//绑定另外一个服务bindService();(intent,flags,startId);}}

5、定义一个远程前台服务类:

;;;;;;;;;;;;;_MIN;/***远程前台服务*/publicclassRemoteForegroundServiceextsService{/***远程调用Binder对象*/privateMyBindermyBinder;/***连接对象*/privateConnectionconnection;/***AIDL远程调用接口*其它进程调与该RemoteForegroundService服务进程通信时,可以通过onBind方法获取该myBinder成员*通过调用该成员的basicTypes方法,可以与该进程进行数据传递*/{@OverridepublicvoidbasicTypes(intanInt,longaLong,booleanaBoolean,floataFloat,doubleaDouble,StringaString)throwsRemoteException{//通信内容}}@OverridepublicIBinderonBind(Intentintent){returnmyBinder;}@OverridepublicvoidonCreate(){();//创建Binder对象myBinder=newMyBinder();//启动前台进程startService();}privatevoidstartService(){if(_INT=_){//startForeground();//创建通知通道NotificationChannelchannel=newNotificationChannel("service","service",_NONE);();(_PRIVATE);NotificationManagerservice=(NotificationManager)getSystemService(_SERVICE);//正式创建(channel);=(this,"service");Notificationnotification=(true).setSmallIcon(_launcher).setPriority(PRIORITY_MIN).setCategory(_SERVICE).build();//开启前台进程,API26以上无法关闭通知栏startForeground(10,notification);}elseif(_INT=__BEAN_MR2){startForeground(10,newNotification());//API18~25以上的设备,启动相同id的前台服务,并关闭,可以关闭通知startService(newIntent(this,));}elseif(___BEAN_MR2){//将该服务转为前台服务//需要设置ID和通知//设置ID为0,就不显示已通知了,但是oom_adj值会变成后台进程11//设置ID为1,会在通知栏显示该前台服务//8.0以上该用法报错startForeground(10,newNotification());}}/***绑定另外一个服务*LocalForegroundService与RemoteForegroundService两个服务互相绑定*/privatevoidbindService(){//绑定另外一个服务//LocalForegroundService与RemoteForegroundService两个服务互相绑定//创建连接对象connection=newConnection();//创建本地前台进程组件意图IntentbindIntent=newIntent(this,);//绑定进程操作bindService(bindIntent,connection,BIND_AUTO_CREATE);}@OverridepublicintonStartCommand(Intentintent,intflags,intstartId){//绑定另外一个服务bindService();(intent,flags,startId);}}

6、启动两个服务:

;;;publicclassMainActivityextsAppCompatActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){(savedInstanceState);setContentView(_main);startService(newIntent(this,));startService(newIntent(this,));}}
5.双进程保活+JobScheduler整合方案

这种方案是在JobService的onStartJob方法中判定“双进程保活”中的双进程是否挂了,如果这两个进程挂了,就重新将挂掉的进程重启。

这里给出一个双进程保活+JobScheduler整合方案中JobScheduler部分的示意代码,而双进程保活部分保持不变。

publicclassKeepAliveJobServiceextsJobService{@OverridepublicbooleanonStartJob(JobParametersparams){("KeepAliveJobService","JobServiceonStartJob开启");if(_INT=_){//如果当前设备大于7.0,延迟5秒,再次执行一次startJob(this);}//判定本地前台进程是否正在运行booleanisLocalServiceRunning=(this,());if(!isLocalServiceRunning){startService(newIntent(this,));}//判定远程前台进程是否正在运行booleanisRemoteServiceRunning=(this,());if(!isRemoteServiceRunning){startService(newIntent(this,));}returnfalse;}@OverridepublicbooleanonStopJob(JobParametersparams){("KeepAliveJobService","JobServiceonStopJob关闭");returnfalse;}publicstaticvoidstartJob(Contextcontext){//创建JobSchedulerJobSchedulerjobScheduler=(JobScheduler)(_SCHEDULER_SERVICE);//第一个参数指定任务ID//第二个参数指定任务在哪个组件中执行//setPersisted方法需要_BOOT_COMPLETED权限//setPersisted方法作用是设备重启后,依然执行JobScheduler定时任务=(10,newComponentName((),())).setPersisted(true);//7.0以下的版本,可以每隔5000毫秒执行一次任务if(__){(5_000);}else{//7.0以上的版本,设置延迟5秒执行//该时间不能小于方法获取的最小值(5_000);}//开启定时任务(());}}
参考文献

1、【Android进程保活】应用进程拉活(双进程守护+JobScheduler保活):

2、【Android进程保活】应用进程拉活(双进程守护保活):

3、【Android进程保活】应用进程拉活(JobScheduler拉活):

4、Android实现进程保活的思路:

5、WorkManager使用入门:

版权所有©Copyright © 2022-2030 职梦启航网

备案号:粤ICP备09063828号

网站地图