Android开发指南之Binder源码分析
AIDL中的Binder实现
在 Android AIDL实现进程间通信中,我们曾提到要想实现IPC,我们需要通过定义.aidl接口来实现。其实,创建.aidl文件的目的就是让SDK为为我们自动生成.aidl文件对应的java类,该类的主要核心就是Binder。
这里是定义的IContactsService.aidl。
// IContactsService.aidl package com.zhangke.aidlserverdemo; // Declare any non-default types here with import statements import com.zhangke.aidlserverdemo.Contacts; interface IContactsService { /** *保存联系人 */ int saveContacts(in Contacts contacts); /** *获取联系人列表 */ List getContactsList(); }
下面是SDK自动生成的IContactsService.java类,该类继承自android.os.IInterface接口。
这里有几个主要的属性和方法:
DESCTIPTOR:Binder的唯一标识 asInterface():返回客户端需要的AIDL接口类型的对象 asBinder():IInterface接口定义的方法,返回Binder对象 onTransact():IPC的核心方法,也是RPC(远程过程调用)的流程 Proxy#saveContacts和Proxy#getContactsList:AIDL接口定义的方法,该方法也是提供给客户端调用的方法。/** * SDK生成的java类, 该类继承自android.os.IInterface接口 */ public interface IContactsService extends android.os.IInterface { /** * 该类继承自Binder,并且实现了IContactsService接口,这里有方法的具体实现 */ public static abstract class Stub extends android.os.Binder implements com.zhangke.aidlserverdemo.IContactsService { private static final java.lang.String DESCRIPTOR = "com.zhangke.aidlserverdemo.IContactsService"; /** * 在服务中,一般都是通过创建该类,然后获取对应Binder引用 */ public Stub() { /** * 将IContactsService接口和Binder关联起来 */ this.attachInterface(this, DESCRIPTOR); } /** * 将Binder对象转换成与之对应的IContactsService接口对象, * IContactsService对象一般会在客户端被使用 */ public static com.zhangke.aidlserverdemo.IContactsService asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } /** * obj.queryLocalInterface(DESCRIPTOR),该方法判断客户端和服务器是否是在同一进程,如果是同一个进程,则返回服务对象本身 * 否则,会返回系统封装的Proxy对象 */ android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.zhangke.aidlserverdemo.IContactsService))) { return ((com.zhangke.aidlserverdemo.IContactsService) iin); } return new com.zhangke.aidlserverdemo.IContactsService.Stub.Proxy(obj); } /** * 该方法是android.os.IInterface接口中的方法,返回当前Binder对象 * 一般在绑定服务的onBind()方法中,通过该方法返回Binder对象 */ @Override public android.os.IBinder asBinder() { return this; } /** * 核心方法 *
* 1、该方法运行在服务端的Binder线程池中,当客户端发起请求后,服务端根据code参数确定客户端请求的具体方法 */ @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_saveContacts: { data.enforceInterface(DESCRIPTOR); com.zhangke.aidlserverdemo.Contacts _arg0; if ((0 != data.readInt())) { /** * 2、通过data参数,获取客户端输入的参数 */ _arg0 = com.zhangke.aidlserverdemo.Contacts.CREATOR.createFromParcel(data); } else { _arg0 = null; } /** * 3、执行目标方法 */ int _result = this.saveContacts(_arg0); reply.writeNoException(); /** * 4、写入返回值 */ reply.writeInt(_result); /** * 该返回值如果返回false,说明请求调用会失败 */ return true; } case TRANSACTION_getContactsList: { data.enforceInterface(DESCRIPTOR); java.util.List
IInterface源码分析
package android.os; /** * Binder接口的基类,要想实现Binder必须实现该接口 */ public interface IInterface { /** * 查找与接口对应的Binder对象,必须通过该方法才能使Proxy * 对象返回一个正确的结果 */ public IBinder asBinder(); }