1
安卓应用开发案例教程
1.6.3.4 3.3.4 Service
3.3.4 Service

在介绍Service之前,先来了解一下Service和Thread线程的区别。其实两者并没有太大的关系,不过有很多人经常把二者混淆。Thread是线程,是程序执行的最小单元,也是分配CPU的基本单位。Service则是Android系统提供的一个允许长时间留驻后台的一个组件,最常见的用法就是进行轮询操作,或者在后台进行一些操作,比如后台下载更新!记得别把这两个概念混淆!

Service是Android中实现程序后台运行的解决方案。它适合去执行那些不需要和用户交互而且要求长期运行的任务。Service是一个生命周期长且运行不依赖任何用户界面的程序。

比如一个正在从播放列表中播放歌曲的媒体播放器,在这个媒体播放器应用中有很多个Activity,让使用者可以选择歌曲并播放歌曲。然后,音乐重放这个功能并没有对应的Activity,因为使用者会认为在导航到其他屏幕时音乐应该还在播放。

在这个例子中,媒体播放器这个Activity会使用Context.startService()方法启动一个Service,从而可以在后台保持音乐播放。同时,系统也将保持这个Service一直执行,直到这个Service运行结束。另外,还可以通过使用Context.bindService()方法连接到一个Service(如果这个Service当前还没有处于启动状态,则将启动它)。当连接到一个Service之后,还可用Service提供的接口与它进行通信。以媒体播放器为例,还可以执行暂停、重播等操作。

下面通过一个例子学习Service的使用方法。首先介绍如何在项目中定义一个服务。打开Eclipse,新建一个名为“ServiceDemo”的项目,然后在这个项目中添加一个MyService类,并让它继承于Service,全部完成后的代码如下:

目前MyService类中只有一个onBind()方法,这个方法是Service中唯一的抽象方法。既然已经定义了一个Service,就应该在Service中处理一些事情,那么处理事情的代码应该写在哪里呢?这时就需要重写Service中的另外一些方法,比如可以重写onCreate()、onStartCommand()和onDestroy()这3个方法,具体如下:

这是Service中最常用到的3个方法。其中onCreate()方法在Service第一次被创建的时候调用,该方法在整个生命周期中只会调用一次;onStartCommand()方法是在每次服务启动的时候调用,早期版本是onStart(intent,startId),当客户端调用startService(Intent)方法时会调用,可多次调用StartService方法,但不会再创建新的Service对象,而是继续复用前面产生的Service对象,但会继续回调onStartCommand()方法,而onDestroy()方法会在服务销毁的时候调用,该方法只会回调一次。一般情况下如果某个操作需要在服务启动的时候就立刻执行,那么就可以把这个操作的逻辑写在onStartCommand()方法里,而onDestroy()方法常常用来回收那些不再使用的资源,销毁Service。

另外需要注意的是,每个Service都需要在“AndroidManifest.xml”文件中进行注册才能生效,这在前面介绍Android四大模块的时候提过。所以,需要对“AndroidManifest.xml” 文件进行修改,代码如下:

到此,就已经定义好一个Service。接下来需要考虑的就是如何启动和停止这个Service。启用和停止Service主要借助Intent来实现,下面在“ServiceDemo”项目中尝试启动和停止MyService。

首先,修改布局文件“activity_main.xml”中的代码,具体如下:

在布局文件中添加两个Button控件,一个用于控制Service的启动,另一个用于控制Service的停止。

接下来修改MainActivity中的代码如下:

在onCreate()方法中分别获取到了“开启服务”按钮和“停止服务按钮”的实例,并分别给它们添加了监听事件。然后在“开启服务”按钮的点击事件里,构建一个Intent对象,并且调用startService()方法来启动MyService。在“停止服务”按钮的点击事件里,同样构建一个Intent对象,并调用stopService()方法来停止MyService。需要强调的一点是,这里Service的启动和停止完全是由Activity来决定的,如果一直不点击“停止服务”按钮,那么这个Service就会一直开启。

程序到这里基本上已经完成,可是如何才能直观地看到Service到底是处于启动状态还是停止状态呢?最简单的办法就是在MyService的几个方法里加入打印信息,调用了哪个方法就打印输出指定的内容,这样就能帮助用户直观地看到当前Service的状态,具体代码如下:

现在运行程序,并进行实际操作,程序的界面如图3-19所示。

单击“开启服务”按钮,查看Logcat里打印的日志,如图3-20所示。

可以看到onCreate()方法和onStartCommand()方法都已经执行,Service已经启动,并且可以在正在运行的Service中看到应用程序的身影,如图3-21所示。

当单击“停止服务”按钮后,查看Logcat中的打印信息,如图3-22所示。

可以看到onDestroy()方法被调用,因此当前Service已经成功地停止下来。

图3-19 “ServiceDemo”项目主界面

图3-20 开启Service的Logcat信息

图3-21 正在运行的Service

图3-22 停止Service的Logcat信息

延伸知识点

可以发现,单击“开启服务”按钮的时候,onCreate()方法和onStartCommand()方法都被调用,那么二者的区别是什么?

其实onCreate()方法是在Service第一次创建的时候调用的,而onStartCommand()方法则在每次启动Service的时候都会调用,上面是第一次点击“开启服务”按钮,这个时候Service还没有被创建,所以两个方法都会执行,之后如果连续点击几次“开启服务”按钮,就会发现onStartCommand()方法被多次调用。