关于Android中的Binder,从以下问题开始学习。
1) 什么是Binder?
Binder属于一个驱动,但是这种驱动不需要硬件支持,他是运行在Linux内核的一段程序,也就是说它的操作完成是基于一段内存,所以我们所开发的应用APK中对Binder的使用都是系统完成。
2) Binder是干什么的?在Android中起什么作用?
FrameWork提供Binder的原因是为了解决不同进程之间的通信(常说的IPC),即Binder的存在就是解决不同的进程之间通信。试想,在Android操作系统平台上,可能会安装很多个应用程序,这些应用程序必定运行在不同的进程中,假如有一个程序崩溃了,并不会影响其他程序运行。同样的道理,在我们开发的应用程序中有的Activity会与Android系统的服务(Service)打交道,Android系统的服务必定与我们的应用程序不在同一个进程中,所以,此时我们的应用程序要想获取系统的服务就需要Binder机制来完成通信请求和应答了。
3) Binder是如何实现不同进程之间的通信呢?
首先需要理清Binder在Android中的架构,Binder架构由服务端、Binder驱动和客户端三部分组成。原理图如下:
正如上图所示,服务端和客户端都是在用户空间工作,Binder驱动在内核,下面解释下这三部分组成。
① Binder服务端:一个Binder服务器就是一个Binder类的对象,当创建一个Binder对象的同时驱动端也创建了一个Binder对象(mRemote对象),服务端的Binder创建完成后,在Binder内部就会创建一个隐藏的线程,该线程接下来会接收Binder驱动发送的消息,收到消息后就会执行Binder对象中的onTransact()方法,并且按方法的参数执行不同的服务代码,因此要实现一个Binder服务必须重载onTransact()方法。
② Binder驱动:上面说过,当服务端创建Binder对象时,内核驱动同时也会创建一个叫做mRemote的Binder对象,客户端就是通过此对象的引用来访问远程服务。
③ 客户端:客户端要想访问Binder的远程服务,就必须获取远程服务的Binder对象在binder驱动层对应的mRemote引用。当获取到mRemote对象引用后就可以调用其transact()方法,而在Binder驱动中mRemote对象重载了transact()方法。
说明:从以上的分析可以看出,对于应用程序来说,客户端看起来是直接调用远程服务对应的Binder,而事实上则是通过Binder驱动进行了中转,即存在两个Binder对象,一个是服务端的Binder对象,另一个是Binder驱动中的Binder对象,所不同的是Binder驱动中的对象不会再额外产生一个线程。
4)客户端如何获取Binder驱动的mRemote对象?
在上面③中已经介绍了客户端是如何完成IPC的,此过程最重要的是获取mRemote对象,那么客户端是如何获取mRemote对象的?
事实上,在了解了Binder机制之后我们就可以自己定义一个服务端的服务,即编写一个类继承于Binder,以代替系统的服务。但是对于程序的客户端来说还是必须继承SDK提供的Service来获取服务的。
无论是否自定义在客户端的Service中都需要解决如何获取mRemote对象的问题。首先AmS提供了一个startService()的方法用于启动客户服务,而对于客户端来说,可以使用以下两个方法来和一个服务建立连接:startService(Intent intent)和bindService(。。。)。
5)系统的服务的Binder引用是如何传递给客户端的?
我们在应用编程时,经常使用getSystem方法获取一个系统服务,那么这些服务的Binder对象是如何传递到客户端的?系统的服务并不是通过startService()方法启动的。这就是ServiceManager的作用了。
ServiceManager是一个独立的进程,它用来管理各种系统的服务。ServiceManager本身也是一个Service,FrameWork提供了一个系统函数,可以获取Service对应的Binder引用,那就是BinderInternal.getContextObject()。该静态函数返回ServiceManager后就可以通过ServiceManager提供的方法获取其他系统的Service的Binder引用。而ServiceManager所管理的所有Service都是以相应的Manager返回给客户端的。
本节完毕,关于在应用程序中使用Android的四大组件之一的Service的使用以及原理后面再说吧。