【Android】【应用保活】保证应用在后台继续运行

您所在的位置:网站首页 华为手机设置怎么锁定应用 【Android】【应用保活】保证应用在后台继续运行

【Android】【应用保活】保证应用在后台继续运行

2023-10-01 08:50| 来源: 网络整理| 查看: 265

网上关于Service保活和进程保活的文章有很多,但其实大多作用并不大 这些文章大多是只适合很久以前的旧系统,或者是原生的安卓系统,更多的是以讹传讹,未经实践,实际并不可用

实际Service的运行,不完全是由代码控制的,很大程度上取决于操作系统的进程管理策略,手机系统、手机性能息息相关

这里根据我的经验总结出的一些可行的方案,在中高端机型上,基本都能保证Service在后台运行

锁定后台应用

这个功能允许应用在后台运行,不被清理,可以点击任务键,再点击带锁图标的菜单开启

这个不是安卓系统原生的功能,不同的操作系统有不同的打开方法,一般都要点击任务键

在这里插入图片描述

在系统设置-启动管理里面,允许应用后台运行

这个设置允许应用进程在切换到后台时继续运行,但是每个手机的设置方法都有所不同

这里以华为手机为例,有的手机上叫应用启动管理,有的叫后台运行管理,有的叫电池优化

安卓系统定制版本太多了,大家需要自己动手多研究下,把系统设置里面权限应用电池相关的选项都过一遍就能找到

在这里插入图片描述 允许应用后台获取位置信息

这对于有定位功能的应用来说很重要,即便应用进程存活,系统也可能限制定位来达到省电目的 安卓从10.0开始,增加了一个后台定位权限管理功能(Manifest.permission.ACCESS_BACKGROUND_LOCATION) 需要在Manifest清单中配置此权限,并通过代码动态申请此权限,否则息屏后就会立刻停止定位

在这里插入图片描述 关闭电源优化功能

系统对后台进程和定位进行限制,无非为了两个目的,一个是节省CPU和内存,另一个是续航 随着手机性能越来越好,很多高端手机已经不存在性能问题,但是电量消耗问题仍然是存在的

尤其对于定位,视频,屏幕亮度这些功能,大家如果有留意就会知道,它们会明显地大幅提示电量消耗速度 对于有电源优化设置的手机,大家一定要关闭电源优化 也有一些比较简单的系统,会把后台运行等设置都归到电源优化功能里面来

在这里插入图片描述

将服务设置为前台服务

这个功能将后台服务转为前台服务,从而避免被系统清理,这个功能对服务保活效果显著,同样也能提升整个进程的存活率 但相应地,必须将服务与一个前台通知绑定,服务存活期间通知会一直显示,以便告之用户后台应用在运行

service.startForeground(id, notification);

监听系统广播重新启动

我们可以通过静态注册一个广播接收器,去监听一些比较广播频次比较高系统广播,比如电量更新广播 当系统发出这些广播时,广播接收器就会被唤起,然后我们在Receiver里面重新启动Service即可

不过可惜,从安卓8.0开始,静态广播已经受到了严格限制,这个方法现在已经行不通了 如果所有应用都按这种方法做,系统只要一发广播,就会启动一批应用,非常消耗性能和电量 所以从安卓8.0开始,发送静态广播必须指定包名和接收器的类名,只有特定应用可以收到,而不再是群发 我之所以还把它写出来,是因为它代表了一种通用的解决思路,这个思路在其它操作系统中也许是可行的

多进程守护

即开启两个或更多个进程,彼此之间定时相互启动,除非两个进程同时被杀,否则就可以达到一直存活的目的

不过很遗憾,安卓系统从6.0之后,在杀死进程时,会按照包名,将同一个应用下的所有子进程同时杀死 所以这个方法对于进程复活来说,效果并不理想,但是对于复活Service来说,还是可行的

//定义一个保活服务基类,服务之间定时相互启动 //当服务被启动时,服务所在的进程,自然也随之被唤起 public class KeepAliveService extends Service { public Class[] services() { return new Class[]{SA.class, SB.class}; } @Override public void onCreate() { super.onCreate(); WorkThread.postByLoop(() -> { for (Class service : services()) startService(new Intent(this, service)); Threads.sleep(5000); }); Notification notification = Notifications.buildForegroundNotification("应用正在后台运行"); startForeground(Codes.CODE_BACKGROUND_RUNNING, notification); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Console.info(getClass().getSimpleName(), Applications.currentProcessName(), Applications.currentProcessId(), hashCode()); return Service.START_STICKY; } @Nullable @Override public IBinder onBind(Intent intent) { return null; } } public class SA extends KeepAliveService { @Override public int onStartCommand(Intent intent, int flags, int startId) { Console.info("SA execute its work"); return super.onStartCommand(intent, flags, startId); } } public class SB extends KeepAliveService { @Override public int onStartCommand(Intent intent, int flags, int startId) { Console.info("SB execute its work"); return super.onStartCommand(intent, flags, startId); } } //在主进程启动所有服务 startService(new Intent(this, SA.class)); startService(new Intent(this, SB.class));

通过JobScheduler拉活进程

JobScheduler用于在系统中注册一个定时任务,可以定时启动一个JobService 所以只要我们的服务继承JobService,就可以定时被JobScheduler唤起

当然,和其它的功能一样,安卓系统肯定是不可能允许应用通过JobScheduler来作弊,在后台一直运行的 实际上,JobScheduler最快也得15分钟才能唤醒一次任务,JobService最多只能工作10分钟就会被杀死 JobScheduler设计出来并不是让用户肆意滥用的,而是给那些需要定时工作,但是工作频次小,工作时间短的功能设计的

虽然JobScheduler不能保证进程一直存活,但却可以起到定时拉活进程的目的,我们再配合其它技术一起使用,就可以达到一个比较好的效果 毕竟,服务和进程并不会一启动就会被系统杀死,我们将进程拉活和进程守护功能结合起来,就可以保证进程在大多时间都在工作

//在触发JobScheduler任务时,启动指定Service来拉活进程 public class SJ extends JobService { public Class[] services() { return new Class[]{SA.class, SB.class}; } @Override public boolean onStartJob(JobParameters params) { for (Class service : services()) startService(new Intent(this, service)); return false; } @Override public boolean onStopJob(JobParameters params) { return true; } } //在主进程启动所有服务 startService(new Intent(this, SA.class)); startService(new Intent(this, SB.class)); //启动JobScheduler任务来定时拉活Service进程 startKeepAliveJob(1001, SJ.class); //开启一个用于拉活的JobScheduler任务 public void startKeepAliveJob(int jobId, Class service) { ComponentName componentName = new ComponentName(getPackageName(), service.getName()); JobInfo.Builder builder = new JobInfo.Builder(jobId, componentName); builder.setPeriodic(15 * 60 * 1000); builder.setPersisted(true); JobInfo jobInfo = builder.build(); JobScheduler scheduler = getSystemService(JobScheduler.class); scheduler.schedule(jobInfo); }

设置服务以粘性模式启动

STICKY模式的服务,会在进程意外中断时,自动重新启动

@Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; }

综合各种方法技巧

进程保活并不是一个100%稳定的技术,但是以上的措施都会起到一些作用,有的作用其实非常明显 将它们结合起来,基本可以保证应用在后台常驻,千万不要偷懒,奢望只用一个方法就能达到目的



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3