我是靠谱客的博主 哭泣金毛,最近开发中收集的这篇文章主要介绍Android进程通信之AIDL的使用与Binder浅谈,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、AIDL简介

AIDL是Android接口定义语言,有点类似于我们开发中的普通接口。由于不同进程间不能共享内存,为了解决进程间通信的问题,可以通过AIDL接口语言来实现进程间的通信。

二、AIDL文件支持的数据类型

  • 基本数据类型(int、long、char、boolean、double)
  • String和CharSequence
  • List和Map集合
  • 集合内元素必须是AIDL支持的数据类型
  • 服务端具体使用的集合必须是ArrayList和HashMap
  • Parcelable:实现了Parcelable接口的对象
  • AIDL本身接口也可以在AIDl文件使用。

三、AIDL使用步骤

主要有三大步骤

  1. 创建AIDL
    (1)创建实例类,必须实现Parcelable接口,用于序列化和反序列化
    (2)新建aidl文件夹,在其创建与实例类同名的aidl文件及其他aidl接口文件
    (3)rebuild项目,生成Binder的java接口文件。
  2. 创建服务端(Service)
    (1)创建Service,在onBind方法中返回Binder实例对象,并实现aidl接口方法。
  3. 编写客服端(Activity或其他)
    (1)使用bindService方式启动服务,实现ServiceConnection接口,拿到aidl生成的Binder对象。
    (2)调用aidl定义好的函数方法。

四、AIDL具体实现

为了方便AIDL的开发,建议所有和AIDL相关的类和文件全部放在同一个包,这样方便其他地方需要使用,可以直接复制过去。
下面是具体例子的文件目录:
在这里插入图片描述
注意:

aidl文件目录是和java目录同级的

1、创建AIDL
1.1、创建进程间需要传输的实体类,实现 Parcelable 接口
public class Book implements Parcelable{

    private String bookName;

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

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.bookName);
    }

    protected Book(Parcel in) {
        this.bookName = in.readString();
    }

    public static final Creator<Book> CREATOR = new Creator<Book>() {
        @Override
        public Book createFromParcel(Parcel source) {
            return new Book(source);
        }

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

    @Override
    public String toString() {
        return "Book{" +
                "bookName='" + bookName + ''' +
                '}';
    }
}

实现 Parcelable 接口是为了实例类能够在进程间通信。
其实进程间通信是一个序列化和反序列化的过程,关于序列化可以参考这篇文章Android进程通信之文件共享(序列化Serialzable与Parcelable)

1.2、新建aidl文件夹,在其创建与实例类同名的aidl文件及其他aidl接口文件
  • 新建aidl文件夹,主要aidl目录和java目录是同级的,在main目录下面。
    在这里插入图片描述
  • 创建与实体类(Book)同名的aidl文件:Book.aidl
// Book.aidl 
package com.hzw.progress.aidl;

//声明Book实体类已序列化,可用于进程间传输
parcelable Book;

这样做的目的是让aidl文件知道Book类实现了Parcelable接口,可将Book对象作为进程间传输数据的载体。

注意:

Book实体类和Book.aidl文件必须要在相同包结构目录下,否则会运行出错,是因为客服端需要反序列化服务端的AIDL接口相关的类,如果类的路径不一样的话,客户端会反序列失败。

IBookManager.aidl接口

// IBookManager.aidl
package com.hzw.progress.aidl;

// Declare any non-default types here with import statements
//虽然在IBookManager.aidl和Book.aidl同一个包名下,但必须以import方式将Book.aial文件导入(手动导入)
import com.hzw.progress.aidl.Book;

import com.hzw.progress.aidl.OnNewBookAddListener;

//定义客户端与服务端间的回调接口
interface IBookManager {

    //得到全部数据(全部书籍)
    List<Book> getBookList();
    //添加数据的操作(添加书籍)
    void addBook(in Book book);
    //注册监听,用于监听新数据的变化。是典型的观察者模式的运用
    void registerListener(OnNewBookAddListener listener);
    //解注册
    void unregisterListener(OnNewBookAddListener listener);
}

OnNewBookAddListener.aidl接口文件

// OnNewBookAddListener.aidl
package com.hzw.progress.aidl;

import com.hzw.progress.aidl.Book;


// Declare any non-default types here with import statements

//定义监听新数据变化的接口(添加新书籍)
interface OnNewBookAddListener {

    void onNewBookAdd(in Book book);

    void onAllBook();
}

以上需要注意的点,在addBook和onNewBookAdd方法接参中有个in,表示输入型参数。AIDL 中除了基本数据类型,其他数据类型必须标上方向,in,out 或者 inout。

  • in 表示输入型参数
  • out 表示输出型参数
  • inout 表示输入输出型参数
1.3 在创建好了aidl文件后,需要 rebuild项目,生成Binder的java接口文件。
2、创建服务端
2.1、创建服务端BookManagerService继承于Service
public class BookManagerService extends Service {

    private static final String TAG = "BookManagerService";
    private List<Book> mBookList=new ArrayList<>();
    private static List<OnNewBookAddListener> mAddListenerList=new ArrayList<>();

    public BookManagerService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        //初始化书籍
        mBookList.add(new Book("Android群英传"));
        mBookList.add(new Book("Android开发艺术探索"));

    }

    @Override
    public IBinder onBind(Intent intent) {
        //获取Service需要的权限,进行自我验证,防止其他进程访问该服务
       int check= checkCallingOrSelfPermission("com.hzw.progress.aidl.permission.LOCAL");
       //未授权该应用,则无法访问
       if (check== PackageManager.PERMISSION_DENIED){
           return null;
       }
       //添加新书的过程
        BookFactory factory = new BookFactory();
        factory.execute(5); //添加五本书
        return mBinder;
    }

    /*
    * 初次new IBookManager方式构建Binder对象,会报错找不到IBookManager对象
    * 需要Rebuild下项目
    * */
    private Binder mBinder=new IBookManager.Stub() {

        @Override
        public List<Book> getBookList() throws RemoteException {
            return mBookList;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
            mBookList.add(book);
        }

        @Override
        public void registerListener(OnNewBookAddListener listener) throws RemoteException {
            if (!mAddListenerList.contains(listener)){
                mAddListenerList.add(listener);
            }
            Log.i(TAG, "registerListener: "+mAddListenerList.size());
        }

        @Override
        public void unregisterListener(OnNewBookAddListener listener) throws RemoteException {
            if (mAddListenerList.contains(listener)){
                mAddListenerList.remove(listener);
            }
        }
    };

    /**
     * 使用静态内部类,避免泄漏
     */
    private static   class BookFactory extends AsyncTask<Integer,Book,Book>{

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Book doInBackground(Integer... integers) {
            //每隔2秒添加新建一本新书,最多只能添加5本
            int i=0;
            Book mBook=null;
            while (i< integers[0]){
                mBook=new Book("新书"+(i+1));
                try {
                    Thread.sleep(2000);
                    publishProgress(mBook);
                    i++;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }

            return mBook;
        }

        @Override
        protected void onProgressUpdate(Book... values) {
            super.onProgressUpdate(values);
            //监听每次添加数据内容
            for (int i = 0; i <mAddListenerList.size() ; i++) {
                OnNewBookAddListener listener = mAddListenerList.get(i);
                try {
                    if (listener!=null){
                        listener.onNewBookAdd(values[0]);
                    }
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        protected void onPostExecute(Book book) {
            super.onPostExecute(book);
            //得到全部的书籍
            for (int i = 0; i <mAddListenerList.size() ; i++) {
                OnNewBookAddListener listener = mAddListenerList.get(i);
                try {
                    if (listener!=null){
                        listener.onAllBook();
                    }
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

服务端是Service的典型实现,具体使用可以参考这篇文章Service实例深入理解,以上需要注意的点:

  • 在onBind方法中,最好添加访问权限的判断,防止一些恶意的访问,可使用 Permission 验证,在 manifest 中声明。
  • 创建Binder 对象时,不能使用new Binder ()的方式,必须使用new IBookManager.Stub()创建Binder对象,这是AIDL接口文件自动生成的Binder对象。

最后需要在Mainfest文件中注册Service,同时自定义定义服务端的访问权限并引用。

 <!--自定义访问Service的权限-->
    <permission android:name="com.hzw.progress.aidl.permission.LOCAL"/>
    <!--声明本拥有该权限-->
    <uses-permission android:name="com.hzw.progress.aidl.permission.LOCAL"/>

 <service
            android:name=".aidl.BookManagerService"
            android:enabled="true"
            android:exported="true"
            android:process=":remote"
            android:permission="com.hzw.progress.aidl.permission.LOCAL">
        </service>

注意:

BookManagerService要在独立进程中需要,必须定义属性 android:process=”:remote”

3、编写客服端

绑定远程服务后,通过ServiceConnection得到代理对象Binder,同时将Binder对象转换成AIDL接口,然后通过AIDL接口去调用服务端的方法。

public class AIDLActivity extends AppCompatActivity {
    private static final String TAG = "AIDLActivity";
    private Intent mIntent;
    private IBookManager mIBookManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_aidl);
        mIntent = new Intent(this, BookManagerService.class);
    }

    public void onClick(View view) {

        switch (view.getId()){
            case R.id.bindService:
                //绑定服务
                bindService(mIntent,mConnection,BIND_AUTO_CREATE);
                break;
            case R.id.unbindService:
                //解绑服务
                unbindService(mConnection);
                break;
        }
    }

    private ServiceConnection mConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            try {
                //ClassCastException
//                IBookManager iBookManager=(IBookManager)service;
                mIBookManager = IBookManager.Stub.asInterface(service);
                mIBookManager.addBook(new Book("Android进阶之光"));
                List<Book> bookList = mIBookManager.getBookList();
//                Log.i(TAG, "全部书籍: "+bookList.toString());
                mIBookManager.registerListener(sListener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mConnection);
        try {
            mIBookManager.unregisterListener(sListener);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    private  OnNewBookAddListener sListener=new OnNewBookAddListener.Stub() {
        @Override
        public void onNewBookAdd(Book book) throws RemoteException {
            mIBookManager.addBook(book);
            Log.i(TAG, "onNewBookAdd: "+book.toString());
        }

        @Override
        public void onAllBook() throws RemoteException {
            List<Book> bookList = mIBookManager.getBookList();
            Log.i(TAG, "onAllBook: "+bookList.toString());
        }
    };

}

以上就是客户端的基本实现,需要注意一下几点:

  • 在得到代理对象Binder时,不能直接使用强转的方式,否则会报类型转换异常,必须使用IBookManager.Stub.asInterface()得到AIDL接口文件生成的Binder对象。
  • 在需得到一个AIDl接口实例对象,需要.Stub()方法得到实例。

以上三大步骤就是AIDL实现进程通信的简单例子,运行结果如下:

07-14 17:59:47.974 6970-6988/com.hzw.progress I/AIDLActivity: onNewBookAdd: Book{bookName='新书1'}
07-14 17:59:49.974 6970-6989/com.hzw.progress I/AIDLActivity: onNewBookAdd: Book{bookName='新书2'}
07-14 17:59:51.974 6970-6988/com.hzw.progress I/AIDLActivity: onNewBookAdd: Book{bookName='新书3'}
07-14 17:59:53.975 6970-6989/com.hzw.progress I/AIDLActivity: onNewBookAdd: Book{bookName='新书4'}
07-14 17:59:55.976 6970-6988/com.hzw.progress I/AIDLActivity: onNewBookAdd: Book{bookName='新书5'}
07-14 17:59:55.977 6970-6989/com.hzw.progress I/AIDLActivity: onAllBook: [Book{bookName='Android群英传'},
 Book{bookName='Android开发艺术探索'}, Book{bookName='Android进阶之光'}, Book{bookName='新书1'}, 
 Book{bookName='新书2'}, Book{bookName='新书3'}, Book{bookName='新书4'}, Book{bookName='新书5'}]

五、AIDL使用注意点:

  • AIDL接口文件的包结构必须与实体类的同结构,否则会反序列化失败
  • 与实体类同名的AIDL接口文件,必须使用parcelable声明Book类已序列化,注意全是小写
  • 在一个AIDL文件中使用另外一个AIDL文件时,需手工显式(全包名)导入。

以上任何一个点不小心搞错的话,AIDL就无法实现进程通信。

六、AIDL使用解析

上面的例子基本实现了AIDL进程间的通信,其中还存在很多疑问,比如:

  1. AIDL 在实现通信过程中具体做哪些内容?
  2. 服务端创建Binder对象或者得到AIDL接口对象,都在调用Stub()方法实现,那么该方法具体有哪些操作?
  3. 什么是Binder?

其实上面这三点可以统称理解为AIDL本质是什么;下面重点对AIDL文件生成的java文件进行解析,在创建了AIDL文件后SDK会自动生成对应的Binder类,可以简单理解为AIDL是一种实现Binder的工具。

  • 从接口层面,Binder是Android中的一个类,它实现了IBinder接口
  • 从应用层面,Binder是客户端和服务端进行通信的中间代理,当bindService后,服务端会返回一个代理对象Binder,通过其可以获取服务端的数据。
  • 从IPC层面,Binder是Android中的一种跨进程通信方式
  • 从底层角度,Binder是连接各种Manager(ActivityManager、WindowManager等)的桥梁
  • 从物理层面,Binder是一种虚拟的物理设备,有自己的驱动设备。

七、AIDL原理

在上篇的例子中我们创建了两个aidl文件,分别是IBookManager.aidl、OnNewBookAddListener.aidl文件,在rebuild编译项目后,会自动生成对应的java文件,如下:
在这里插入图片描述
打开对应的java文件,下面以IBookManager.java为例

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: F:\StudyAndroid\progress\src\main\aidl\com\hzw\progress\aidl\IBookManager.aidl
 */
package com.hzw.progress.aidl;


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

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

        /**
         * Cast an IBinder object into an com.hzw.progress.aidl.IBookManager interface,
         * generating a proxy if needed.
         */
        public static com.hzw.progress.aidl.IBookManager asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.hzw.progress.aidl.IBookManager))) {
                return ((com.hzw.progress.aidl.IBookManager) iin);
            }
            return new com.hzw.progress.aidl.IBookManager.Stub.Proxy(obj);
        }

     private static class Proxy implements com.hzw.progress.aidl.IBookManager {

       *********************省略********************

        }
    }

    public java.util.List<com.hzw.progress.aidl.Book> getBookList() throws android.os.RemoteException;


    public void addBook(com.hzw.progress.aidl.Book book) throws android.os.RemoteException;


    public void registerListener(com.hzw.progress.aidl.OnNewBookAddListener listener) throws android.os.RemoteException;

    public void unregisterListener(com.hzw.progress.aidl.OnNewBookAddListener listener) throws android.os.RemoteException;
}

以上的代码很多,我们可以通过类的树形结构图大体知道AIDL文件生成java文件的基本信息及内容:
在这里插入图片描述

  • IBookManager.java这个类是一个接口,继承于IInterface这个接口
  • 接着声明了一个内部类Stub,而这个Stub是继承于Binder,就是一个Binder对象;同时实现了IBookManager本身的实例。
  • 同时也声明了在aidl文件定义的四个方法,分别是:getBookList、addBook、registerListener、unregisterListener

从整个代码结构可以看出,IBookManager类的具体功能在内部类Stub实现的,接下来就看看内部类Stub的逻辑,

public static abstract class Stub extends android.os.Binder implements com.hzw.progress.aidl.IBookManager {

        //Binder的唯一标识,一般是以当前Binder的类名表示
        private static final java.lang.String DESCRIPTOR = "com.hzw.progress.aidl.IBookManager";

        //将IBookManager接口关联到Binder对象中
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

       //将服务端的Binder对象转换成客户端需要的接口对象IBookManager。
        public static com.hzw.progress.aidl.IBookManager asInterface(android.os.IBinder obj) {
            //判断obj是否null,为null则说明客户端与服务端连接失败
            if ((obj == null)) {
                return null;
            }
            //通过标识查询obj对象是否有关联的接口
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            //不为null,说明服务端和客户端在同一个进程中,返回自身对象
            if (((iin != null) && (iin instanceof com.hzw.progress.aidl.IBookManager))) {
                return ((com.hzw.progress.aidl.IBookManager) iin);
            }
            //为null,则返回一个Binder的代理对象Proxy
            return new com.hzw.progress.aidl.IBookManager.Stub.Proxy(obj);
        }

Stub类是继承于Binder类,同时实现了IBookManager接口,定义了两个自身的函数分别是构造函数Stub和asInterface:

  • 通过构造函数 Stub()将IBookManager接口关联到Binder对象中,通过传入DESCRIPTOR 字段标识当前Binder对象,保证Binder对象的唯一性。
  • 通过asInterface函数将服务端的Binder对象转换成客户端需要的接口对象IBookManager,从而实现客户端与服务端的交互。
    在这里插入图片描述

asInterface方法有以下几个流程逻辑:

  • 首先会判断传入的binder对象是否为null,若为null,说明客户端和服务端没有建立连接。
  • 接着会拿着DESCRIPTOR 标识去查询binder对象是否有本地对应的接口(通过queryLocalInterface返回值判断)。
  • 最后根据queryLocalInterface返回值判断返回具体的AIDL接口对象,若返回值存在,则返回服务端对象本身Stub,若为null,则返回系统封装好的代理对象Stub.Proxy。

接下看看queryLocalInterface方法的源码

 /**
     * Attempt to retrieve a local implementation of an interface
     * for this Binder object.  If null is returned, you will need
     * to instantiate a proxy class to marshall calls through
     * the transact() method.
     */
    public IInterface queryLocalInterface(String descriptor);

从源码的注释可以知道一个大概,通过descriptor标识会先尝试获取本地的binder对象,所谓本地的是指客户端和服务端同属一个进程。如果返回值为null,则需要实例化一个代理对象。我们也可以通过测试来在不同进程queryLocalInterface具体返回情况

  private ServiceConnection mConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            try {
                mIBookManager = IBookManager.Stub.asInterface(service);
                IInterface queryLocalInterface = service.queryLocalInterface("com.hzw.progress.aidl.IBookManager");
                if (queryLocalInterface!=null){
                    //客户端与服务端同一个进程
                    Log.i(TAG, "queryLocalInterface 不为null");
                }else {
                    //不同进程
                    Log.i(TAG, "queryLocalInterface 为null");
                }
}

既然在不同进程时,asInterface会返回一个Stub.Proxy代理对象,就看看Proxy对象是怎么样的

  private static class Proxy implements com.hzw.progress.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<com.hzw.progress.aidl.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.hzw.progress.aidl.Book> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.hzw.progress.aidl.Book.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }


            @Override
            public void addBook(com.hzw.progress.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);
                    }
                    //执行远程Rcp请求,向服务端发送请求
                    mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            @Override
            public void registerListener(com.hzw.progress.aidl.OnNewBookAddListener listener) 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.writeStrongBinder((((listener != null)) ? (listener.asBinder()) : (null)));
                    mRemote.transact(Stub.TRANSACTION_registerListener, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            @Override
            public void unregisterListener(com.hzw.progress.aidl.OnNewBookAddListener listener) 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.writeStrongBinder((((listener != null)) ? (listener.asBinder()) : (null)));
                    mRemote.transact(Stub.TRANSACTION_unregisterListener, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }

Proxy 代理类同样也实现了IBookManager接口,同时也实现了IBookManager类中所有方法。代理类的方法是在客户端调用的,客户端可以通过代理Proxy对象调用相应的方法getBookList、addBook等等。内部实现大概流程如下:

  • 获取输入型Parcel包对象_data和输出型Parcel包对象_reply;
  • 如果方法传入的参数不为null,则将其参数信息写入_data对象中,其实是个对象序列化过程
  • 接着通过远程Binder对象调用transact方法来发送RPC(远程过程调用)请求,同时当前线程会被挂起;
  • 最后,服务端的onTransact会被调用,当服务端处理完请求后,会返回数据,当前线程继续执行知道返回 _result结果。返回数据的过程其实就是一个反序列化过程

在第三步开始,当客户端向服务端发送远程请求,服务端接受到请求,会回调Binder的onTransact方法,并将数据返回给客户端,接下来就看看onTransact的实现逻辑是如何的:

@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
    //根据客户端发起请求code,来确定执行
    switch (code) {
        case INTERFACE_TRANSACTION: {
            reply.writeString(DESCRIPTOR);
            return true;
        }
        case TRANSACTION_getBookList: {
            data.enforceInterface(DESCRIPTOR);
            java.util.List<com.hzw.progress.aidl.Book> _result = this.getBookList();
            reply.writeNoException();
            reply.writeTypedList(_result);
            return true;
        }
        case TRANSACTION_addBook: {
            //从输入型对象取出参数信息
            data.enforceInterface(DESCRIPTOR);
            com.hzw.progress.aidl.Book _arg0;
            //读取数据
            if ((0 != data.readInt())) {
                //传入参数存在,则反序列化过程
                _arg0 = com.hzw.progress.aidl.Book.CREATOR.createFromParcel(data);
            } else {
                _arg0 = null;
            }
            this.addBook(_arg0);
            reply.writeNoException();
            return true;
        }
        case TRANSACTION_registerListener: {
            data.enforceInterface(DESCRIPTOR);
            com.hzw.progress.aidl.OnNewBookAddListener _arg0;
            _arg0 = com.hzw.progress.aidl.OnNewBookAddListener.Stub.asInterface(data.readStrongBinder());
            this.registerListener(_arg0);
            reply.writeNoException();
            return true;
        }
        case TRANSACTION_unregisterListener: {
            data.enforceInterface(DESCRIPTOR);
            com.hzw.progress.aidl.OnNewBookAddListener _arg0;
            _arg0 = com.hzw.progress.aidl.OnNewBookAddListener.Stub.asInterface(data.readStrongBinder());
            this.unregisterListener(_arg0);
            reply.writeNoException();
            return true;
        }
    }
    return super.onTransact(code, data, reply, flags);
}

当客户端发起跨进程请求时,远程服务端会通过系统底层封装好的方法来处理返回数据,这个就是方法就是onTransact,它内部大概流程如下:

  • 首次会根据客户端请求code来确定需要执行的内容是什么
  • 接着从输入型对象data中取出目标参数,如果参数存在,则进行反序列化操作。
  • 当目标方法执行完毕后,就向输出型reply对象写入数据,并将数据返回给Binder对象,最后返回给客户端。

上面就是整个AIDL实现进程通信的原理流程。

总结

下面简单总结Binder的工作机制

在这里插入图片描述

Binder的工作流程可以分为三部分,分别是连接请求、序列化写入数据、反序列化结果返回客户端

  1. 绑定服务建立连接后,服务端会返回一个Binder对象给客户端,通过Binder对象就可以跨进程交互。在获取Binder实例对象时,需调用asInterface方法进行判断客户端和服务端是否在同一进程,若在同一个进程,则返回一个本地binder对象,反之则需创建一个代理对象Stub.Proxy返回。
  2. 获取到代理对象Proxy后,客户端可以调用服务端相应的方法(addBook、getBookList等)传入参数,当Binder拿到数据后,会根据参数的有无(序列化过程)写入包裹类Parcel中,接着调用binder对象的transact方法。
  3. 最后会触发Stub类(Binder类)的onTransact方法,从线程池中取出数据,写入reply中把结果返回给客户端,最终唤醒线程。

参考Android开发艺术探索

最后

以上就是哭泣金毛为你收集整理的Android进程通信之AIDL的使用与Binder浅谈的全部内容,希望文章能够帮你解决Android进程通信之AIDL的使用与Binder浅谈所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部