Android Binder

            Binder 是 Android 中的 一个 类, 它 继承 了 IBinder 接口。 从 IPC 角度 来说, Binder 是 Android 中的 一种 跨进 程 通信 方式, Binder 还可以 理解 为 一种 虚拟 的 物理 设备, 它的 设备 驱动 是/ dev/ binder, 该 通信 方式 在 Linux 中 没有; 从 Android Framework 角度 来说, Binder 是 ServiceManager 连接 各种 Manager( ActivityManager、 WindowManager, 等等) 和 相应 ManagerService 的 桥梁; 从 Android 应用 层 来说, Binder 是 客户 端 和 服务 端 进行 通信 的 媒介, 当 bindService 的 时候, 服务 端 会 返回 一个 包含 了 服务 端 业务 调用 的 Binder 对象, 通过 这个 Binder 对象, 客户 端 就可以 获取 服务 端 提供 的 服务 或者 数据, 这里 的 服务 包括 普通 服务 和 基于 AIDL 的 服务。(任玉刚. Android开发艺术探索 . 电子工业出版社)

            看过上面大佬对Binder的总结,想必每个人还有自己的看法,我也说说自己的看法。鉴于本人目前经验的原因,对Binder更多的是在应用层的理解。实际应用中Binder多是在Service中,主要是AIDL跟Messenger,看过Messenger源码或者是Messenger原理的同学应该知道,Messenger底层其实也是AIDL,下面我们就从AIDL入手分析下Binder。

            AIDL,Android Interface Definition Language,安卓接口定义语言。这里还涉及到IPC的几种方式,留在后面来说。下面我们就直接上代码看下。先看下整体的结构。


pachage视图


android视图

看完了结构,大概我们需要先有一个类Student,还要有对应的AIDL文件,然后就是处理业务的 Manager AIDL,IStudentManager是根据Manager 生成的,还有就是Service,用来监听。下面就具体看下每个文件的结构。


Student.java

这个是实现了Parcelable接口的类,AIDL支持的数据类型:

基本数据类型(int、long、char、boolean、double等);

String和CharSequence;

List:只支持ArrayList,里面每个元素都必须能够被AIDL支持;

Map:只支持HashMap,里面的每个元素都必须被AIDL支持,包括key和value;

Parcelable:所有实现了Parcelable接口的对象;

AIDL:所有的AIDL接口本身也可以在AIDL文件中使用。

Parcelable这个比较常用不再赘述。

Student.aidl

这个是上面的类对应的AIDL文件,需要在同一级目录,并声明Student类是parcelable的。


IStudentManager.aidl

处理业务的AIDL,这里需要注意的是,引用的类必须要import即使是在同一个目录下,这一点比较特殊,我觉得应该是为了准确的定位到这个类。

当前需要的AILD就定义完了。现在Make Project一下,生成了IStudentManager.java:


IStudentManager

到这里我们先分析下生成的这个文件。

1.DESCRIPTOR

Binder的唯一标识,一般用当前Binder的类名表示,比如本例中的“com.stone.demoandroid.entity.IStudentManager”。

2.asInterface

用于将服务端的Binder对象转换成客户端所需的AIDL接口类型的对象,这种转换过程是区分进程的,如果客户端和服务端位于同一进程,那么此方法返回的就是服务端的Stub对象本身,否则返回的是系统封装后的Stub.proxy对象。

3.asBinder

此方法用于返回当前Binder对象。

4.onTransact

这个方法运行在服务端中的Binder线程池中,当客户端发起跨进程请求时,远程请求会通过系统底层封装后交由此方法来处理。该方法的原型为publicBooleanonTransact(intcode,android.os.Parceldata,android.os.Parcelreply,intflags)。服务端通过code可以确定客户端所请求的目标方法是什么,接着从data中取出目标方法所需的参数(如果目标方法有参数的话),然后执行目标方法。当目标方法执行完毕后,就向reply中写入返回值(如果目标方法有返回值的话),onTransact方法的执行过程就是这样的。需要注意的是,如果此方法返回false,那么客户端的请求会失败,因此我们可以利用这个特性来做权限验证,毕竟我们也不希望随便一个进程都能远程调用我们的服务。

5.Proxy#getBookList

这个方法运行在客户端,当客户端远程调用此方法时,它的内部实现是这样的:首先创建该方法所需要的输入型Parcel对象_data、输出型Parcel对象_reply和返回值对象List;然后把该方法的参数信息写入_data中(如果有参数的话);接着调用transact方法来发起RPC(远程过程调用)请求,同时当前线程挂起;然后服务端的onTransact方法会被调用,直到RPC过程返回后,当前线程继续执行,并从_reply中取出RPC过程的返回结果;最后返回_reply中的数据。

6.Proxy#addBook

这个方法运行在客户端,它的执行过程和getBookList是一样的,addBook没有返回值,所以它不需要从_reply中取出返回值。

通过上面对IStudentManager里面主要方法的分析我们也能大概了解到Binder的原理,下面给出Binder的工作机制图。当然还有一点要说明的就是线程同步的问题,因为不过操作是否耗时,应该不会只有一个线程所以要采用同步的方式去实现。

Binder工作机制

下面我们需要一个Service来实现服务端,并实现线程同步。

StudentManagerService

下面就很简单了,实现客户端的调用,我这里直接用了MainActivity。


MainActivity

这里AIDL的简单应用就介绍完了,希望大家能对Binder有更进一步的认识。

另外一个Messenger的可以看下这篇博客IPC方式,3Messenger

demo链接

你可能感兴趣的:(Android Binder)