从AIDL来认识Binder
来源:互联网 发布:http默认端口号8080 编辑:程序博客网 时间:2024/05/24 22:44
在平时的Android开发过程中,很少接触到Binder,对这个东西也是带了几分畏惧,虽然知道这个很重要,但是,理解起来却不是一件容易的事情。今天就带大家从AIDL来分析Binder。
Binder是一个C/S架构,就是说分为客户端跟服务端。这里的客户端跟服务端不是我们平时开发中所说的那样,这里的客户端是指发送消息的一端,服务端是指接受消息的一端。
Binder在进程间通信发挥了很大的作用,起到了一个媒介的作用,谁给谁发送或者接受消息都要通过它。这里的进程间通信不只是单纯的值多个进程之间,一个进程里的通信也是通过Binder,像四大组件的通信,这些都是通过Binder的。
相信大家也或多或少的使用过AIDL来实现进程间通信,在Androidstudio中,可以通过新建一个AIDL文件,然后,编译器自动帮我们生成这样一个文件,不需要我们手动再去编写,提供了很大的便利。下面我们来看下编译器帮我们生成的AIDL文件长什么样子。
public interface IMyAidlInterface extends IInterface { void basicTypes(int var1, long var2, boolean var4, float var5, double var6, String var8) throws RemoteException; public abstract static class Stub extends Binder implements IMyAidlInterface { private static final String DESCRIPTOR = "com.rxdemo.IMyAidlInterface"; static final int TRANSACTION_basicTypes = 1; public Stub() { this.attachInterface(this, "com.rxdemo.IMyAidlInterface"); } public static IMyAidlInterface asInterface(IBinder obj) { if(obj == null) { return null; } else { IInterface iin = obj.queryLocalInterface("com.rxdemo.IMyAidlInterface"); return (IMyAidlInterface)(iin != null && iin instanceof IMyAidlInterface?(IMyAidlInterface)iin:new IMyAidlInterface.Stub.Proxy(obj)); } } public IBinder asBinder() { return this; } public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch(code) { case 1: data.enforceInterface("com.rxdemo.IMyAidlInterface"); int _arg0 = data.readInt(); long _arg1 = data.readLong(); boolean _arg2 = 0 != data.readInt(); float _arg3 = data.readFloat(); double _arg4 = data.readDouble(); String _arg5 = data.readString(); this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5); reply.writeNoException(); return true; case 1598968902: reply.writeString("com.rxdemo.IMyAidlInterface"); return true; default: return super.onTransact(code, data, reply, flags); } } private static class Proxy implements IMyAidlInterface { private IBinder mRemote; Proxy(IBinder remote) { this.mRemote = remote; } public IBinder asBinder() { return this.mRemote; } public String getInterfaceDescriptor() { return "com.rxdemo.IMyAidlInterface"; } public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken("com.rxdemo.IMyAidlInterface"); _data.writeInt(anInt); _data.writeLong(aLong); _data.writeInt(aBoolean?1:0); _data.writeFloat(aFloat); _data.writeDouble(aDouble); _data.writeString(aString); this.mRemote.transact(1, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } }}首先是要继承自IInterface,这是肯定的,编写AIDL时都需要继承这个接口。
我们可以看到这里生成了两个内部类,Stub 跟 Proxy ,Stub 继承自Binder 并且实现了IMyAidlInterface, 可以看出这是一个Binder, Proxy 实现了 IMyAidlInterface这个接口,从名字上面可以看到这是一个代理类。这里其实就是一个服务端跟客户端。现在,假设有两个进程,A和B ,当A向B发消息的时候,会通过代理类Proxy,向Binder 发送消息,然后Binder 再把这个消息发给进程B的Stub对象,完成一次进程间通信,这里也充分的说明了Binder 既可以是服务端也可以是客户端,主要取决于是接受消息还是发送消息。
在Proxy这个代理类里面有这样一段代码
Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken("com.rxdemo.IMyAidlInterface"); _data.writeInt(anInt); _data.writeLong(aLong); _data.writeInt(aBoolean?1:0); _data.writeFloat(aFloat); _data.writeDouble(aDouble); _data.writeString(aString); this.mRemote.transact(1, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); }
注意到没有,创建了一个reply对象,然后 通过 this.mRemote.transact 方法将数据打包发送出去。这个方法是非常重要的,客户端向服务端发送消息就是通过这个方法,也就是说这个方法是在客户端的。我们再看 Stub这个类里面是怎么接收消息的。
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch(code) { case 1: data.enforceInterface("com.rxdemo.IMyAidlInterface"); int _arg0 = data.readInt(); long _arg1 = data.readLong(); boolean _arg2 = 0 != data.readInt(); float _arg3 = data.readFloat(); double _arg4 = data.readDouble(); String _arg5 = data.readString(); this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5); reply.writeNoException(); return true; case 1598968902: reply.writeString("com.rxdemo.IMyAidlInterface"); return true; default: return super.onTransact(code, data, reply, flags); } }onTransact 这个方法是在服务端的,用于接收消息。
在Stub这个类里面有一个asInterface方法,
public static IMyAidlInterface asIn return null;terface(IBinder obj) {if(obj == null) {} else { IInterface iin = obj.queryLocalInterface("com.rxdemo.IMyAidlInterface"); return (IMyAidlInterface)(iin != null && iin instanceof IMyAidlInterface?(IMyAidlInterface)iin:new IMyAidlInterface.Stub.Proxy(obj)); } }queryLocalInterface这个方法里面传入了一个参数,这个参数是descriptor用来表示唯一的AIDL文件,我们看asInterface这个方法返回的逻辑是什么,表示,如果能找到这个iin对象,表示在同一个进程,如果找不到,就需要通过代理对象去实现远程通信,不在一个进程。
我们在启动一个Service的时候,会去使用binderService这个方法来绑定一个服务,可以是同进程的,也可是远程的。
this.bindService(intent, new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { try { IMyAidlInterface asInterface=IMyAidlInterface.Stub.asInterface(service); asInterface.testBinder(); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } },);
在service bind成功之后,就可以通过IMyAIDLInterface 这个接口对象去调用远程的方法了。
- 从AIDL来认识Binder
- 从dumpsys自定义服务来认识Android binder
- 深入理解Binder(一),从AIDL谈起
- Binder AIDL
- Binder&AIDL
- 从AIDL开始谈Android进程间Binder通信机制
- 从AIDL开始谈Android进程间Binder通信机制
- 认识AIDL
- 跟面试官讲Binder(二)之关于AIDL的认识
- partial BINDER(AIDL)
- Binder与AIDL服务
- Binder与AIDL服务
- AIDL的Binder框架
- Binder-基础知识和AIDL
- Binder AIDL 理解
- AIDL和Binder图解
- Binder机制和AIDL
- AIDL 与 Binder机制
- normalize、splitText
- 关于RecyclerView中含有CheckBox,Button等控件失去焦点的解决办法
- pip install --upgrade pip 9.0.1 error
- Bot Framework使用Direct Line实现第三方渠道调用Bot服务
- 小白初识线段树(线段树原理+专题练习)
- 从AIDL来认识Binder
- iOS AVCapture前置摄像头不显示镜像翻转
- Python库的安装方法
- 使用可编辑JComboBox的时遇到的一个坑,编辑后如果JCombobox的焦点还在,则获取不到当前的编辑值。
- ZOJ--1010:Area(线段判交问题)
- 西财2018届电商研究生招生简介
- iOS
- poj3620 DFS
- Linux系统下yum命令