前言
Binder通信机制对于Android来说是一个十分重要的通信机制,因为基本每个App都会使用Client(Activity)-Server这两个组件,而这两个组件的通信通常情况下都是通过Binder来实现的。
网上关于Binder机制的讲解数不胜数,很多都详细讲到源代码,可是对于我这个基本没学过C++,也不怎么了解Linux的人来说看起来真是痛苦。
本文只是简单讲解Binder机制是什么,为什么使用Binder,以及Android中的使用。
想深入了解Binder机制的请移步:
什么是Binder通信机制?
- Binder基于Client-Server通信模式.
- Binder是Android系统中的一种IPC进程间通信结构。
- 在Android系统的Binder机制中,由系统组件组成,分别是Client、Server、Service Manager和Binder驱动程序,其中Client、Server和Service Manager运行在用户空间,Binder驱动程序运行内核空间。
- Binder的整个设计是C/S结构,客户端进程通过获取服务端进程的代理,并通过向这个代理接口方法中读写数据来完成进程间的数据通信。
为什么Android要选择Binder?
Linux已经拥有的进程间通信IPC手段包括(Internet Process Connection): 管道(Pipe)、信号(Signal)和跟踪(Trace)、插口(Socket)、报文队列(Message)、共享内存(Share Memory)和信号量(Semaphore)。
既然进程间通信有这么多手段,为什么Android还选择Binder机制呢?
- 安全,每个进程都会被Android系统分配UID和PID,不像传统的在数据里加入UID,这就让那些恶意进程无法直接和其他进程通信,进程间通信的安全性得到提升。
- 高效,像Socket之类的IPC每次数据拷贝都需要2次,而Binder只要1次,在手机这种资源紧张的情况下很重要。
IPC | 数据拷贝次数 |
共享内存 | 0 |
Binder | 1 |
Socket/管道/消息队列 | 2 |
怎么使用Binder?
对Binder而言,Binder可以看成Server提供的实现某个特定服务的访问接入点, Client通过这个‘地址’向Server发送请求来使用该服务;对Client而言,Binder可以看成是通向Server的管道入口,要想和某个Server通信首先必须建立这个管道并获得管道入口。
下面是一个简单的activity与Service数据通信的例子,activity通过Service获取当前系统时间。
Client(Activity)
public class MainActivity extends AppCompatActivity {
private MyService.MyBinder binder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.btn_click);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
System.out.println(binder.getCount());
}
});
}
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent();
intent.putExtra("string","客户端请求数据:");
intent.setAction("com.demon.aidlclient.myservice");
intent.setPackage(getPackageName());
bindService(intent, connection, BIND_AUTO_CREATE);
}
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
binder = (MyService.MyBinder) iBinder;
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
@Override
protected void onDestroy() {
super.onDestroy();
Log.i("Main", "--------onDestroy");
unbindService(connection);
}
}
Service
public class MyService extends Service {
private MyBinder binder = new MyBinder();
/**
* 继承Binder实现数据通信
*/
public class MyBinder extends Binder {
public String getCount() {
return "服务端返回当前时间:" + System.currentTimeMillis();
}
}
private String TAG = "BindService";
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "Service is Bind!");
System.out.println(intent.getStringExtra("string"));
return binder;
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Service is Created!");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service is Started!");
return START_STICKY;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "Service is Unbinded!");
return true;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "Service is Destroy!");
}
}
Activity向Service发送数据可以通过Intent和Bundle传值实现,而Service将数据传递到activity则需要使用Binder机制。