Service
一个Service
是一段长生命周期的,没有用户界面的程序,可以用来开发如监控类程序。
比较好的一个例子就是一个正在从播放列表中播放歌曲的媒体播放器。在一个媒体播放器的应用中,应该会有多个activity
,让使用者可以选择歌曲并播放歌曲。然而,音乐重放这个功能并没有对应的activity
,因为使用者当然会认为在导航到其它屏幕时音乐应该还在播放的。在这个例子中,媒体播放器这个activity
会使用Context.startService()
来启动一个service
,从而可以在后台保持音乐的播放。同时,系统也将保持这个service
一直执行,直到这个service
运行结束。另外,我们还可以通过使用Context.bindService()
方法,连接到一个service
上(如果这个service
还没有运行将启动它)。当连接到一个service
之后,我们还可以service
提供的接口与它进行通讯。拿媒体播放器这个例子来说,我们还可以进行暂停、重播等操作。
注意:Service默认是运行在它所在的宿主进程的主进程中,所以不可以做耗时操作,若要做耗时操作须在Service中创建新线程来做耗时操作。
app崩溃的时候会结束线程,
Service使用步骤如下
继承
service
类AndroidManifast.xml
配置清单文件中<application>
节点里对服务进行配置
<service name=".SMSService"/>
服务不能自己运行,需要通过Contex.startService()
或Contex.bindService()
启动服务
通过startService()
方法启动的服务于调用者没有关系,即使调用者关闭了,服务仍然运行想停止服务要调用Context.stopService()
,此时系统会调用onDestory()
,使用此方法启动时,服务首次启动系统先调用服务的onCreate()
–>onStart()
,如果服务已经启动再次调用只会触发onStart()
方法
使用bindService()
启动的服务与调用者绑定,只要调用者关闭服务就终止,使用此方法启动时,服务首次启动系统先调用服务的onCreate()
–>onBind()
,如果服务已经启动再次调用不会再触发这2个方法,调用者退出时系统会调用服务的onUnbind()
–>onDestory()
,想主动解除绑定可使用Contex.unbindService()
,系统依次调用onUnbind()
–>onDestory()
;
优先级
Service
分为两种工作状态,一种是启动状态
,主要用于执行后台计算;另一种是绑定状态
,主要用于其他组件和 Service
的交互。
启动过程
ActivityThread.java
1 |
|
绑定过程
ActivityThread.java
1 | private void handleBindService(BindServiceData data) { |
生命周期:
StartService
onCreate
:如果多次执行了Context
的startService
,Service
的**onCreate
也只走一遍**,可在其中做些初始化工作。onStartCommand
:如果多次执行了Context
的startService
,onStartCommand
也会多次执行,它很重要,我们可根据传入的Intent
参数来进行不同的操作,比如创建一个线程用于下载数据或播放音乐等。onBind
:是抽象方法,所以通过startService
时,重写onBind
只需返回null
即可。onBind
主要是给bindService
调用Service时才使用到的onDestroy
:Service
销毁时回调函数
值 | 说明 |
---|---|
START_NOT_STICKY |
如果系统在 onStartCommand() 返回后终止服务,则除非有挂起 Intent 要传递,否则系统不会重建服务。这是最安全的选项,可以避免在不必要时以及应用能够轻松重启所有未完成的作业时运行服务 |
START_STICKY |
如果系统在 onStartCommand() 返回后终止服务,则会重建服务并调用 onStartCommand() ,但不会重新传递最后一个 Intent 。相反,除非有挂起 Intent 要启动服务(在这种情况下,将传递这些 Intent ),否则系统会通过空 Intent 调用 onStartCommand() 。这适用于不执行命令、但无限期运行并等待作业的媒体播放器(或类似服务) |
START_REDELIVER_INTENT |
如果系统在 onStartCommand() 返回后终止服务,则会重建服务,并通过传递给服务的最后一个 Intent 调用 onStartCommand() 。任何挂起 Intent 均依次传递。这适用于主动执行应该立即恢复的作业(例如下载文件)的服务 |
补充:安卓有IntentService
(对Service
进一步的封装)
IntentService
自带一个工作线程,若要在Service
中做些阻塞UI(主)线程工作时,可以用它。- 在
IntentService
的onHandleIntent
中处理实际工作,onHandleIntent
是运行在IntentService
的工作线程中,非主线程中。 - 多次启动
IntentService
,会产生多个job
,IntentService
只能按先后顺序一个个处理(不能并行处理)
StartSerice大概过程
BindService
启用前台服务:
1 | <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> |
1 | Notification notification = new Notification(icon, text, System.currentTimeMillis()); |
关于service启动方式的总结
Service
中需要创建一个实现IBinder
的内部类(这个内部类不一定在Service
中实现,但必须在Service
中创建它)在
onBind()
方法中需返回一个IBinder
实例,不然onServiceConnected
方法不会调用ServiceConnection
的回调方法onServiceDisconnected()
在连接正常关闭的情况下不会被调用的,该方法只在Service
被破坏了或者被杀死的时候调用。例如,系统资源不足,要关闭一些Services
,刚好连接绑定的Service
是被关闭这之一,这个时候onServiceDisconnected()
就会被调用