[TOC]

文章参考:https://blog.csdn.net/SuperBigLw/article/details/53126676

文章参考:https://www.heqiangfly.com/2015/12/20/android-knowledge-about-service/

一、概述

绑定服务是客户端-服务器接口中的服务器。绑定服务可让组件(例如 Activity)绑定到服务、发送请求、接收响应,甚至执行进程间通信 (IPC)。 绑定服务通常只在为其他应用组件服务时处于活动状态,不会无限期在后台运行。

二、实现原理

应用程序组件(客户端)通过调用bindService()方法能够绑定服务,然后Android系统会调用服务的onBind()回调方法,这个方法会返回一个跟服务端交互的IBinder对象。这个绑定是异步的,bindService()方法立即返回,并且不给客户端返回IBinder对象。要接收IBinder对象,客户端必须穿件一个ServiceConnection类的实例,并且把这个实例传递给bindService()方法。
ServiceCOnnection对象包含了一个系统调用的传递IBinder对象的回调方法。
注意:只有Activity、Service 、和内容提供器(content provider)能够绑定服务。
广播接收器不能绑定服务。

三、生命周期

Bind Service的生命周期:

  • onCreate(): 创建服务
  • onBind(): 绑定服务,服务开始运行
  • onUnbind(): 取消绑定
  • onRebind(): 重新绑定服务的前提条件:服务处于启动状态,且onUnbind方法返回true。
  • onDestroy(): 服务被停止

在程序中调用:context.bindService()会触发执行Service生命周期中的onCreate()、onBind()回调方法,此时服务开始运行;

onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。此后调用者(Context,例如Activity)会和Service绑定在一起;

如果调用Service的调用者Context退出了,那么会依次调用Service生命周期中的onUnbind()、onDestroy()回调方法,会让服务停止;

所以BindService的生命周期为:onCreate –> onBind(只一次,不可多次绑定) –> onUnbind –> onDestory。

四、Service的销毁

如果是直接绑定的那么解绑就会销毁,如果先是StartService启动再绑定的那么需要解绑并且停止才会销毁,也就是说一个Service必须要在既没有和任何Activity关联又处理停止状态的时候才会被销毁。

五、如何使用Binder类来BindService

如果服务是供您的自有应用专用,并且在与客户端相同的进程中运行(常见情况),则应通过扩展Binder 类并从 onBind() 返回它的一个实例来创建接口。客户端收到 Binder 后,可利用它直接访问Binder 实现中乃至 Service 中可用的公共方法。如果服务只是您的自有应用的后台工作线程,则优先采用这种方法。

不以这种方式创建接口的唯一原因是,您的服务不能被其他应用或不同的进程占用。

但是以上这么创建的绑定Service!!!!!!!!
如果将Service变成远程Service的话,绑定会报错:
这是由于在Bind Service按钮的点击事件里面我们会让MainActivity和MyService建立关联,但是目前MyService已经是一个远程Service了,Activity和Service运行在两个不同的进程当中,这时就不能再使用传统的建立关联的方式,程序也就崩溃了。

六、使用方法

1.创建一个服务重写四个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Override
public void onCreate() {
super.onCreate();
}

@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}

@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}

@Override
public void onDestroy() {
super.onDestroy();
}

onBind()方法是绑定时调用
onUnBind()方法是解绑的时候调用

2.在Mainactivity创建一个ServiceConnection类的对象并实现。

1
2
3
4
5
6
7
8
9
10
11
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {

}

@Override
public void onServiceDisconnected(ComponentName componentName) {

}
};

onServiceConnected是绑定成功时调用的方法
onServiceDisconnected是服务异常终止时调用的方法

3.进行绑定

1
2
Intent intent = new Intent(this, MyBoundService.class);
bindService(intent, conn, BIND_AUTO_CREATE);

这个绑定是异步绑定
bindService(Intent,ServiceConnection对象,常量)的参数说明
第一个参数:Intent指示对应的Service对象
第二个参数:实现了 ServiceConnection接口的对象
第三个参数:Flags
在进行服务绑定时,其标志位可以为:

  1. BIND_AUTO_CREATE
  2. BIND_DEBUG_UNBIND
  3. BIND_NOT_FOREGROUND

BIND_AUTO_CREATE表示当收到绑定请求时,如果服务尚未创建,则即刻创建,在系统内存不足,需要先销毁优先级组件来释放内存,且只有驻留该服务的进程成为被销毁对象时,服务才可被销毁;

BIND_DEBUG_UNBIND通常用于调试场景中判断绑定的服务是否正确,但其会引起内存泄漏,因此非调试目的不建议使用;

BIND_NOT_FOREGROUND表示系统将阻止驻留该服务的进程具有前台优先级,仅在后台运行,该标志位在Froyo中引入。

4.解除绑定

1
unbindService(conn);

5.创建一个MyBinder类集成Binder的类

1
2
3
4
5
6
public class MyBinder extends Binder {
public void startDownload() {
Log.e("SuperLw", "startDownload() executed");
// 执行具体的下载任务
}
}

6.在MyBoundService中的onBind方法返回MyBinder对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class MyBoundService extends Service {
private MyBinder mBinder = new MyBinder();
public MyBoundService() {
}

@Override
public void onCreate() {
super.onCreate();
}

@Override
public void onDestroy() {
super.onDestroy();
}

@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}

@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return mBinder;
}
}

7.定义一个MyBinder对象并在onServiceConnected方法中实例化

1
2
3
4
5
6
7
8
9
10
11
12
13
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
myBinder = (MyBinder) iBinder;
myBoundService = true;

}

@Override
public void onServiceDisconnected(ComponentName componentName) {
myBoundService = false;
}
};

8.在你想要进行通信的方法中调用方法就可以进行操作了

1
2
3
4
5
6
public void correspondedClick(View view){
if(myBinder!=null){
myBinder.startDownload();
}

}