Android AIDL和Binder 简单分析

来源:互联网 发布:什么软件上youtube 编辑:程序博客网 时间:2024/05/16 00:53

AIDL使用方法:

在AIDLService中创建aidl文件在aidl文件中创建想要创建的接口,之后将.java文件改成.aidl文件重新编译项目.

创建service类在这个类中创建这个接口的对象实现对应的方法如下图:

public class ControlerService extends Service {    private final IController.Stub binder = new IController.Stub() {        @Override        public int addFun(int m, int n) throws RemoteException {            return m+n;        }    };    @Override    public void onCreate() {        super.onCreate();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        return super.onStartCommand(intent, flags, startId);    }    @Nullable    @Override    public IBinder onBind(Intent intent) {        return binder;    }}
之后在AIDLClient这个工程中创建同样的aidl文件夹和同样的aidl文件,之后通过bindService绑定服务就可以实现两个进程间的通信了.

public class MainActivity extends AppCompatActivity {    private IController controller = null;    private ServiceConnection myConn = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            controller = IController.Stub.asInterface(service);            Log.e(MainActivity.class.getName(), "绑定成功");        }        @Override        public void onServiceDisconnected(ComponentName name) {        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }    public void bindService(View view) {        //绑定服务        Intent intent = new Intent("com.zfr.aidlservice.ControllerService");        intent.setPackage("com.zengfanrui.practice.learnaidl");        bindService(intent, myConn,BIND_AUTO_CREATE);    }    public void addFun(View view) {        if (controller == null) {            return;        }        try {            int i = controller.addFun(1, 2);            Toast.makeText(this, "" + i, Toast.LENGTH_SHORT).show();        } catch (RemoteException e) {            e.printStackTrace();        }    }}
如上就实现了两个进城之间的通信了

现在分析一下这两个进程之间是如何实现通信的,这个时候就要使用到Binder,对于Binder本人了解的也不是很明白,个人认为Binder就是一个关联者(或者是中间者)用于协调Client和Service首先来看一下Android对.aidl文件所生成的代码

public interface IController extends android.os.IInterface{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.zengfanrui.aidlserver.IController{private static final java.lang.String DESCRIPTOR = "com.zengfanrui.aidlserver.IController";/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an com.zengfanrui.aidlserver.IController interface, * generating a proxy if needed. */public static com.zengfanrui.aidlserver.IController asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.zengfanrui.aidlserver.IController))) {return ((com.zengfanrui.aidlserver.IController)iin);}return new com.zengfanrui.aidlserver.IController.Stub.Proxy(obj);}@Override public android.os.IBinder asBinder(){return this;}@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_addFun:{data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();int _arg1;_arg1 = data.readInt();int _result = this.addFun(_arg0, _arg1);reply.writeNoException();reply.writeInt(_result);return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.zengfanrui.aidlserver.IController{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 int addFun(int m, int n) 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);_data.writeInt(m);_data.writeInt(n);mRemote.transact(Stub.TRANSACTION_addFun, _data, _reply, 0);_reply.readException();_result = _reply.readInt();}finally {_reply.recycle();_data.recycle();}return _result;}}static final int TRANSACTION_addFun = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);}public int addFun(int m, int n) throws android.os.RemoteException;}
Binder机制是由三个重要的部分组成的 Binder驱动,Binder服务端和Binder客户端,在Binder服务启动的之后服务会自动的将自己"送给"Binder驱动,Binder驱动会将这个服务记录,个人认为就是添加服务表中,之后在Binder客户端获取到了Binder对象之后

通过Binder对象发送调用某个方法的消息实际上是将这个消息传递给Binder驱动,Binder驱动会去对应的表中找到这个Binder服务,调这个服务对应的方法.

Binder服务在一开始启动的时候Binder就会调用transact()这个方法调用这个方法之后会去执行onTransact()这个方法,执行这个方法的时候就会将服务添加到驱动中,从上面的代码可以看到内部类Stub继承了Binder并且实现了我们自己定义的接口

这个Stub类重写了onTransact()方法所以在Binder服务刚刚启动的时候会执行Stub重写的onTransact将DESCRIPTOR通过writeString写进Binder驱动中

Binder客户端在调用Binder服务端方法的时候会通知Binder驱动客户端传递过来的数据是属于哪个服务端的并将数据写进内存中之后会调用transact方法,将客户端想要调用的方法的标志和参数传入,这时候Binder驱动就会找到对应的Service和对应的方法将参数传递过去并且等待Service将结果返回.

这篇文章只是简单的分析了一下Binder的执行过程,关于Binder机制还有很多需要了解的地方

想要更深的理解Binder 请看罗升阳大神的博客

点击打开链接