Service是能够在后台长期运行并且不提供用户界面的应用程序组件。
Service可以分为以下两种类型:
- Started(启动):当Activity通过startService()方法启动服务时,服务处于started状态。一旦启动,就算组件被销毁也不会停止。只有自身调用stopSelf()或者其他组件调用stopService()才停止
- Bound(绑定):当Activity通过bindService()方法启动服务时,服务处于bound状态。一个Service可以被多个服务绑定,当它们都解绑时,服务被销毁
Service类中的重要方法
- onStartCommand():当组件调用startService()时,系统调用该方法。如果开发人员实现该方法,需要调用stopSelf()或stopService()来停止服务
- onBind():当组件调用bindService()时,系统调用该方法。在该方法的实现中,开发人员必须返回IBinder提供客户端与服务通信的接口,该方法必须实现
- onCreate():服务第一次创建时调用。在onStartCommand()或onBind()之前
- onDestory():当服务不再使用时销毁
一、Started Service
1.继承IntentService类
IntentService可以实现如下任务:
- 创建区别于主线程的线程来执行发送到onStartCommand()方法的全部Intent
- 创建工作队列,每次传递一个Intent到onHandleIntent()
- 所有请求处理完毕后停止服务,不必调用stopSelf()
- 提供onBind()方法默认实现,返回null
- 提供onStartCommand()默认实现,它先发送Intent到工作队列,然后到onHandleIntent()方法实现
public class HelloIntentService extends IntentService {
public HelloIntentService() {
super("HelloIntentService");
// TODO Auto-generated constructor stub
}
@Override
protected void onHandleIntent(Intent arg0) {
// TODO Auto-generated method stub
// do something
}
}
以上就是实现IntentService类所需要的全部操作:
无参构造方法和onHandleIntent()方法
如果一定要重写其他回调方法,必须返回默认实现。也就是自动生成的return语句不能改
2.继承Service类
使用IntentService将简化启动服务的实现,但如果要处理多线程,则可以继承Service来处理各个Intent
对于每次启动的请求,它使用工作线程来执行任务,并且每次处理一个请求
public class HelloService extends Service {
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
return START_STICKY;
}
}
onStartCommand()必须返回一个整数。该值用来描述系统停止服务以后如何继续服务。返回值必须是下列值之一:
- START_NO_STICKY:停止服务,不再创建服务
- START_STICKY:停止服务,重新创建服务并调用onStartCommand(),但是不重新发送最后的Intent。使用空Intent调用onStartCommand()
- START_REDELIVER_INTENT:停止服务,重新创建服务并使用最后的Intent调用onStartCommand()
二、Bound Service
绑定服务是允许其他应用进程绑定并且与之交互的Service类实现类。为了提供绑定,开发人员必须实现onBind()回调方法。该方法返回IBinder对象,它定义了客户端与服务的交互接口
在实现绑定服务时,最重要的是定义onBind()回调方法返回的接口
(1)继承Binder类:继承Binder类创建接口,从onBind()返回一个实例。仅用于私有应用程序
(2)使用Messenger:它是执行IPC最简单的方式
(3)使用AIDL:不推荐。会导致更加复杂的实现
1.继承Binder类
如果服务仅用于本地应用程序并且不必跨进程工作,那么可以实现自己的Binder类来为客户端提供访问的方式
实现步骤如下
- (1)在服务中创建Binder类实例来完成下列操作之一
- 包含客户端能调用的公共方法
- 返回当前Service实例,其中包含客户端能调用的方法
- 返回服务管理的其他类的实例
- (2)从onBind()回调方法中返回Binder实例
- (3)在客户端,从onServiceConnected()接受Binder实例,并且使用提供的方法调用绑定服务
下面举个例子来说明:
CurrentTimeService.java
package com.example.bindertime;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.text.format.Time;
public class CurrentTimeService extends Service {
public class LocalBinder extends Binder {
CurrentTimeService getService(){ //返回当前Service实例
return CurrentTimeService.this;
}
}
private final IBinder binder = new LocalBinder();
@Override
public IBinder onBind(Intent intent) { //返回binder实例,自动生成的
// TODO Auto-generated method stub
return binder;
}
public String getCurrentTime(){
Time time = new Time();
time.setToNow();
String currentTime = time.format("%Y-%m-%d %H:%M:%S");
return currentTime;
}
}
CurrentTimeActivity.java
调用bindService()方法,传递ServiceConnection实现
package com.example.bindertime;
import com.example.bindertime.CurrentTimeService.LocalBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class CurrentTimeActivity extends Activity {
CurrentTimeService cts;
boolean bound;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Button button = (Button)findViewById(R.id.current);
button.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(CurrentTimeActivity.this, CurrentTimeService.class);
bindService(intent, sc, BIND_AUTO_CREATE); //调用bindService()方法,传递ServiceConnection实现
if(bound){
Toast.makeText(CurrentTimeActivity.this, cts.getCurrentTime(),
Toast.LENGTH_SHORT).show();
}
}
});
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
if(bound){
bound = false;
unbindService(sc);
}
}
//实现ServiceConnection,这需要重写onServiceConnected()和onServiceDisconnected()两个回调函数
private ServiceConnection sc = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) { //接受Binder实例
// TODO Auto-generated method stub
LocalBinder binder = (LocalBinder)service;
cts = binder.getService();
bound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
bound = false;
}
};
}
2.使用Messenger类
如果需要和远程进程通信,可以使用Messenger来为服务提供接口。
使用Messenger要注意:
- 实现Handler的服务因为每次从客户端调用而收到回调
- Handler用于创建Messenger对象
- Messenger创建IBinder,服务从onBind()方法返回到客户端
- 客户端使用IBinder来实例化Messenger,然后使用它来发送Message对象到服务
- 服务在Handler的handleMessage()方法接受message
CurrentTimeService.java
package com.example.messengertime;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.text.format.Time;
import android.widget.Toast;
public class CurrentTimeService extends Service {
public class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) { //服务在Handler的handleMessage()方法接受message
// TODO Auto-generated method stub
if(msg.what == CURRENT_TIME){
Time time = new Time();
time.setToNow();
String currentTime = time.format("%Y-%m-%d %H:%M:%S");
Toast.makeText(CurrentTimeService.this, currentTime, Toast.LENGTH_SHORT).show();
}else{
super.handleMessage(msg);
}
}
}
public static final int CURRENT_TIME = 0;
@Override //Messenger创建IBinder,服务从onBind()方法返回到客户端
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Messenger messenger = new Messenger(new IncomingHandler());//Handler用于创建Messenger对象
return messenger.getBinder();
}
}
CurrentTimeActivity.java
package com.example.messengertime;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.view.View;
import android.widget.Button;
public class CurrentTimeActivity extends Activity {
Messenger messenger;
boolean bound;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Button button = (Button)findViewById(R.id.current);
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(CurrentTimeActivity.this, CurrentTimeService.class);
bindService(intent, connection, BIND_AUTO_CREATE);
if(bound){
Message message = Message.obtain(null, CurrentTimeService.CURRENT_TIME, 0, 0);
try {
messenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
if(bound){
bound = false;
unbindService(connection);
}
}
private ServiceConnection connection = new ServiceConnection(){
@Override //客户端使用IBinder来实例化Messenger,然后使用它来发送Message对象到服务
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
messenger = new Messenger(service);
bound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
messenger = null;
bound = false;
}
};
}
3.绑定到服务
如果需要从客户端绑定服务,需要完成如下操作:
- 实现ServiceConnection,这需要重写onServiceConnected()和onServiceDisconnected()两个回调函数
- 调用bindService()方法,传递ServiceConnection实现
- 当系统调用ServiceConnection时,可以使用接口定义的方法回调服务
- 调用unbindService()方法解除绑定
三、Service生命周期
可参考这篇文章:service生命周期