BindService 流程分析

本文详细分析了Android中BindService的流程,包括三个Binder对象:ActivityManagerProxy、IApplicationThread和IServiceConnection。讲解了从应用C通过Service连接到应用S的Binder对象传递过程,涉及四个进程间的调用,解释了AMS如何协调这些进程并传递Binder。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 问题介绍

  在应用S中实现一个非常基础的功能(XXInterface)。如果应用C需要用到S实现的功能。通常的做法是:在应用S中定义一个Binder对象b,b同时实现了功能接口(XXInterface)。然后将b传递给应用C,这样C就可以远程调用S中的函数。
  如何将S应用的Binder传递给应用C,主要有两种方法:一种是通过ServiceManager,S将Binder对象注册到ServiceManager中,然后C通过ServiceManager获取;一种是在S中定义一个Service,在Service的onbind函数中提供Binder对象,C应用调用BindService获取Binder对象。本文主要分析BindService获取Binder的流程。

2三个Binder对象

  应用S和应用C无法直接相互通信,他们的联系要通过AMS。所以BindService的过程涉及到应用(进程)S和AMS,以及应用(进程)C和AMS直接的交互。它们的通信过程涉及到了3个不同的Binder对象。
先简单介绍一下Binder的特点和这3个Binder对象。
  Binder 分为proxy(Client)和stub(Service)两种,一般proxy和stub位于不同的进程,通过proxy可以调用stub实现的方法。Binder远程调用的过程其实是将参数从进程C通过Binder驱动传到S,然后执行stub中对应的方法,然后将执行结果由S传到C的过程。
  Binder可以在进程之间相互传递,比如在proxy(进程C)调用stub(进程S)中的方法时,可以传入Binder类型的参数,这样Binder对象就由C传递到S。stub类型的Binder在传递到其他进程之后变为proxy类型,proxy类型传递之后仍然为proxy类型。在跨进程调用时把Binder对象作为参数,在Android中非常常见。

  1. 首先AMS(ActivityManagerService)本身就是一个Binder对象,他的代理对象是ActivityManagerProxy。客户端应用通过ActivityManagerProxy调用AMS的方法。比如应用C在执行BindService时,会通过ActivityManagerProxy调用AMS中的BindService方法。
  2. 实现了IApplicationThread接口的Binder。AMS主要通过该Binder调用客户端进程的函数。比如启动Activity时,AMS通过该Binder通知ActivityThread 创建Activity。这时 AMS是Client,ActivityThread 是Service。应用在通过ActivityManagerProxy 调用AMS的函数时,会把该Binder传递给AMS。
  3. 实现了IServiceConnection接口的Binder。AMS通过该Binder传递最终的Binder对象给 调用进程。该Binder也是客户进程传递给AMS的。

除了ActivityManagerProxy是从ServiceManager获取的,其他的Binder proxy 对象都是在进程间传递得到的。

Created with Raphaël 2.1.0ServiceConnectionServiceConnectionIServiceConnectionIServiceConnectionContextImplContextImplActivityManagerServiceActivityManagerServiceIApplicationThreadIApplicationThreadActivityThreadActivityThreadServiceServicebinderServiceCommonbinderService进程A跨进程调用AMS中的方法。scheduleBindServiceAMS跨进程调用进程B中的方法。handleBindServiceonBindpublishService进程B跨进程调用AMS中的方法。connectedAMS跨进程调用进程A中的方法。onServiceConnected

进程间交互过程

3四个进程间调用

在上面的图中已经标明了这四个进程间调用。下面主要分析这四个调用传递的参数,返回的结果,涉及到的进程。

  1. A进程调用AMS 的BindService方法,传递的参数主要有两个 一个是Intent,包含绑定的Service信息。一个是IServiceConnection Binder对象,在AMS获得要A要的Binder(A调用BinderService要获取的Binder这里称为 Target Binder)对象之后,通过IServiceConnection Binder 将 Target Binder传递给进程A。这里还隐藏了一些细节,我们在调用Context 的BindService是,传递的是一个普通的ServiceConnection对象,并不是Binder 对象。其实是在调用AMS的BindService方法前将ServiceConnection包装为一个Binder对象IServiceConnection Binder。IServiceConnection Binder会调用ServiceConnection的onServiceConnected方法将Target Binder作为参数传递给进程A。
  2. AMS通过IApplicationThread Binder调用进程B的scheduleBindService方法,在scheduleBindService中会调用目标Service的onBind获取Target Binder。这里有一个问题,AMS是如何获得进程B的IApplicationThread Binder?分两种情况,1 如果进程B已经启动,会在AMS中有记录,通过A进程传给的Intent可以知道目标Service的进程,然后通过ProcessRecord可以得到IApplicationThread Binder。2 如果进程B没有启动,这时就比较复杂。通过Intent获得目标进程之后,AMS会先启动目标进程B,当B启动之后,会主动联系AMS,提供IApplicationThread Binder。详见代码。
  3. 进程B通过ActivityManagerProxy 调用AMS的publishService方法,将Target Binder传递给AMS。
  4. AMS 通过IServiceConnection 将Target Binder 传递给进程A。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值