第一章 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生命周期

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.

*/

@Override

protected 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 stub

Intent 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;

// 这个是自定义的action

在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 {

@Override

public 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开启服务应用禁止被杀死,Android Service服务如何不被杀死相关推荐

  1. centos7重新加载服务的命令_Centos7 systemctl添加service服务参数说明

    Centos7可以通过systemctl执行服务命令,同时支持自定义service服务文件来进行一系列的标准执行. 常用命令 systemctl daemon-reload systemctl ena ...

  2. win10高危服务_win10系统禁用Update Orchestrator Service服务的操作方法

    电脑对日常生活的重要性小编就不多说了,可是一旦碰到win10系统禁用Update Orchestrator Service服务的设置方法,想必大家都遇到过需要对win10系统禁用Update Orch ...

  3. android中用代码实现禁止页面旋转,Android通过代码禁止屏幕旋转

    最近在做一个组件,需要让Activity保持启动时的方向而不旋转,查询了网上的办法,大都是通过修改Manifest文件实现屏幕方向的设置,但是这样的方式无法实现我要的效果,即保持横屏或竖屏. 最后,通 ...

  4. win7系统如何关闭不需要的服务器,连接设备平台服务可以禁止吗,win7系统哪些服务可以禁止...

    对于XP系统: 1.NetMeeting Remote DesktopSharing: 允许受权的用户通过NetMeeting在网络上互相访问对方.关 2.Universal Plug and Pla ...

  5. mysql57服务无法启动_将mysqld.service服务加入到systemctl

    在开始安装二进制MySQL的时候感觉都还挺好,就是在启动服务的时候比较麻烦,一开始是在Centos6下的感觉也没有什么费劲的;但是在Centos7下面还是有点不太适应,不过还好用用就熟悉了:说明一下, ...

  6. Windows无法连接到System Event Notification Service服务问题解决

    这也许是自从在笔记本上安装了Windows 7以来Kaijia第一次遇到的不明故障.至今Kaijia仍然无法确认造成错误的具体操作,因为在一次开机后系统,系统任务栏的Aero界面突然消失并且提示&qu ...

  7. Win10 Network Setup Service服务启动后自动停止问题的解决方案

    问题描述 网卡属性界面为空白 解决方案 1.打开服务,找到Network Setup Service服务 2.在启动"Network Setup Service"服务的之后的瞬间, ...

  8. User Profile Service服务未登录,无法加载用户配置文件的解决方案

    最近驱动人生用户反映win10开机提示User Profile Service服务未登录,无法加载用户配置文件.造成这个问题的原因通常是用户配置文件.文件夹被删除或用户配置文件损坏及用户已停止或禁用此 ...

  9. Android 保证Service服务不被杀死的几个方法

    第一章 Service介绍 service服务是一个应用程序的四大组件之一,可以再后台执行长时间运行的操作,不提供用户界面.一个应用程序组件可以启动一个服务,它将继续在后台运行,即使用户切到另一个应用 ...

最新文章

  1. 几种和生成网络相似的纠缠网络(接近人脑)
  2. 改变DIV的背景颜色透明度,但其中的文字不受影响?
  3. [ASP.NET] 限制上传文件类型的两种方法(转)
  4. MIX 2008与ASP.NET MVC框架的Road-Map
  5. BZOJ1026: [SCOI2009]windy数(数位dp)
  6. python安装you—get_使用Python下载工具you-get下载媒体文件
  7. java如何调用同目录下的文件_文件目录发生了增删改操作?Java如何实时监控?...
  8. Codeforces Round #572 (Div. 2)B
  9. SAN(存储区域网络),WWN, WWPN,WWNN区别
  10. pdf拆分成多个文件,方法步骤
  11. java软引用_什么是软引用? 有什么作用
  12. 数据禾|甘肃省国家湿地公园功能区划数据
  13. SN74HC165驱动
  14. 我的远程实习笔记day1
  15. 【docker系列】容器自启动与守护进程停止后容器保活
  16. 小米8 twrp recovery_小米手机机型怎么刷入脸谱Magisk模块详细教程
  17. Au 效果器详解:响度计
  18. spring实战学习(四)AOP及其实现方式
  19. 前端项目中如何去除已经不再使用的图片资源
  20. Win98 is gone

热门文章

  1. 接口测试一般怎么测?接口测试流程和步骤与测试点......
  2. cartographer:论文阅读(Real-Time Loop Closure in 2D LIDAR SLAM)
  3. 音乐游戏格式解析之【Cytus】
  4. Golang学习笔记之依赖包管理工具gvt
  5. 基于ARM开发板搭建物联网服务器
  6. 教育学原理笔记-整理
  7. 我今年50岁了,还在干前端
  8. 美女图库,python爬虫
  9. hive-关系运算符-存储压缩-hive调优
  10. Win11应用程序启动提示配置不正确解决方法