服务是实现程序后台运行的解决方案,适合用于执行那些不需要和用户交互且要求长期运行的任务。
服务并不是运行在一个独立的进程当中,而是依赖于创建服务时所在的应用程序进程,当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行
- 定义一个服务
创建一个类,并让它继承 Service,一般会重写 onBind()、onCreate()、onStartCommand()、和 onDestroy() 这几个方法
public class MyService extends Service{
public IBinder onBind(Intent intent){
return null;
}
public void onCreate(){
super.onCreate();
}
public int onStartCommand(Intent intent, int flags, int startId){
return super.onStartCommand(intent, flags, startId);
}
public void onDestroy(){
super.onDestroy();
}
}
然后要在 AndroidManifest.xml 文件中进行注册
<service android:name=".MyService"></service>
这样,就将一个服务完全定义好了
onCreate() 方法是在服务第一次创建的时候调用的
onStartCommand() 方法则在每次启动服务的时候都会调用
- 启动和停止服务
在布局中添加两个按钮用来实现启动服务和停止服务的功能
public class MainActivity extends Activity implements OnClickListener{
private Button startService;
private Button stopService;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
startService = (Button)findViewById(R.id.start_service);
stopService = (Button)findViewById(R.id.stop_service);
startService.setOnClickListener(this);
stopService.setOnClickListener(this);
}
public void onClick(View v){
switch(v.getId()){
case R.id.start_service:
// 启动服务
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
case R.id.stop_service:
// 停止服务
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
default:
break;
}
}
}
- 活动和服务进行通信
主要要利用 Binder
实例:服务里提供一个下载功能,然后在活动中可以决定何时开始下载,以及随时查看下载进度
新建一个 DownloadBinder 类,并继承自 Binder,然后在它内部提供了开始下载和查看进度的方法,接着在 MyService 中创建 DownloadBinder 的实例,然后在 onBind() 方法里返回这个实例
public class MyService extends Service{
// 创建 Binder 的实例
private DownloadBinder mBinder = new DownloadBinder();
/*
* 新建一个类继承 Binder
*/
class DownloadBinder extends Binder {
public void startDownload() {
Log.d("MyService", "startDownload executed");
}
public int getProgress() {
Log.d("MyService", "getProgress executed");
return 0;
}
}
public IBinder onBind(Intent intent){
// 返回 Binder 的实例
return mBinder;
}
public void onCreate(){
super.onCreate();
}
public int onStartCommand(Intent intent, int flags, int startId){
return super.onStartCommand(intent, flags, startId);
}
public void onDestroy(){
super.onDestroy();
}
}
在布局中添加两个按钮用来实现绑定服务和取消绑定服务,修改 MainActivity 中的代码
public class MainActivity extends Activity implements OnClickListener{
private Button startService;
private Button stopService;
private Button bindService;
private Button unbindService;
private MyService.DownloadBinder downloadBinder;
// 创建一个 ServiceConnection 的匿名类
private ServiceConnection connection = new ServiceConnection(){
// 活动与服务解除绑定时被调用
public void onServiceDisconnected(ComponentName name){
}
// 活动与服务绑定成功时被调用
public void onServiceConnected(ComponentName name, IBinder service){
// 向下转型,获取 DownloadBinder 的实例
downloadBinder = (MyService.DownloadBinder)service;
downloadBinder.startDownload();
downloadBinder.getProgress();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
startService = (Button)findViewById(R.id.start_service);
stopService = (Button)findViewById(R.id.stop_service);
startService.setOnClickListener(this);
stopService.setOnClickListener(this);
bindService = (Button)findViewById(R.id.bind_service);
bindService.setOnClickListener(this);
unbindService = (Button)findViewById(R.id.unbind_service);
unbindService.setOnClickListener(this);
}
public void onClick(View v){
switch(v.getId()){
case R.id.start_service:
// 启动服务
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
case R.id.stop_service:
// 停止服务
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
case R.id.bind_service:
// 绑定服务
Intent bindIntent = new Intent(this, MyService.class);
/*
* BIND_AUTO_CREATE 表示在活动和服务进行绑定后自动创建服务
* 这会使用服务中的 onCreate() 方法得到执行
* 但 onStartCommand() 方法不会执行
*/
bindService(bindIntent, connection, BIND_AUTO_CREATE);
break;
case R.id.unbind_service:
// 解绑服务
unbindService(connection);
break;
default:
break;
}
}
}
首先创建了一个 ServiceConnection 的匿名类,在里面重写了 onServiceConnected() 方法和 onServiceDisconnected() 方法,这两个方法分别会在活动与服务成功以及解除绑定的时候被调用。
在 onServiceConnected() 方法中,通过向下转型得到了 DownloadBinder 的实例,可以通过这个实例根据具体的场景调用 DownloadBinder 中的任何方法。
活动和服务的绑定通过调用 bindService() 方法,BIND_AUTO_CREATE 标志表示在活动和服务进行绑定后自动创建服务,这会使得服务中的 onCreate() 方法得到执行,但 onStartCommand() 方法不会执行。
- 服务的生命周期
- 调用 startService() 方法,相应的服务就会启动起来,并回调 onStartCommand() 方法。如果这个服务之前还没有创建过,onCreate() 方法会先于 onStartCommand() 方法执行。服务启动了之后会一直保持运行状态,直到 stopService() 或 stopSelf() 方法被调用。虽然每调用一次 startService() 方法,onStartCommand() 就会执行一次,但实际上每个服务都只会存在一个实例。所以不管调用了多少次 startService() 方法,只需调用一次 stopService() 或 stopSelf(),服务就会停止下来。
- 通过调用 bindService() 方法可以获取一个服务的持久连接,这时会回调服务中的 onBind() 方法。类似地,如果这个服务之前还没有创建过,onCreate() 方法会先于 onBind() 方法执行。之后,调用方可以获取到 onBind() 方法里返回的 IBinder 对象的实例,这样就能自由地和服务进行通信。
- 当调用了 startService() 方法后,又去调用 stopService() 方法,这时服务中的 onDestroy() 方法就会执行,表示服务已经销毁。类似 bindService() 方法和 unbindService() 方法组合。如果一个服务既调用了 startService() 方法,又调用了 bindService() 方法,这种情况要同时调用 stopService() 和 unbindService() 方法,onDestroy() 方法才会执行。