Android 保证Service服务不被杀死的几个方法
第一章 Service介绍
service服务是一个应用程序的四大组件之一,可以再后台执行长时间运行的操作,不提供用户界面。一个应用程序组件可以启动一个服务,它将继续在后台运行,即使用户切到另一个应用程序。此外,一个组件可以绑定到一个服务与它交互,甚至执行进程间的通信(IPC)。
1.1 基础介绍
Service中比较重要的方法有以下几个:
onStartCommand()
当其他组件,如Activity请求服务启动的时候,系统会调用这个方法。一旦这个方法执行,服务就开始执行。如果实现这个方法,当服务完成任务后,需要你调用stopSelf()
或者stopService()
来停止服务。如果只想提供绑定,不需要自己实现这个方法。onBind()
当有其他组件想通过bindService()
方法绑定这个服务时系统就会调用此方法。在实现的方法里面,必须添加一个供客户端使用的接口通过返回IBinder
来与服务通信,这个方法必须实现。当然想禁止绑定的话,返回null
即可。onCreate()
服务第一次建立的时候会调用这个方法,执行一次性设置程序,在上面2个方法执行前调用。如果服务已存在,则不执行该方法。onDestory()
服务不再使用则调用该方法。服务应该事先这个方法来清理诸如线程,注册的监听器等资源。这是最后调用的方法。
Android系统只会在内存占用很高,必须回复系统资源供当前运行程序的情况下强制停掉一个运行中的服务。如果服务绑定在当前的运行程序中,就几乎不会被kill,如果服务声明了在前台运行(其实在后台,只是给系统一个错误的信息来提高优先级),就几乎不会被kill。另外,如果一个服务正在运行,且运行了很久,系统就会根据运行时间把其排在后台任务列表的后面,则这个服务很容易被杀掉。根据onStartCommand()
的返回值设置,服务被杀掉后仍然可以再资源充足的条件下立即重启。
1.2启动服务的两种方式:
- started启动:
started
形式的服务是指当一个应用组件(比如activity
)通过startService()
方法开启服务。一旦开启,该服务就可以永久的在后台运行,哪怕开启它的组件被销毁掉。通常开启的服务执行一个单独的操作并且不向调用者返回一个结果。比如,从网络下载文件,当文件下载完成,服务就应该自己停止。
关闭服务则需要服务自己调用方法stopSelf()
或者由启动服务的地方调用stopService(Intent)
方法来关闭。 - Bound绑定:
bound
形式的服务是指一个应用组件通过调用bindService()
方法与服务绑定。一个绑定的服务提供一个接口,允许组件与服务交互,发送请求、获得结果、甚至进行进程间通信。一个绑定的服务只和与其绑定的组件同时运行。多个组件可以同时绑定到一个服务,当全部解除绑定后,服务就会被销毁。
虽然分为两类,但是一个服务可以同时使用这两种方式-使用started
永久运行,同时允许绑定。只要在服务中实现两个回调方法:onStartCommand()
允许组件开启服务,onBind()
允许绑定。
不论引用程序是怎么起服务的,任何应用程序都可以用这个服务。同样的,任何组件可以使用一个Activity
通过传递Intent
开启服务。你也可以在配置文件设置服务为私有来防止其他应用访问该服务。
注意:一个服务在进程中的主线程运行,服务不会自己创建线程和进程(除非特别指定或者开启一个线程)。这意味着,如果服务需要做一些频繁占用CPU的工作或者会发生阻塞的操作,需要在服务另外开启线程。
1.3 Service生命周期
- 启动服务:
startService()->onCreate()->onStartCommand()->running->stopService()/stopSelf()->onDestroy()->stopped
,其中,服务未运行时会调用一次onCreate()
,运行时不会调用。 - 绑定服务:
bindService()->onCreate()->onBind()->running->onUnbind()->onDestory()->stopped
。
在上面两个过程中,只有onStart
第二章 实现Service
实现服务有两种方式,继承service
或者IntentService
。后者是前者的子类。前者包含上一章节中Service的几个重要的方法,用于普通的服务。后者可以自己开一个工作线程,串行的处理多个请求。
2.1 继承Service
继承Service
就可以实现对请求多线程的处理,前面介绍了Service
的生命周期,可以按照生命周期实现方法,就不放示例了。
2.2 继承IntentService
大多数服务不需要同时处理多个请求,继承IntentService
是最好的选择。
IntentService处理流程:
- 创建按默认的一个
worker
线程处理传递给onStartCommand()
所有的intent
,在非UI线程中区工作。 - 创建一个工作队列依次传递一个
intent
到你实现的onHandleIntent()
方法,避免了多线程。 - 在所有启动请求被处理后自动关闭服务,不需要调用
stopSelf()
- 默认提供
onBind()
的实现,并返回null
- 默认提供
onStartCommand()
的实现,实现发送intent
到工作队列再到你的onHandleIntent()
方法实现。
这些都加入到IntentService
中了,你需要做的就是实现构造方法和onHandleIntent(),如下:
public class HelloIntentService extends IntentService {/*** A constructor is required, and must call the super IntentService(String)* constructor with a name for the worker thread.*/public HelloIntentService() {super("HelloIntentService");}/*** The IntentService calls this method from the default worker thread with* the intent that started the service. When this method returns, IntentService* stops the service, as appropriate.*/@Overrideprotected void onHandleIntent(Intent intent) {// Normally we would do some work here, like download a file.// For our sample, we just sleep for 5 seconds.long endTime = System.currentTimeMillis() + 5*1000;while (System.currentTimeMillis() < endTime) {synchronized (this) {try {wait(endTime - System.currentTimeMillis());} catch (Exception e) {}}}}
}
第三章 如何保证服务不被杀死
在有些特定的情况下,服务需要保持开启不能被杀死。主要有以下几种方法保持Service不被杀死。
3.1 onStartCommand
方法中,返回START_STICKY
在StartCommand()
几个常量:
START_STICKY
系统重新创建服务并且调用onStartCommand()
方法,但并不会传递最后一次传递的intent
,只是传递一个空的intent
。除非存在将要传递来的intent
,那么就会传递这些intent
。这个适合播放器一类的服务,不需要执行命令,只需要独自运行,等待任务。START_NOT_STICKY
系统不重新创建服务,除非有将要传递来的intent
。这是最安全的选项,可以避免在不必要的时候运行服务。START_REDELIVER_INTENT
系统重新创建服务并且调用onStartCommand()
方法,传递最后一次传递的intent
。其余存在的需要传递的intent
会按顺序传递进来。这适合像下载一样的服务,立即恢复,积极执行。@Override public int onStartCommand(Intent intent, int flags, int startId) { flags = START_STICKY; return super.onStartCommand(intent, flags, startId); }
手动返回START_STICKY,亲测当service因内存不足被kill,当内存又有的时候,service又被重新创建,比较不错,但是不能保证任何情况下都被重建,比如进程被干掉了….
3.2 提升Service优先级
前台服务是被认为用于已知的正在运行的服务,当系统需要释放内存时不会优先杀掉该进程。前台进程必须发一个notification
在状态栏中显示,知道进程被杀死。因为前台服务一直消耗一部分资源,但不像一般服务那样会在需要的时候被杀掉,所以为了节约资源,保护电池寿命,一定要在建前台服务的时候发送notification
,提示用户。当然系统提供的方法就必须有notification
参数的,所以不要想着怎么把notification
隐藏掉。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {// TODO Auto-generated method stubIntent notificationIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);Notification noti = new Notification.Builder(this).setContentTitle("Title").setContentText("Message").setSmallIcon(R.drawable.ic_launcher).setContentIntent(pendingIntent).build();startForeground(123456,noti);return Service.START_STICKY;
}
startForeground()
方法就是将服务设置为前台服务,参数123456就是这个通知的唯一的id,只要不为0即可。
3.3 在onDestory()中发送广播开启自己
service+broadcast方式,就是当service调用到ondestory()
的时候,发送一个自定义的广播,当收到广播的时候,重新启动service;
<receiver android:name="com.example.demo.MyReceiver"><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED"/><action android:name="android.intent.action.USER_PRESENT"/><action android:name=com.example.demo.destroy"/>// 这个是自定义的action</intent-filter>
</receiver>
在service中的ondestroy()
时候:
@Override
public void onDestroy(){stopForeground(true);Intent intent = new Intent("com.example.demo.destroy");sendBroadcast(intent);super.onDestroy();
}
在MyReceiver中
public class MyReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if(intent.getAction().equals("com.example.demo.destroy")){Intent sevice = new Intent(this, MyService.class); this.startService(sevice); }}
}
当然,从理论上来讲这个方案是可行的,实验一下结果也是可行的。但是有些情况下,发送的广播在消息队列中排的靠后,就有可能服务还没有接收到广播就销毁了(只是猜想)。所以为了能让这个机制完美运行,可以开启两个服务,相互监听,相互启动。服务A监听B的广播来启动B,服务B监听A的广播来启动A。经过实验,这个方案是可行的。
完!!!
Android 保证Service服务不被杀死的几个方法相关推荐
- 开机时User服务器未能登录,Win10开机提示user profile service服务登录失败的原因及解决方法...
最近一位Win10用户反馈,电脑每次开机都会提示"user profile service服务未能登录.无法加载用户配置文件.",这是怎么回事呢?遇到这种提示,说明user pro ...
- Android Service服务不被杀死(保活)
1.设置->应用->运行中->停止->杀死service 这样可以在service的onDestroy()方法中重启service public void onDestroy( ...
- android的service组件不被杀死
文章转载自:http://blog.csdn.net/mad1989/article/details/22492519 序言 最近项目要实现这样一个效果:运行后,要有一个service始终保持在后台运 ...
- Angular中怎样创建service服务来实现组件之间调用公共方法
场景 Angular介绍.安装Angular Cli.创建Angular项目入门教程: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/detail ...
- android job service,服务保活那些事(Job Service ,JobScheduler)
Android5.0以上保活 Android5.0之后,很多都是可以被APP杀死,尤其是某机型做服务保活更难.Android5.0之后Android提供了JobService和JobScheduler ...
- android 获取Service(服务)的运行状态
在开发的时候,经常会用到服务,有时候就会用到判断服务的运行状态,下面就创建一个工具类来判断服务是在还在运行. package cn.edu.cqu.mobilesafe.utils;import ja ...
- android中service名词解释,Android中Service(服务)详解
A service is "bound" when an application component binds to it by calling 通过startService() ...
- 如何让android的service一直在后台运行
1. 把service和activity分开,让service开机启动.设置一个broadcast receiver接受开机信号, 使用RECEIVE_BOOT_COMPLETED的permissio ...
- (七十)Android O Service启动流程梳理——bindService
前言:最近在处理anr问题的时候迫切需要搞清楚service的启动流程,抽时间梳理一下. 1.service启动简述 service启动分三种,比较简单的就是startService,Android ...
最新文章
- (转)面试必备技能:JDK动态代理给Spring事务埋下的坑!
- git tag学习记录(二)
- 宁波大红鹰学院计算机科学与技术,2019宁波大红鹰学院专业排名
- HighLight selected features
- 【Kotlin】扩展接收者 与 分发接收者 ( 类内部扩展用法 | 注意事项 | open 修饰扩展 )
- 前端也要会的数据结构 (不定期更新篇)
- 日志级别 debug info warn eirror fatal
- Simulink之单管非隔离直流斩波器
- 学会提问,你就成功了一大半!
- 不要让开源成为贸易战的牺牲品!
- caffe MNISTAutoencoder
- cmd中文乱码解决方案
- 机房建设整体设计方案
- 5G云游戏革命风云已起,各方势力谁执牛耳
- JS获取下个月的第一天和最后一天
- AppCan MVVM框架简单介绍
- 在浏览器输入URL,按下回车之后的流程
- torch.optim.lr_scheduler源码和cosine学习率策略学习
- 安装 Adblock plus 插件彻底屏蔽Chrome 浏览器上的广告 以及Adblock plus 的使用教程(亲测有效)
- 虹科方案 | 制药环境中冰箱温度记录的最佳实践——全集成温度监测系统