android IPC机制(二)

Binder对象

是android中的一个类,实现了IBinder接口,是一种android中实现跨进程通信的一种方式,可以ManagerService连接各种Manager(LayoutManager,ServiceManager,ActivityManager,SensorManager等等)和各种相应ManagerService的桥梁。

AIDL文件之自动生成的java文件

每次书写aidl文件之后,系统会自动生成相应的java文件,比如本人自己写的一个aidl文件:

// IBookManager.aidl
package micro.com.chapter2.inter.aidl;

// Declare any non-default types here with import statements
import micro.com.chapter2.inter.aidl.Book ;
import micro.com.chapter2.inter.aidl.Person ;
import micro.com.chapter2.inter.aidl.INewBookArriveListener ;

interface IBookManager {

     List<Book> getBooks();

     void addBook(in Book book) ;

     void addPerson(in Person p);
}

系统自动生成的IBookManager.java文件是:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 */
package micro.com.chapter2.inter.aidl;

public interface IBookManager extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements micro.com.chapter2.inter.aidl.IBookManager {
        private static final java.lang.String DESCRIPTOR = "micro.com.chapter2.inter.aidl.IBookManager";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an micro.com.chapter2.inter.aidl.IBookManager interface,
         * generating a proxy if needed.
         */
        public static micro.com.chapter2.inter.aidl.IBookManager asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof micro.com.chapter2.inter.aidl.IBookManager))) {
                return ((micro.com.chapter2.inter.aidl.IBookManager) iin);
            }
            return new micro.com.chapter2.inter.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(DESCRIPTOR);
                    return true;
                case TRANSACTION_getBooks: {
                    data.enforceInterface(DESCRIPTOR);
                    java.util.List<micro.com.chapter2.inter.aidl.Book> _result = this.getBooks();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
                case TRANSACTION_addBook: {
                    data.enforceInterface(DESCRIPTOR);
                    micro.com.chapter2.inter.aidl.Book _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = micro.com.chapter2.inter.aidl.Book.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addBook(_arg0);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_addPerson: {
                    data.enforceInterface(DESCRIPTOR);
                    micro.com.chapter2.inter.aidl.Person _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = micro.com.chapter2.inter.aidl.Person.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addPerson(_arg0);
                    reply.writeNoException();
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements micro.com.chapter2.inter.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 DESCRIPTOR;
            }

           
            @Override
            public java.util.List<micro.com.chapter2.inter.aidl.Book> getBooks() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<micro.com.chapter2.inter.aidl.Book> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getBooks, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(micro.com.chapter2.inter.aidl.Book.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public void addBook(micro.com.chapter2.inter.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();
                }
            }

            @Override
            public void addPerson(micro.com.chapter2.inter.aidl.Person p) 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 ((p != null)) {
                        _data.writeInt(1);
                        p.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }
        static final int TRANSACTION_getBooks = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
        static final int TRANSACTION_addPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
       
    public java.util.List<micro.com.chapter2.inter.aidl.Book> getBooks() throws android.os.RemoteException;

    public void addBook(micro.com.chapter2.inter.aidl.Book book) throws android.os.RemoteException;

    public void addPerson(micro.com.chapter2.inter.aidl.Person p) throws android.os.RemoteException;
}

其中重要属性和方法说明如下:
1.DESCRIPTOR:
Binder中唯一的标识,自动生成时用当前Binder类名表示。

static final int TRANSACTION_getBooks = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_addPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);

三个声明的整型的id用于标识在transact过程中客户端中请求的到底是哪个方法。

2.asInterface(android.os.IBinder object)
将服务端的Binder对象转换成客户端所需AIDL接口类型的对象,转换是区分进程的,客户端和服务器在同一进程中,返回的是服务端Stub本身,否则就返回系统封装后的Stub.proxy对象。

3.asBinder
返回当前的Binder对象

4.onTransact
本方法运行在服务器端中Binder线程池中,客户端发起跨进程请求时,远程请求会通过系统底层封装后交给此方法来处理:

public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException 

通过code确定客户端方法的方法,然后从data中取得参数(如果存在参数的话),然后执行在服务端的目标方法,执行完成之后,向reply中写入返回值(如果客户端中需要返回值的话)。当然onTransact方法是有返回值的,如果返回false,那么客户端就会请求失败。

5.Proxy#getBookList
在客户端中运行,当客户端远程调用此方法时,内部实现方法如下:先创建所需的输入型Parcel对象_data,输出型Parcel对象 _replay和返回值对象List。先将需求参数写入_data中,接着调用transact方法发起远程调用(RPC)请求,同时当前线程会挂起,然后服务端的onTransact方法会被调用,当RPC方法结束返回后,当前线程从挂起状态变成重新运行状态,并从_reply中取出RPC过程的返回结果,最后返回 _reply中的数据。 基本图解如下:

这里写图片描述

linkToDeath & unlinkToDeath

Binder运行在服务端进程,如果服务进程由于某种原因异常终止,此时服务端的Binder链接断裂(Binder死亡),会导致我们的远程调用失败。更为关键的是,不知道Binder链接断裂,那么客户端的功能就会受影响。为了解决这个问题,Binder中提供了两个配对的方法lineToDeath和unlinkToDeath,通过linktoDeath可以Binder设置死亡代理,Binder死亡时会受到死亡通知,此时可以重新发起连接请求从而恢复链接。

private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            Log.d(TAG,"binder died...");
            //unlinkToDeath
            xxx.unlinkToDeath(mBinderPoolDeathRecipient,0);
            //restart server or rebinding ServiceConnection
        }
    } ;

在客户端绑定远程服务成功后,给binder设置死亡代理:

private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            try {
               //linktoDeath
                xxx.linkToDeath(mBinderPoolDeathRecipient,0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {}
    } ;

基本上通过以上两个步骤,就会给我们的Binder设置死亡代理,当Binder死亡的时候就会受到相应的通知了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值