IPC之Binder

从不同角度对Binder的理解:

        直观来说,Binder是Android中的一个类,它实现了IBinder接口。从IPC来说,Binder是Android中的一种跨进程通信方式;Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder,该通信方式在Linux中没有;从Android 框架层来说,Binder 是ServiceManager连接各种Manager(ActivityManager、WindowManager,等等)和相应ManagerService的桥梁;从Android应用层来说。Binder是客户端和服务端通信的媒介,当bindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,通过这个Binder对象,客户端可以获取服务端提供的服务或者数据,这里的服务包括普通服务和机遇AIDL的服务。

      在Android开发中,Binder主要应用在Service中,包括AIDL和Messenger,其中普通Service中的Binder不涉及进程间通信;Messenger的底层是AIDL,所以采用分析AIDL的工作方式来学校Binder还是较好的。

代码分析:

包名:com.myj.example.aidl

文件:Book.java 、Book.aidl和IBookManager.aidl

//Book.java
package com.myj.example.aidl

public class Book implements Parcelable{
    public int bookId;
    public String bookName;

    public Book(int bookId,String bookName){
        this.bookId=bookId;
        this.bookName=bookName;
    }

    public int describeContents(){
        return 0;
    }

    public void writeToParcel(Parcel out,int flags){
        out.writeInt(bookId);
        out.writeString(bookName);
    }

    public static final Parcelable.Creator<Book> CREATOR=new Parcelable.CREATOR<Book>(){
        public Book createFromParcel(Parcel in){
            return new Book(in);
        }

        public Book[] newArray(int size){
            return new Book[size];
        }
    };

    private Book(Parcel in){
        bookId=in.readInt();
        bookName=in.readString();
    }
}


//Book.aidl
package com.myj.example.aidl

parcelable Book;
//IBookManager.aidl
package com.ryg.example.aidl

interface IBookManager{
    List<Book> getBookList();
    void addBook(in Book book);
}

方法声明:

getBookList():从远程服务端获取图书列表

addBook():往图书列表添加一本书

虽然Book类已经和IBookManager位于相同的包中,但是在IBookManager.aidl中仍然要导入Book类,这就是AIDL的特殊之处。

在gen目录下的com.myj.example.aidl包中有一个IBookManager.java的类,打开用于分析产生的Binder类。

//IBookManager.java
package com.myj.example.aidl

public interface IBookManager extends android.os.IIterface{

    public static abstract class Stub extends android.os.Binder implements com.myj.example.aidl.IBookManager{

    private static final java.lang.String DESCRIPTOR="com.myj.example.aidl.IBookManager";
    public Stub(){
        this.attachInterface(this,DESCRIPTOR);
    }

    public static com.myj.example.aidl.IBookManager asInterface(android.os.IBinder obj){
        if(obj==null){
            return null;
        }
        android.os.IInterface iin=obj.queryLocalInterface(DESCRITOR);
        if((iin != null) && (iin instanceof com.myj.example.IBookManager)){
            return ((com.myj.example.aidl.IBookManager)iin); 
        }
        return new com.myj.example.aidl.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(DESCROPTOR):
                return this;
            case TRANSACTION_getBookList():
                data.enforceInterface(DESCRIPTOR);
                java.util.List<com.myj.example.aidl.Book> _result=this.getBookList();
                reply.writeNoException();
                reply.writeTypedList(_result);
                return true;
            case TRANSACTION_addBook:
                data.enforceInterface(DESCRIPTOR);
                com.myj.example.aidl.Book _arg0;
                if(0 != data.readInt()){
                    _arg0=com.myj.example.aidl.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.myj.example.aidl.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 DESCROPTOR;
        }

        @Override
        public java.util.List<com.myj.example.aidl.Book> getBookList() throws android.os.RemoteException{
            android.os.Parcel _data=android.os.Parcel.obtain();
            android.os.Parcel _reply=android.os.Parcel.botain();
            java.util.List<com.myj.example.aidl.Book> _result;
            try{
                _data.writeInterfaceToken(DESCRIPTOR);
                mRemote.transact(Stub.TRANSACTIN_getBookList,_data,_reply,0);
            _reply.readException();
            _result=_reply.createTypedAArrayList(com.myj.example.aidl.Book.CREATOR);
            }finally{
                _reply.recycle();
                _data.recycle();
            }
            return _result;
        }

        @Override
        public void addBook(com.myj.example.aidl.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.myj.example.aidl.Book> getBookList() throws android.os.RemoteException;

    public void addBook(com.myj.example.aidl.Book book) throws android.os.RemoteException;

理解:这个类的结构很简单,首先,它声明了两个方法getBookList和addBook,显然这就是我们在IBookManager.aidl中所声明的方法,同时声明了两个整型的id分别用于标识这两个方法,用于标识在transact过程中客户端所请求的是哪个方法。

内部类Stub:是一个Binder类,当客户端和服务端都位于同一个进程时,方法调用不会走跨进程的transact过程;当两者位于不同进程时,方法调用需要走transact过程,这个逻辑由内部代理类Proxy来完成。由此可见,这个接口的核心是内部类Stub和Stub的内部代理类Proxy。

下面理解一下它的内部方法:

DESCRIPTOR

Binder的唯一标识,一般用当前Binder的类名表示,比如本例中的"com.myj.example.aidl.IBookManager"

asInterface(android.os.IBinder obj)

未完,待补充。。。

猜你喜欢

转载自blog.csdn.net/weixin_38664232/article/details/84531497