这篇文章涉及的知识点:

  • Binder的应用场景及原理
  • AIDL的应用场景及原理
  • Messenger的应用场景及原理
  • Service

官网:

:只有允许不同应用的客户端用 IPC 方式访问服务,并且想要在服务中处理多线程时,才有必要使用 AIDL。 如果您不需要执行跨越不同应用的并发 IPC,就应该通过实现一个 Binder 创建接口;或者,如果您想执行 IPC,但根本不需要处理多线程,则使用 Messenger 类来实现接口。无论如何,在实现 AIDL 之前,请您务必理解绑定服务。

这段话说了跨进程的三种方式以及每种的使用场景

  1. 跨应用(此时跨应用就是在不同进程内)并且在服务中处理多线程时使用AIDL
  2. 同一个应用不同进程存在多线程时使用Binder
  3. 同一个应用不同进程在不需要处理多线程时使用Messenger

Binder原理

android 跨进程通讯 android跨进程通信应用场景_多线程

 

简单的可以理解为Server在ServiceManager中进行注册,Client要调用Server的方法,但是ServerManager不会把真的Server返回给Client,而把Server的一个代理对象Proxy返回给Client。再次Client调用Proxy的add方法ServerManager会帮Client调用Server的add方法并把结果返回给Client。

 

 

AIDL的原理

官网:

注:在您开始设计 AIDL 接口之前,要注意 AIDL 接口的调用是直接函数调用。 您不应该假设发生调用的线程。 视调用来自本地进程还是远程进程中的线程,实际情况会有所差异。 具体而言:

  • 来自本地进程的调用在发起调用的同一线程内执行。如果该线程是您的主 UI 线程,则该线程继续在 AIDL 接口中执行。 如果该线程是其他线程,则其便是在服务中执行您的代码的线程。 因此,只有在本地线程访问服务时,您才能完全控制哪些线程在服务中执行(但如果真是这种情况,您根本不应该使用 AIDL,而是应该通过实现 Binder 类创建接口)。
  • 来自远程进程的调用分派自平台在您的自有进程内部维护的线程池。 您必须为来自未知线程的多次并发传入调用做好准备。 换言之,AIDL 接口的实现必须是完全线程安全实现。
  • oneway 关键字用于修改远程调用的行为。使用该关键字时,远程调用不会阻塞;它只是发送事务数据并立即返回。接口的实现最终接收此调用时,是以正常远程调用形式将其作为来自 Binder 线程池的常规调用进行接收。 如果 oneway 用于本地调用,则不会有任何影响,调用仍是同步调用。

 

用此图说明原理很清晰:

android 跨进程通讯 android跨进程通信应用场景_Server_02

                                                                                 来自Android插件话开发指南

 

解释图片上跨进程的流程:

1.无论是Client还是Server 里面都有类Stub,Proxy。从Client看,对于AIDL使用者,我们这样写程序:


MyAidl.Stub.asInterface(某IBinder对象).sum(1,2)


asInterface()方法的作用是判断参数也就是IBinder和自己是否是在一个进程中,如果在就直接调用和跨进层没有关系。

如果不是则把这个IBinder参数包装成一个Proxy对象,则调用Stub的sum方法就是间接调用Proxy的sum方法。

2.Proxy在自己的sum方法中,会使用Parcelable来准备数据,把函数名称、函数参数都写入_data,让_reply接受函数返回值。最后使用IBinder的transact方法,就可以把数据传给Binder的Server端了。

3.Server接受Client传输过来的方法名,参数后,根据方法名再找到对应的函数并传入参数得出结果返回给客户端。

Server处理过程:接收数据->调用函数->把数据返回写数据的过程。