Binder详解
Binder 在 Android 中占有很重要的作用,这里就对 Binder 做个解析,也便于以后复习。
主要从以下几方面分析:
-
Android 中的 IPC 机制
-
AIDL 的使用及分析
-
Binder 通信机制的分析
Android 中的 IPC 机制
Android 是基于 Linux 内核的,所以先看下 Linux 中的 IPC 机制
-
管道
-
信号
-
消息队列
-
信号灯
-
共享内存
-
Socket
这个就不详细看了,以后有时间了再研究
Android 的 IPC 机制
-
通过文件共享
-
Socket
-
Messager
-
ContentProvider
-
AIDL
其中 Messager,ContentProvider,AIDL 都是基于 Binder,可以看出 Binder 的重要性,理解了 Binder 机制后感觉还是很巧妙的。
AIDL 的使用及分析
AIDL 的使用
-
创建 aidl 文件
-
在 aidl 文件中定义接口
package zy.com.uninstall.aidl;interface IMyAidlInterface { void set(int val); int get(); }
-
构建工程生成 Java 文件
-
编写 Service 并集成 IMyAidlInterface.Stub() 重写接口函数,在 onBind() 中返回
public class MyServer extends Service { @Nullable @Override public IBinder onBind(Intent intent) { IMyAidlInterface binder = new IMyAidlInterface.Stub() { @Override public void set(int val) throws RemoteException { } @Override public int get() throws RemoteException { return 0; } }; return null; } }
-
使用时在 onServiceConnected() 中获取到 IMyAidlInterface,之后就可以通过 binder 调用远程方法
private void initService() throws RemoteException { ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { binder = IMyAidlInterface.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { } }; Intent intent = new Intent(this, MyServer.class); bindService(intent, connection, BIND_AUTO_CREATE); }
aidl 生成 java 文件的分析
创建 aidl 文件构建工程后,会自动生成下面的 java 文件
// IMyAidlInterface.javapackage zy.com.uninstall.aidl;// Declare any non-default types here with import statementspublic interface IMyAidlInterface extends android.os.IInterface { /**
* Local-side IPC implementation stub class.
*/
// service 方的 Binder
public static abstract class Stub extends android.os.Binder implements zy.com.uninstall.aidl.IMyAidlInterface { private static final java.lang.String DESCRIPTOR = "zy.com.uninstall.aidl.IMyAidlInterface"; /**
* Construct the stub at attach it to the interface.
*/
public Stub() { this.attachInterface(this, DESCRIPTOR);
} /**
* Cast an IBinder object into an zy.com.uninstall.aidl.IMyAidlInterface interface,
* generating a proxy if needed.
*/
public static zy.com.uninstall.aidl.IMyAidlInterface asInterface(android.os.IBinder obj) { if ((obj == null)) { return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); // 如果 client 和 service 是同一个进程,直接返回 Stub 本身
if (((iin != null) && (iin instanceof zy.com.uninstall.aidl.IMyAidlInterface))) { return ((zy.com.uninstall.aidl.IMyAidlInterface) iin);
} // 如果 client 和 service 不是同一个进程,返回代理类
return new zy.com.uninstall.aidl.IMyAidlInterface.Stub.Proxy(obj);
} @Override
public android.os.IBinder asBinder() { return this;
} // 通过 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_set: { // 调用 set() 函数
data.enforceInterface(DESCRIPTOR); int _arg0;
_arg0 = data.readInt(); this.set(_arg0); // 在 service 中实现
reply.writeNoException(); return true;
} case TRANSACTION_get: { // 调用 get() 函数
data.enforceInterface(DESCRIPTOR); int _result = this.get(); // 在 service 中实现
reply.writeNoException();
reply.writeInt(_result); return true;
}
} return super.onTransact(code, data, reply, flags);
} // Binder 的代理类,如果 client 和 service 不是同一个进程就会给 client 返回这个代理类
private static class Proxy implements zy.com.uninstall.aidl.IMyAidlInterface { private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
} @Override
public android.os.IBinder asBinder() { return mRemote;
} public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR;
} @Override
public void set(int val) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain(); try { // 对参数进行打包
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(val); // 调用服务器端的 transact() 函数,最终会调用到上面 Stub 中的 onTransact(),如果 service 端实现的方法耗时比较长,这个地方是会阻塞的
mRemote.transact(Stub.TRANSACTION_set, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
} @Override
public int get() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain(); int _result; try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_get, _data, _reply, 0); // 获取到返回参数
_reply.readException();
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
} return _result;
}
} // 对接口中方法的标志
static final int TRANSACTION_set = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_get = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
} public void set(int val) throws android.os.RemoteException; public int get() throws android.os.RemoteException;
}
上述代码在注释中对重要的地方做了解释,整体调用流程就是 service 中实现了 Stub 中的方法,并将 Binder 对象返回给 client,如果 client 和 service 在同一个进程,就返回 Stub 本身,否则返回 Proxy 对象,client 通过 Proxy 对象调用时,最终会调用到 Stub 的 onTransact() 函数,其中用 int 值来区分不同的函数。接下来详细分析下 Binder 的调用过程。
Binder 通信机制的分析
获取系统的 service
以后在写吧
ServiceManager 自身的注册和其他 service 的注册
这里放一张图说明整个过程
Binder 通信过程
这里放一张图说明整个过程
关于 Binder 的资料
关于 Binder 的资料有很多,这里放一些个人感觉很好的连接,这些博客资料都比本文写的要好也更详细,但还要写这篇的原因是方便自己以后复习看,个人认为把流程绘制成图更好理解一些,以后有更详细的分析也会加进来。