定义
服务就是一个在后台执行长时间操作的应用组件,并且它不会提供用户界面。
服务分为三种:
-
前台服务
前台服务执行一些对用户可见的操作 .例如:音乐播放器。前台服务必须在状态栏显示一个图标。即使用户不操作app了前台服务也能继续运行。 -
后台服务
后台服务执行一些用户感知不到的操作。
笔记:如果APP的targetApi在26及以上的时候,当app不在前台的时候系统会限制后台服务的执行。所以我们应该使用scheduled job替代service。 -
绑定服务
当app的组件通过bindService()方法绑定到一个Service的时候,这个服务就叫绑定服务。绑定服务提供了一个允许组件和服务交互的客户-服务器接口。绑定服务运行的时长和它绑定的组件是一样的。多个组件在同一时间可以绑定同一个服务,但当这些组件都解绑的时候,服务就会被销毁。
注意:服务默认运行在主机进程的主线程上;服务并不会创建自己的线程并且如果用户不特别指定的话服务不会运行在其他进程上。当我们在服务中做耗时操作时必须新建一个线程去完成工作。
基础
为了启动服务,我们必须创建Service的子类。在我们的实现中必须覆盖几个重要的方法:
-
onStartCommand()
系统会在其他组件调用startService方法启动服务后调用这个方法。当这个方法执行的时候,服务就会启动并且会无限期运行在后台。如果调用这个方法启动服务必须在服务的工作做完后调用stopSelf()或stopService()方法结束服务。如果只需要绑定服务则无需覆盖这个方法。
这个方法有三个整型的返回值,这些返回值描述了当系统杀死这个服务后会怎么继续服务:
START_NOT_STICKY
START_STICKY
START_REDELIVER_INTENT -
onBind()
系统会在其他组件通过bindService()绑定到Service的时候调用这个方法。我们必须在这个方法中返回一个客户可以用来与Service交互的IBinder对象。这个方法必须被实现,然而,当我们不想使用绑定的时候,这个方法应该返回null。 -
onCreate()
这个方法只有在Service被初始化的时候执行一次(在onStartCommand()与onBind()之前调用),如果服务已经运行,这个方法不会再被调用。 -
onDestroy()
系统会在服务不再被使用并且将要被销毁时调用这个方法。在这个方法中可以做一些资源清理工作。这是Service接收到的最后一个方法。
注意:为了保证APP是安全的,我们必须使用显式意图去启动Service并且不为Service声明intent-filter,使用隐式意图启动Service是十分不安全的因为我们不确定服务是否一定会回应这个意图,并且用户也不知道哪个服务启动了。从安卓5.0开始,使用隐式意图启动Service会抛出一个异常。
笔记:当我们在manifest为service设置android:exported属性为false的时候就表明这个Service只有本应用的组件可以启动,其他应用的组件即使使用显式意图也启动不了。
Service和IntentService
-
Service
所有Service的基类。当我们继承这个类时,我们应该创建一个新的线程用于执行service要进行的所有工作。 -
IntentService
Service的子类,内部含有一个处理所有请求的工作线程,每次只能接受一个请求。如果我们不需要Service同时处理多个请求的话,最好使用这个类。必须实现onHandleIntent()方法,这个方法用于接受所有请求。
笔记:如果要同时执行多个请求的话使用Service而不能使用IntentService,因为IntentService是按队列方式执行请求的,只要前面一个请求阻塞了,后面的请求就都执行不了了。
结束Service
通过startService()启动的服务必须处理他自己的生命周期。系统只会在系统需要回收内存并且service在onStartCommand方法返回值后还在运行的情况下才会销毁它。
绑定服务不需要结束,当所有绑定在它上面的所有组件都解绑了,这个Service就会被销毁了。
当一个服务先以startService启动再被绑定的话,调用stopService()和stopSelf()并不能关闭服务,必须在所有组件都解绑了之后调用这两个方法才有效。