前言

Binder通信机制对于Android来说是一个十分重要的通信机制,因为基本每个App都会使用Client(Activity)-Server这两个组件,而这两个组件的通信通常情况下都是通过Binder来实现的。
网上关于Binder机制的讲解数不胜数,很多都详细讲到源代码,可是对于我这个基本没学过C++,也不怎么了解Linux的人来说看起来真是痛苦。
本文只是简单讲解Binder机制是什么,为什么使用Binder,以及Android中的使用。
想深入了解Binder机制的请移步:


什么是Binder通信机制?

  1. Binder基于Client-Server通信模式.
  2. Binder是Android系统中的一种IPC进程间通信结构。
  3. 在Android系统的Binder机制中,由系统组件组成,分别是Client、Server、Service Manager和Binder驱动程序,其中Client、Server和Service Manager运行在用户空间,Binder驱动程序运行内核空间。
  4. Binder的整个设计是C/S结构,客户端进程通过获取服务端进程的代理,并通过向这个代理接口方法中读写数据来完成进程间的数据通信。

android things485通讯 android 通信机制_android

为什么Android要选择Binder?

Linux已经拥有的进程间通信IPC手段包括(Internet Process Connection): 管道(Pipe)、信号(Signal)和跟踪(Trace)、插口(Socket)、报文队列(Message)、共享内存(Share Memory)和信号量(Semaphore)。

既然进程间通信有这么多手段,为什么Android还选择Binder机制呢?

  1. 安全,每个进程都会被Android系统分配UID和PID,不像传统的在数据里加入UID,这就让那些恶意进程无法直接和其他进程通信,进程间通信的安全性得到提升。
  2. 高效,像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!");
    }
}

android things485通讯 android 通信机制_Binder_02


Activity向Service发送数据可以通过Intent和Bundle传值实现,而Service将数据传递到activity则需要使用Binder机制。