Android中的服务与windows中的服务非常类似——没有用户操作界面、长时间在后台运行而不易被用户所知。

应用程序可以开启某些服务在后台运行,即使用户切换到其他应用程序也不会被停止。同时,应用程序可以bind一个服务与之交互,甚至可以执行IPC,例如:网络处理、音乐播放、文件输入输出或者是与内容提供者交互,都可以放在后台执行。

服务的两个运行方式

应用的组件(如Activity)可以通过下面两个方式运行服务:

  1. startService():开启服务(started)。
    即使应用被关闭,服务也不会被停止。这种开启方式,没有返回值,不能和应用交互,如下载和上传文件到网络,注意的是:服务应该在业务执行完毕后自我停止。
  2. bindService():绑定服务(bound)。
    服务被绑定后可以与应用交互数据。当应用被关闭后,服务应立即被解绑(unbind)。一个服务可以被多个应用绑定,当这些应用都解绑了服务,服务将被销毁(destoryed)。

Tips:服务可以同时被这两个方式开启。但要注意的是:如果被绑定,则服务只能在解绑后才能被停止。
一般两者混用的调用顺序为:startService()->bindService()->unbindService()->stopService()。

Service的生命周期

  1. onStartCommand():当其他组件startService()来启动服务时,系统调用这个方法。一经执行,服务开始运行在后台。当服务业务执行完毕后应调用stopSelf()自我停止或者其他组件来调用stopService()停止服务。如果这个服务只是提供内容绑定,则不应该去实现这个方法。
  2. onBind():服务通过bindService()方式启动,系统调用此方法。应该提供一个接口给应用,使之能回调服务中的方法(接口其实就服务的代理),方法应返回一个实现了该接口的IBinder对象。如果不想让应用绑定则应该返回null。
  3. onCreate():系统仅在服务第一次被创建时调用。之前会执行上面两个方法
  4. onUnbind():在被解绑时调用。如果服务可以被重新绑定(onRebind()),应返回true。
  5. onRebind():在被解绑(onUnbind()返回true)后又被重新bindService()启动,则会调用此方法。
  6. onDestory():系统会在服务许久不使用或在销毁时调用。可以实现此方法,在服务销毁前清除使用过的资源。

Tips:

  1. 服务的生命周期方法不需要像Activity的生命周期方法那样,在实现方法体中需要显式调用其父类的方法来维护生命周期。
  2. 多次startService()开启服务不会多次调用onCreate()但会多次调用onStart()
  3. 服务在所有绑定组件unbindService()解绑时会被系统销毁,需要自我停止。 Service的生命周期

创建和使用服务

第一步:继承或间接继承Service类

按业务需要去实现一些生命周期方法。

ExampleService.java
1
2
3
4
5
public class ExampleService extends Service {
//onCreate()
//onStart()
//...
}

第二步:在清单文件中的<application>节点里对服务进行配置:

1
2
3
4
5
6
7
<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>

第三步:Activity等组件中开启服务

在onCreate()方法中:
startService(new Intent(this,ExampleService.class))
或者是 bindService(new Intent(this,ExampleService.class),this.conn, BIND_AUTO_CREATE);

注意的是绑定服务需要定义服务的连接器serviceConnection:

1
2
3
4
5
6
7
8
9
10
11
ServiceConnection conn= new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//service.doSomething();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
// do something
}
};

该连接器要调用unbindService(conn)方法进行解绑服务,否则Activity被销毁时会报内存溢出异常。
解绑服务一般都写在Activity的onDestroy()方法中:

1
2
3
4
5
try{
unbindService(conn);
}catch(Exception ignore){
//忽略可能的多次解绑异常
}

调用其他应用的服务

利用AIDL可以实现应用程序进程间的通信,使之可以传递服务的对象,进而实现与其他应用的服务交互。
*详见AIDL