Binder是Android的一个类,它实现了IBinder接口。从IPC角度来说,Binder是Android中一种跨进程通信方式,还可以理解为是一种物理设备,它的设备驱动是 /dev/binder ;从Android Framework角度来说,Binder是ServiceManager连接各种Manager(ActivityManager、WindowManager,等等)和相应ManagerService的桥梁;从Android应用层来说,Binder是客户端和服务端进行通信的媒介,当bindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,通过这个Binder对象,客户端就可以获得服务器提供的服务或数据,这里的服务包括普通服务和基于 AIDL 的服务。 Android 开发中,Binder主要用在Service中,包括AIDL和Message,Message的底层其实就是AIDL.

/* * This file is auto-generated. DO NOT MODIFY. * Original file: /Users/mac/AndroidStudioProjects/ProcessDemo/app/src/main/aidl/com/example/mac/processdemo/bean/IBookManager.aidl */package com.example.mac.processdemo.bean;// Declare any non-default types here with import statementspublic interface IBookManager extends android.os.IInterface {    /** * Local-side IPC implementation stub class. */    public static abstract class Stub extends android.os.Binder implements com.example.mac.processdemo.bean.IBookManager {        private static final java.lang.String DESCRIPTOR = "com.example.mac.processdemo.bean.IBookManager";        /** * Construct the stub at attach it to the interface. */        public Stub() {            this.attachInterface(this, DESCRIPTOR);        }        /** * Cast an IBinder object into an com.example.mac.processdemo.bean.IBookManager interface, * generating a proxy if needed. */        public static com.example.mac.processdemo.bean.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.mac.processdemo.bean.IBookManager))) {                return ((com.example.mac.processdemo.bean.IBookManager) iin);            }            return new com.example.mac.processdemo.bean.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.mac.processdemo.bean.Book> _result = this.getBookList();                    reply.writeNoException();                    reply.writeTypedList(_result);                    return true;                }                case TRANSACTION_addBook: {                    data.enforceInterface(DESCRIPTOR);                    com.example.mac.processdemo.bean.Book _arg0;                    if ((0 != data.readInt())) {                        _arg0 = com.example.mac.processdemo.bean.Book.CREATOR.createFromParcel(data);                    } else {                        _arg0 = null;                    }                    this.addBook(_arg0);                    reply.writeNoException();                    return true;                }                case TRANSACTION_basicTypes: {                    data.enforceInterface(DESCRIPTOR);                    int _arg0;                    _arg0 = data.readInt();                    long _arg1;                    _arg1 = data.readLong();                    boolean _arg2;                    _arg2 = (0 != data.readInt());                    float _arg3;                    _arg3 = data.readFloat();                    double _arg4;                    _arg4 = data.readDouble();                    java.lang.String _arg5;                    _arg5 = data.readString();                    this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);                    reply.writeNoException();                    return true;                }            }            return super.onTransact(code, data, reply, flags);        }        private static class Proxy implements com.example.mac.processdemo.bean.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.mac.processdemo.bean.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.mac.processdemo.bean.Book> _result;                try {                    _data.writeInterfaceToken(DESCRIPTOR);                    mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);                    _reply.readException();                    _result = _reply.createTypedArrayList(com.example.mac.processdemo.bean.Book.CREATOR);                } finally {                    _reply.recycle();                    _data.recycle();                }                return _result;            }            @Override            public void addBook(com.example.mac.processdemo.bean.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();                }            }            /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */            @Override            public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException {                android.os.Parcel _data = android.os.Parcel.obtain();                android.os.Parcel _reply = android.os.Parcel.obtain();                try {                    _data.writeInterfaceToken(DESCRIPTOR);                    _data.writeInt(anInt);                    _data.writeLong(aLong);                    _data.writeInt(((aBoolean) ? (1) : (0)));                    _data.writeFloat(aFloat);                    _data.writeDouble(aDouble);                    _data.writeString(aString);                    mRemote.transact(Stub.TRANSACTION_basicTypes, _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);        static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);    }    public java.util.List<com.example.mac.processdemo.bean.Book> getBookList() throws android.os.RemoteException;    public void addBook(com.example.mac.processdemo.bean.Book book) throws android.os.RemoteException;    /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;}

上面是系统生成的 .aidl 对应的 java 类,这个类是继承了IInterface的接口,在Binder中传输的接口都需要继承IInterface接口。看一下它的结构,首先它声明了在IBookManager.aidl中定义的两个方法 getBookList 和 addBook,同时它还定义了两个整形的id分别用于标记这两个方法,这两个id用于标识在transact 过程中客户端所请求的到底是哪个方法。接着,它声明了一个内部类Stub,这个Stub就是一个Binder类,当客户端和服务端都处于同一个进程时,方法调用不会走跨进程的transact过程,当两者位于不同进程时,方法调用会走transact过程,这个逻辑由Stub的内部代理类Proxy来完成。

下面详细介绍这两个类和方法:

DESCRIPTOR

Binder的唯一标识,一般用当前类名标识。

asInterface(android.os.IBinder obj)

用于将服务端的Binder对象转换成客户端所需的AIDL接口类型的对象,这种转换过程是区分进程的,如果客户端和服务端位于同一进程,那么此方法返回的就是服务端的Stub对象本身,否则返回的是系统封装后后的Stub.proxy对象。

asBinder

此方法用于返回当前 Binder 对象。

onTransact

这个方法运行在服务端的Binder线程池中,当客户端发起跨进程请求时,远程请求会通过系统底层封装后交由此方法来处理。

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

服务端通过code可以确定客户端请求的目标方法是什么,接着从data中取出目标方法所需的参数,然后执行目标方法。当目标方法执行完毕后,就向reply中写入返回值,onTransact方法执行结束。注意:如果此方法返回false,那么客户端的请求会失败,可以利用这个特性来做权限验证。

Proxy#getBookList

这个方法运行在客户端,当客户端远程调用这个方法时,首先创建该方法所需要的输入型Parcel对象_data、输出型Parcel对象_reply对象和返回值对象List;然后把该方法的参数写入_data中;接着调用transact方法来发起RPC(远程过程调用)请求,同时当前线程挂起;然后服务端的onTransact方法会被调用,直到RPC过程返回后,当前线程继续执行,并从_replay中取出RPC过程的返回结果;最后返回_reply中的数据。

Proxy#addBook

这个方法运行在客户端,它的运行过程和getBookList是一样的,只是没有返回值。

注意:

(1)客户端发起远程请求时,由于当前线程会被挂起直至服务端进程返回数据,耗时操作不能在UI线程中发起远程请求;
(2)由于服务端的Binder方法运行在Binder的线程池中,所以Binder方法不管是否耗时都应该采用同步的方式实现,因为它已经运行在一个线程中了。

linkToDeath 和 unlinkToDeath 方法

Binder运行在服务端进程,如果服务端由于某种原因异常终止,Binder连接断裂(称之为Binder死亡),会导致我们远程调用失败,通过 linkToDeath 可以给Binder设置一个死亡代理,当Binder死亡时,就会收到通知,这个时候可以重新发起连接请求从而恢复连接。

给Binder设置死亡代理

首先声明一个DeathRecipient对象。DeathPecipient是一个借口,其内部只有一个方法 binderDied,需要实现这个方法,当Binder死亡的时候,系统会回调binderDied方法,然后就可以移除之前绑定的binder代理并重新绑定远程服务:

 private IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {        @Override        public void binderDied() {            if (mBookManager == null)                return;            mBookManager.asBinder().unlinkToDeath(deathRecipient,0);            mBookManager = null;            //TODO :这里重新绑定远程服务        }    };

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

mService = IMessageBoxManager.Stub.asInterface(binder);binder.linkToDeath(deathRecipient, 0);

通过上面两个步骤,就给binder设置了死亡代理,当Binder死亡的时候就可以收到通知,通过Binder的方法 isBinderAlive 也可以判断Binder是否死亡。

更多相关文章

  1. Android(安卓)JNI编程内存问题定位方法
  2. Android(安卓)之 ContentProvider 共享数据库-通讯录
  3. Android中onConfigurationChanged监视系统配置更新
  4. Android(安卓)自定义View 使用VelocityTracker记录滑动速度
  5. android中处理json最佳方法
  6. Android(安卓)浅谈相机研发
  7. Android(安卓)对话框(Dialog)【大全】
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. android上加载大图片需要注意的问题
  2. android 4.3 操作源码实现系统截屏(暂无移
  3. bt开发类
  4. Android(安卓)XML设置圆角边框
  5. Android疑问1——Handler的removeCallbac
  6. Android的JS调用Java代码或使用了Javascr
  7. Android(安卓)几种弹框样式 自定义Dialog
  8. android仿ios开关按钮
  9. Android开发_字符串处理类-TextUtils类
  10. Android(安卓)本地文件、文件夹操作