一、 Service简介
Service是Android 系统中的四大组件之一,它跟Activity的级别差不多,但不能自己运行只能后台运行,并且可以和其他组件进行交互。service可以在很多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务总是藏在后台的。
二、Service的启动
Service的启动有两种方式:context.startService() 和 context.bindService(),分别对应非绑定服务和绑定服务。
1、非绑定服务
非绑定服务的生命周期如下图:
使用服务首先得自己先创建一个类去继承Service,这里创建一个UnBindService:
public class UnBindService extends Service {
// startService方式启动时不调用
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.d("Tag","创建服务");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 服务启动
Log.d("Tag","服务启动");
// 接收activity传递的数据
String str = intent.getStringExtra("data");
Log.d("Tag",str);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d("Tag", "服务挂了");
}
}
创建好后系统会为我们将onBind方法写好,但是此处非绑定服务不会去调用该方法。代码中的onCreate,onStartCommand都需要我们去重写,onCreate方法是在首次创建服务时调用,只要服务还在运行,当再次启动服务时不会再执行onCreate方法。onStartCommand方法会紧接着onCreate方法执行,在该方法的参数中有个intent,可以传递从activity发送过来的数据。
然后不要忘了在清单文件中注册刚才创建的服务:
<service android:name="com.example.servicetest.UnBindService"></service>
启动非绑定服务需要在activity中利用startService方法,传入一个意图intent,指定启动哪个服务:
Intent intent= new Intent(this, UnBindService.class);
intent.putExtra("data", "activity传递的数据");
startService(intent);
当执行startService方法后,会依次执行onCreate、onStartCommand方法,查看一下log信息:
我们从activity传递的数据在服务类中也接受到了,此时服务已经处于运行状态,虽然什么事也没做。我们可以在系统设置中查看正在运行的服务,我这里以夜神模拟器为例(其他模拟器、手机大家可自行查看,大致的方法都差不多):
非绑定服务启动后,即便启动该服务的activity销毁了服务依旧运行。我们可以调用stopService方法去手动结束服务,同样要传入一个intent对象:
Intent intent= new Intent(this, UnBindService.class);
stopService(intent);
当执行stopService方法后,系统将会调用服务类中onDestroy方法将服务销毁掉。
2、绑定服务
绑定服务的生命周期跟随与之关联的activity,activity销毁时绑定的服务也会随之销毁,生命周期图如下:
与非绑定服务的区别在于没有了onStartCommand方法,多了onBind和onUnbind这两个方法,同样去创建一个类继承Service并在清单文件注册:
public class BindService extends Service {
@Override
public void onCreate() {
super.onCreate();
Log.d("Tag", "创建bind服务");
}
// bindservice启动服务时调用该方法
@Override
public IBinder onBind(Intent intent) {
// intent可传递activity传递的数据
Log.d("Tag", "绑定服务");
return new MyBinder();
}
String result = "数据";
// 自定义一个类继承Binder
public class MyBinder extends Binder {
public String getdata() {
return result;
}
}
@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
Log.d("Tag", "解除绑定服务");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.d("Tag", "服务挂了");
super.onDestroy();
}
}
我们首先去看onBind方法,同样也可以利用参数intent接收activity传递的数据。注意方法的返回值,这里返回的是一个自定义类的对象,MyBinder类继承了Binder,但是onBind方法的返回值类型IBinder,为什么不报错呢?因为Binder类实现了IBinder接口。这个返回的IBinder对象我们会在activity中接收到,那该如何拿到这个对象呢?
我们需要在activity中去创建一个匿名内部类,如下所示:
ServiceConnection conn = new ServiceConnection() {
// 服务异常断开连接时调用
@Override
public void onServiceDisconnected(ComponentName name) {
}
// 成功绑定服务时调用
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// service即为onBind方法返回
MyBinder myBinder = (MyBinder) service;
Log.d("Tag","服务发给activity的数据:" + myBinder.getdata());
}
};
重写其中的两个方法onServiceDisconnected和onServiceConnected,在onServiceConnected方法中的第二个参数正好就是一个IBinder类型,参数service也就是onBinder返回的数据,只需要在该方法中接收,这样一来activity和服务的关系更加紧密,activity可以通过拿到的MyBinder对象去调用服务类中MyBinder类中的方法,达到控制服务的效果。
最后就需要去启动绑定服务了,代码如下:
Intent intent= new Intent(this, BindService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
conn参数即为上面创建的ServiceConnection对象,第三个参数为一个标志, Context.BIND_AUTO_CREATE表示在Activity和Service建立关联后自动创建Service,这会使得MyService中的onCreate()方法得到执行,下面启动服务。
我们也可以手动的解除绑定,调用unbindService方法:
Intent intent= new Intent(this, BindService.class);
unbindService(conn);
解除绑定后会执行onUnbind和onDestroy方法,服务销毁。
注意:
这里所说的服务并不是子线程,它其实也是运行在UI线程中,所以服务要处理耗时操作时要开启子线程。
如有错误之处,望各位指正。
生活不只是敲代码,如果你或你身边的人喜欢摄影或者生活的点点滴滴,可以关注下我亲爱的公众号~