BindService
首先介绍下Binder机制,我们熟悉的是AIDL接口
每一个AIDL接口都是下面这种格式
public interface aidl接口 extends android.os.IInterface
public static abstract class Stub extends android.os.Binder implements aidl接口
public Stub() {this.attachInterface(this, DESCRIPTOR);}
public static aidl接口 asInterface(android.os.IBinder obj)
private static class Proxy implements aidl接口
Proxy(android.os.IBinder remote) {mRemote = remote;}
每个aidl接口都由两部分构成,一个是Stub,一个是Proxy(也就是我们常说的本地代理)
这两个是有分工的,Proxy主要是用来写数据的,而Stub是用来接收数据的
举个例子:
假如要给好友发送一条消息,这个时候你的消息是由Proxy帮你发出去的,
如果你的好友收到消息,并给你发了一条消息,这个时候你会接收到消息,是通过Stub接收的
下面举个源码中的例子:
public interface IActivityManager extends IInterface
public abstract class ActivityManagerNative extends Binder implements IActivityManager
class ActivityManagerProxy implements IActivityManager
public final class ActivityManagerService extends ActivityManagerNative这个类继承自ActivityManagerNative,也就是一个远端的Stub
源码分析,以下是以SDK25源码来看的
MainActivity:
-->this.bindService()
ContextImpl:
-->bindServiceCommon()
--> ActivityManagerNative.getDefault()
ActivityManagerNative也就是本地代理
--> IBinder b = ServiceManager.getService("activity") 拿到远端的ActivityManagerService的IBinder引用
--> IActivityManager am = asInterface(b); 通过远端的IBinder引用拿到了IActivityManager接口对象,也就是本地代理Proxy
在new本地Proxy时把远端IBinder引用传入构造方法,所以本地Proxy持有远端ActivityManagerService的IBinder引用
--> public int bindService(
mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
这句实际是执行的远端ActivityManagerService的IBinder引用的transact方法,因为ActivityManagerService间接继承Binder所以,该方法在Binder里可以找到
Binder:
--> onTransact 由于子类重写了这个方法,所以最后应该在ActivityManagerNative里找到
ActivityManagerNative:
--> case BIND_SERVICE_TRANSACTION:
ActivityManagerService:
--> bindService()//ActivityManagerService继承ActivityManagerNative并且重写了bindService
ActivesServices:
-->int bindServiceLocked()
-->bringUpServiceLocked()
-->realStartServiceLocked(r, app, execInFg);
-->requestServiceBindingsLocked(r, execInFg);
-->requestServiceBindingLocked(r, ibr, execInFg, false)
--> r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,r.app.repProcState);
ActivityThread:
-->scheduleBindService()
-->handleBindService()
-->
if (!data.rebind) {//如果没有bind过,就bind
IBinder binder = s.onBind(data.intent);
ActivityManagerNative.getDefault().publishService(data.token, data.intent, binder);
} else {//如果bind过,就rebind
s.onRebind(data.intent);
ActivityManagerNative.getDefault().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
最后的这个publishService(data.token, data.intent, binder);也是一个进程间通信的过程
假如进程A绑定进程B的某个服务,在B绑定成功之后,要回调A的ServiceConnection告诉A,我绑定成功了,并把IBinder引用返回