IPC基础小记 关于Binder

来源:互联网 发布:怎么申请网站域名 编辑:程序博客网 时间:2024/06/05 11:12

Binder是Android中的一个类,它实现了IBinder接口。
从IPC角度来说Binder是Android中的一种跨进程通信方式
Binder是桥梁,Binder是媒介。。。给笔者印象Binder就是个顺丰。。。
我们可以通过AIDL文件生成一个Binder类
新建一个文件后缀改成.aidl敲如下代码


package com.example.testandroid;

parcelable Book;


新建一个文件后缀改成.aidl 敲如下代码


package com.example.testandroid;

import com.example.testandroid.Book;
interface IBookManager{
List<Book>getBookList();
void addBook(in Book book);
}


系统会生成一个IBookManager.java类

/* * This file is auto-generated.  DO NOT MODIFY. * Original file:  */package com.example.testandroid;public interface IBookManager extends android.os.IInterface {    /** Local-side IPC implementation stub class. */    public static abstract class Stub extends android.os.Binder implements com.example.testandroid.IBookManager {        private static final java.lang.String DESCRIPTOR = "com.example.testandroid.IBookManager";        /** Construct the stub at attach it to the interface. */        public Stub() {            this.attachInterface(this, DESCRIPTOR);        }        /**         * Cast an IBinder object into an com.example.testandroid.IBookManager         * interface, generating a proxy if needed.         */        public static com.example.testandroid.IBookManager asInterface(android.os.IBinder obj) {            if ((obj == null)) {                return null;            }            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);            if (((iin != null) && (iin instanceof com.example.testandroid.IBookManager))) {                return ((com.example.testandroid.IBookManager) iin);            }            return new com.example.testandroid.IBookManager.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_getBookList: {                data.enforceInterface(DESCRIPTOR);                java.util.List<com.example.testandroid.Book> _result = this.getBookList();                reply.writeNoException();                reply.writeTypedList(_result);                return true;            }            case TRANSACTION_addBook: {                data.enforceInterface(DESCRIPTOR);                com.example.testandroid.Book _arg0;                if ((0 != data.readInt())) {                    _arg0 = com.example.testandroid.Book.CREATOR.createFromParcel(data);                } else {                    _arg0 = null;                }                this.addBook(_arg0);                reply.writeNoException();                return true;            }            }            return super.onTransact(code, data, reply, flags);        }        private static class Proxy implements com.example.testandroid.IBookManager {            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 java.util.List<com.example.testandroid.Book> getBookList() throws android.os.RemoteException {                android.os.Parcel _data = android.os.Parcel.obtain();                android.os.Parcel _reply = android.os.Parcel.obtain();                java.util.List<com.example.testandroid.Book> _result;                try {                    _data.writeInterfaceToken(DESCRIPTOR);                    mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);                    _reply.readException();                    _result = _reply.createTypedArrayList(com.example.testandroid.Book.CREATOR);                } finally {                    _reply.recycle();                    _data.recycle();                }                return _result;            }            @Override            public void addBook(com.example.testandroid.Book book) throws android.os.RemoteException {                android.os.Parcel _data = android.os.Parcel.obtain();                android.os.Parcel _reply = android.os.Parcel.obtain();                try {                    _data.writeInterfaceToken(DESCRIPTOR);                    if ((book != null)) {                        _data.writeInt(1);                        book.writeToParcel(_data, 0);                    } else {                        _data.writeInt(0);                    }                    mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);                    _reply.readException();                } finally {                    _reply.recycle();                    _data.recycle();                }            }        }        static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);        static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);    }    public java.util.List<com.example.testandroid.Book> getBookList() throws android.os.RemoteException;    public void addBook(com.example.testandroid.Book book) throws android.os.RemoteException;}

根据AIDL文件系统生成了IBookManager.java这个类,它继承了IInterface这个接口,同时他本身也是一个接口。所有在Binder中传输的接口都需要继承IInterface这个接口。
类中声明了aidl文件中声明的两个方法,这两个方法还有对应的id。
然后还生成了一个Stub内部类,这就是Binder了

属性详解:
DESCRIPTOR :Binder的唯一标识

private static final java.lang.String DESCRIPTOR = "com.example.testandroid.IBookManager";

asInterface(android.os.IBinder obj)

public static com.example.testandroid.IBookManager asInterface(android.os.IBinder obj) {            if ((obj == null)) {                return null;            }            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);            if (((iin != null) && (iin instanceof com.example.testandroid.IBookManager))) {                return ((com.example.testandroid.IBookManager) iin);            }            return new com.example.testandroid.IBookManager.Stub.Proxy(obj);        }

该方法用于判断传进来的IBinder是不是就在当前进程里面,如果是的话就直接返回((com.example.testandroid.IBookManager) iin),不是的话就返回com.example.testandroid.IBookManager.Stub.Proxy(obj)

public android.os.IBinder asBinder():返回当前Binder

onTransact方法是在Stub的内部实现的。

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_getBookList: {                data.enforceInterface(DESCRIPTOR);                java.util.List<com.example.testandroid.Book> _result = this.getBookList();                reply.writeNoException();                reply.writeTypedList(_result);                return true;            }            case TRANSACTION_addBook: {                data.enforceInterface(DESCRIPTOR);                com.example.testandroid.Book _arg0;                if ((0 != data.readInt())) {                    _arg0 = com.example.testandroid.Book.CREATOR.createFromParcel(data);                } else {                    _arg0 = null;                }                this.addBook(_arg0);                reply.writeNoException();                return true;            }            }            return super.onTransact(code, data, reply, flags);        }

code:每个方法都有一个int类型的数字用来区分(后面中的swicth),也就是之前说到生成的方法ID。
data:传过来的数据,其中包含我们的参数,以及类的描述。
reply:传回的数据,我们要写入是否发生了Exception,以及返回值
flags:该方法是否有返回值 ,0表示有返回值。

调用onTransact就表示有数据传来,首先就会通过swicth判断是哪个方法,然后取出方法参数,调用本地实现的方法获取返回值,写入返回值到reply。最后,返回true,才会把数据发送出去,返回false就不会把结果返回给Activity了。这里也就是说,只有返回true,我们Proxy中才能接受从远端传回的数据。

public java.util.List<com.example.testandroid.Book> getBookList() throws android.os.RemoteException 

这个方法内部实现大概是:
创建输入型Parcel对像:android.os.Parcel _data = android.os.Parcel.obtain();
创建输出型对象:android.os.Parcel _reply = android.os.Parcel.obtain();
创建返回值对像:java.util.List<com.example.testandroid.Book> _result;
然后把方法参数信息写入_data中,之后调用
mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);发起请求。然后服务端的onTransaction方法会被调用直到这个请求被返回后
_result = _reply.createTypedArrayList(com.example.testandroid.Book.CREATOR);获取返回结果,返回_reply中的数据return _result;


以上就是通过AIDL文件通过系统生成Binder的相关内容,当然也可以手动写一个Bineder。

0 0