Android 组件Service(一)之startService()、bindService()
1.服务Service简介
服务(service)是Android中实现程序后台运行的程序,非常适合去执行那些不需要和用户交互还要长期运行的任务,其运行不依赖任何用户界面。
服务不是运行在一个独立的进程当中的,而是 依赖于创建服务时所在的应用程序进程。当应用程序的进程被杀掉时,所依赖于该进程的服务也会停止运行。
服务并不会自动开启线程,所有的代码都是默认在主线程当中的。这需要我们在服务内部手动创建子线程,并在这里执行具体的任务,否则可能出现主线程被阻塞住的情况。
2.服务基本用法
Service使用步骤如下:
1. 继承service类
2. AndroidManifast.xml配置清单文件中<application>
节点里对服务进行注册<service name=".ServiceName"/>
服务不能自己运行,需要通过Contex.startService()或Contex.bindService()启动服务
2.1 startService()用法
通过startService()方法启动的服务于调用者没有关系,即使调用者关闭了,服务仍然运行想停止服务要调用Context.stopService()或者stopSelf()方法,此时系统会调用onDestory(),使用此方法启动时,服务首次启动系统先调用服务的onCreate()–>onStartCommand(),如果服务已经启动再次调用只会触发onStartCommand()方法,onStart方法在API 5时被废弃,替代它的是onStartCommand方法。
public class MainActivity extends AppCompatActivity {
private Button btn_startservice;
private Button btn_stopservice;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_startservice = (Button) findViewById(R.id.btn_startserver);
btn_stopservice = (Button) findViewById(R.id.btn_stopservice);
btn_startservice.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//借助Intent来实现启动服务
Intent startIntent = new Intent(MainActivity.this, StartService.class);
startService(startIntent);
}
});
btn_stopservice.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Intent stopIntent = new Intent(MainActivity.this, StartService.class);
//停止服务
stopService(stopIntent);
}
});
}
}
//service类
public class StartService extends Service {
@Override
public void onCreate(){
super.onCreate();
Log.d("startService", "onCreate executed");
}
@Override
public int onStartCommand(Intent intent, int flag, int startId){
Log.d("startService", "onStartCommand executed");
return super.onStartCommand(intent, flag, startId);
}
@Override
public void onDestroy(){
super.onDestroy();
Log.d("startService", "onDestroy executed");
}
@Override
public IBinder onBind(Intent intent){
throw new UnsupportedOperationException("Not yet implemented");
}
}
显示结果:
02-21 09:10:06.086 3712-3712/com.example.servicetest D/startService: onCreate executed
02-21 09:10:06.086 3712-3712/com.example.servicetest D/startService: onStartCommand executed
02-21 09:10:07.933 3712-3712/com.example.servicetest D/startService: onStartCommand executed
02-21 09:10:09.703 3712-3712/com.example.servicetest D/startService: onDestroy executed
应用程序界面中使用startservice按钮 调用onCreate() onStartCommand(),再次按只调用onStartCommand(),按stopservice按钮调用onDestroy()。
2.2 bindService()方式
使用bindService()启动的服务与调用者(Context)绑定,只要调用者关闭服务就终止,使用此方法启动时,服务首次启动系统先调用服务的onCreate()–>onBind(),如果服务已经启动再次调用不会再触发这两个方法,调用者退出(或不存在)时系统会调用服务的onUnbind()–>onDestory(),想主动解除绑定可使用Contex.unbindService(),系统依次调用onUnbind()–>onDestory(),
使用bindService可以实现与正在运行的service进行联系交流。而startService适合自己在后台长期运行,若与之交流频繁会造成性能问题。
//创建一个Binder对象对下载功能进行管理
public class DownBinderService extends Service {
/**
* 1. 添加了一个public内部类继承Binder,并添加两个方法;
* 2. 新建一个IBinder对象——new那个Binder内部类;
* 3. onBind方法返还那个IBinder对象。
*/
private DownloadBinder mBinder = new DownloadBinder();
//继承Binder的DownloadBinder内部类,并写了两个可被操作的方法。
class DownloadBinder extends Binder {
public void startDownload(){
Log.d("DownBinderService", "startdownload");
}
public int getProgress(){
Log.d("DownBinderService","getprogress..");
return 0;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
//MainActivity中的onCreate()里写如下代码服务的绑定与解绑定
btn_bindservice = (Button) findViewById(R.id.btn_bindservice);
btn_unbindservice = (Button) findViewById(R.id.btn_unbindservice);
btn_bindservice.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Intent bindIntent = new Intent(MainActivity.this, DownBinderService.class);
//绑定服务
bindService(bindIntent, connection, BIND_AUTO_CREATE);
}
});
btn_unbindservice.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
//解绑服务
unbindService(connection);
}
});
//MainActivity里写下面服务回调的代码
private DownBinderService.DownloadBinder downloadBinder;
//在Activity中,我们通过ServiceConnection接口来取得建立连接
// 定义服务绑定的回调,传递给bindService()
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downloadBinder = (DownBinderService.DownloadBinder) service;
downloadBinder.startDownload();
downloadBinder.getProgress();
}
//与服务联系中断的时候就调用这个方法
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
bindService()调用方法的步骤:
- 在服务的内部创建一个内部类(如上述的DownloadBinder)提供方法,可以间接调用服务的方法
- 实现服务的onBind()方法,返回的就是这个内部类DownloadBinder 的对象(实际也是IBinder对象)
- 在Activity 绑定服务。
- 在服务成功绑定的回调方法onServiceConnected, 会传递过来一个 IBinder对象
- 强制类型转化为自定义的接口类型(如
downloadBinder = (DownBinderService.DownloadBinder) service;
),调用接口里面的方法。
创建了ServiceConnection匿名类,要重写其中的两个方法,在服务成功绑定和解绑定的时候调用。
绑定是异步进行的,bindService()将立即返回,并不会向客户端返回 IBinder 。为了接收 IBinder ,客户端必须创建一个 ServiceConnection 的实例,并把它传给 bindService()。 ServiceConnection 包含了一个回调方法,系统将会调用该方法来传递客户端所需的那个 IBinder。
注意:
只有activity、服务和content provider才可以绑定到服务上,不能从广播接收器(broadcast receiver)中绑定服务。
3. Service生命周期
Bounded方式下在onUnbind() 还以调用onRebind():当再绑定服务, 这次绑定的服务对象是之前已经创建好的且没有被销毁(被执行onDestroy()),所以这次绑定服务时就会调用onRebind()方法,并且本次不会调用onBind()。