Link:

IPC__ALL

前言

  • Binder 是 Android中的一个类,它实现了 IBinder接口。从IPC角度说,Binder 是Android中的一种跨进程通信的方式。
  • 从Android Framework角度来说,Binder是ServiceManager连接各种Manager(ActivityManager、WindowManager,etc)和相应ManagerService的桥梁。
  • 从Android应用层来说,Binder是客户端和服务端进行通信的媒介,当你bindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务。

AIDL 支持的数据类型

  1. 基本数据类型
    int、long、char、boolean、double 等
  2. String 和 CharSequence
  • List:
    只支持ArrayList,里面的每一个元素都必须能够被 AIDL 支持
  • Map:
    只支持 HashMap,里面的每一个元素都必须能够被 AIDL 支持
  • Parcelable:
    所有实现了 Parcelable 接口的对象
  • AIDL:
    所有的 AIDL 接口本身也可以在 AIDL文件中使用。

Binder 通信示意图

Binder 的工作机制

跨进程通信的接口, AIDL的包名需要与项目的包名相同, 默认生成即可.

Binder 工作原理分析

可以查看我的相关文章 代理模式
示例:

1. 添加AIDL文件
  • Book.aidl
// Book.aidlpackage com.jack.jack_aidl_demo;// Declare any non-default types here with import statementsimport com.jack.jack_aidl_demo.Book;//Book 类在 AIDL 中的声明parcelable Book;
  • IBookManager.aidl
// IBookManager.aidlpackage com.jack.jack_aidl_demo;// Declare any non-default types here with import statementsimport com.jack.jack_aidl_demo.Book;interface IBookManager {    /**     * Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     */    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,            double aDouble, String aString);    List getBookList();    void addBook(in Book b);}
Paste_Image.png

这样IDE 就能在:
C:\myWidget\temp\Jack_Aidl_demo\app\build\generated\source\aidl\debug\com\jack\jack_aidl_demo\下生成 IBookManager.java,我们看一下,注释非常详细!

注意

如果AIDL文件中用到了自定义的 Parcelable 对象,那么必须新建一个和它同名的AIDL文件,并在其中声明它为 Parcelable 类型。在上面的
IBookManager.aidl 中,我们用到了Book类,所以必须创建 Book.aidl,然后在里面添加内容。

/* * This file is auto-generated.  DO NOT MODIFY. * Original file: C:\\myWidget\\temp\\Jack_Aidl_demo\\app\\src\\main\\aidl\\com\\jack\\jack_aidl_demo\\IBookManager.aidl */package com.jack.jack_aidl_demo;//代理模式——相当于抽象主题类public interface IBookManager extends android.os.IInterface {    /**     * Local-side IPC implementation stub class.     * 代理模式——相当于真实主题类(这边是个抽象类,要服务端完成它的功能,服务端完成类才是真正的真实主题)     */    public static abstract class Stub extends android.os.Binder implements com.jack.jack_aidl_demo.IBookManager {        private static final java.lang.String DESCRIPTOR = "com.jack.jack_aidl_demo.IBookManager";        /**         * Construct the stub at attach it to the interface.         */        public Stub() {            this.attachInterface(this, DESCRIPTOR);        }        /**         * Cast an IBinder object into an com.jack.jack_aidl_demo.IBookManager interface,         * generating a proxy if needed.         * 用于将服务器 Binder 对象转化为客户端所需的 AIDL 接口类型对象         */        public static com.jack.jack_aidl_demo.IBookManager asInterface(android.os.IBinder obj) {            if ((obj == null)) {                return null;            }            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);            if (((iin != null) && (iin instanceof com.jack.jack_aidl_demo.IBookManager))) {                //1. 客户端与服务器位于同一进程,返回服务器的Stub对象本身                return ((com.jack.jack_aidl_demo.IBookManager) iin);            }                //2. 客户端与服务器位于不同一进程,返回系统封装的Stub.Proxy 对象            return new com.jack.jack_aidl_demo.IBookManager.Stub.Proxy(obj);        }        //返回当前 Binder 对象        @Override        public android.os.IBinder asBinder() {            return this;        }        /**         * 运行在服务器的Binder线程池中,当客户端发起跨进程请求时,远程请求会通过系统底层封装交由此方法处理。         * 1.code确定客户端请求的方法是什么         * 2.data取出目标方法所需参数,如果需要,然后执行目标方法。         * 3.目标方法执行完,向reply中写入返回值。         * 4.方法的返回值 true代表请求成功,false代表请求失败,可以用来权限认证         */        @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_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;                }                case TRANSACTION_getBookList: {                    data.enforceInterface(DESCRIPTOR);                    java.util.List _result = this.getBookList();                    reply.writeNoException();                    reply.writeTypedList(_result);                    return true;                }                case TRANSACTION_addBook: {                    data.enforceInterface(DESCRIPTOR);                    com.jack.jack_aidl_demo.Book _arg0;                    if ((0 != data.readInt())) {                        _arg0 = com.jack.jack_aidl_demo.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.jack.jack_aidl_demo.IBookManager {            private android.os.IBinder mRemote;            /**             * 代理模式——真实主题传入             * @param remote             */            Proxy(android.os.IBinder remote) {                mRemote = remote;            }            @Override            public android.os.IBinder asBinder() {                return mRemote;            }            public java.lang.String getInterfaceDescriptor() {                return DESCRIPTOR;            }            /**             * 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();                }            }            /**             * 运行在客户端             * @return             * @throws android.os.RemoteException             */            @Override            public java.util.List getBookList() throws android.os.RemoteException {                //输入型对象                android.os.Parcel _data = android.os.Parcel.obtain();                //输出型对象                android.os.Parcel _reply = android.os.Parcel.obtain();                //返回值对象                java.util.List _result;                try {                    _data.writeInterfaceToken(DESCRIPTOR);                    //发起RPC(远程调用),客户端线程挂起,不应该在ui线程调用                    mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);                    _reply.readException();                    //从输出型对象取出返回值                    _result = _reply.createTypedArrayList(com.jack.jack_aidl_demo.Book.CREATOR);                } finally {                    _reply.recycle();                    _data.recycle();                }                return _result;            }            @Override            public void addBook(com.jack.jack_aidl_demo.Book b) 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 ((b != null)) {                        _data.writeInt(1);                        b.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_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);        static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);        static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);    }    /**     * 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;    public java.util.List getBookList() throws android.os.RemoteException;    public void addBook(com.jack.jack_aidl_demo.Book b) throws android.os.RemoteException;}


当客户端远程调用
这样我们应该对Binder机制了解了!

注意点

  • 当客户端发起远程请求时,由于当前线程会被挂起直至服务器进程返回,所以如果一个远程方法是很耗时的,那么不能再UI线程中发起此远程请求。
  • 由于服务器的 Binder 方法运行在 Binder线程池中,所以 Binder方法不管是否耗时都应该采用同步的方式去实现,因为它已经运行在一个线程中了。

示例地址

请戳我的github:Jack_Aidl_demo

参考资料:

  • 任玉刚的 Android Binder机制浅析,和 《Android 开发艺术探索》。

更多相关文章

  1. android调用java的web service接口
  2. Android在线更新版本(服务端+客户端Code)
  3. Android(安卓)WebView中无法用JS调用Java对象的问题
  4. Android学习笔记:通过Android之Service实现文件断点续传下载
  5. Android(安卓)异步任务 设置 超时使用handler更新通知功能
  6. [Android]网络资源下载时断点续传的实现
  7. Android(安卓)Studio创建Serializable对象时自动生成serialVersi
  8. Android(安卓)ANR问题定位
  9. Android资源加载机制

随机推荐

  1. Android(安卓)解决AIDL bindService异常
  2. Android(安卓)节点进度条
  3. android 用tcpdump抓取网络包
  4. android知识点积累
  5. ConstraintLayout 学习
  6. android中的滚动条ScrollView
  7. ClipboardManager android剪切板使用
  8. Android(安卓)聊天界面软件盘处理
  9. 2013.04.16——— android 获取状态栏高
  10. Android之复选框对话框