AIDL实现Android进程间的通信

来源:互联网 发布:签到赚钱的软件 编辑:程序博客网 时间:2024/06/14 11:37

今天来详讲一种Android进程通信的方式:AIDL

AIDL:android接口定义语言

AIDL的作用:首先我们知道,每个进程都运行在自己的虚拟机中,拥有自己独立的内存地址空间,在自己的内存空间操作自己的数据,但如果想跟其它内存空间通信时。这时就涉及到进程之间的通信,aidl就是它们通信的桥梁之一,它制定自己的规则,只要按照它的规则来就可以实现进程之间的通信。

为什么选用AIDL来进行进程之间的通信:

(1)Messenger时串行方式处理客户端发来的消息,如果有大量消息同时发送到服务端,Messenger只能一条一条道处理。但是如果有大量并发请求,那么Messenger就不行了。另外Messenger主要是传送消息用的,如果我们想调用服务端的方法时,这个时候就要AIDL 了。

(2)BroadcastReceive也可以进行进程之间的通信,但是BroadcastReceive占用的系统资源太多,显然如果频繁的调用的话是不合适的。

AIDL所能使用的数据类型:

(1)  java八种基本类型:int ,short , long , byte , char , Boolean , float ,double .

(2)  List的ArrayList.

(3)  Map的HashMap

(4)  实现了parcelable的对象

(5)   CharSequence、string类型。

定向tag:分别有in、out、inout。这里选择的参考对象是服务端。In表示数据只能从客户端流向服务端。Out表示数据只能从服务端流向客户端。Inout可以双向流动,inout使用比较消耗系统资源。

下面跟着例子讲一下AIDL通信原理:

项目结构:


1、新建一个aidl文件:IBookManager.aidl

// IBookManager.aidlpackage com.ryg.ipcaidl;import com.ryg.ipcaidl.Book;//因为下面用到Book这个类,所以这里一定要import Book。interface IBookManager {    List<Book> getBookList();//因为这里用到Book这个类,所以一定要新建一个Book.aidl文件    void addBook(in Book book);}


2、Book.aidl

package com.ryg.ipcaidl;parcelable Book;

3、此时ReBuild一下,这时那会发现工程下多了一个IBookManager.java的接口文件


在这里来个一个小插曲:

有可能那在rebuild的时候,会报以下错误:



解决办法有两个:

(1)修改 build.gradle 文件:在 android{} 中间加上下面的内容:

buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }    }

(2)或者将你写的Book.java文件放在项目的包路径下。

 

4、这里来详细解说一下IBookManager.java这个文件:

其实这个时候可以将之前的aidl文件删除,它的作用已经用完,哈哈。

默认生成的BookManagerImpl.java文件是这样的:

/* * This file is auto-generated.  DO NOT MODIFY. * Original file: /Users/apple/workSpace/IPCAidl/app/src/main/aidl/com/ryg/ipcaidl/IBookManager.aidl */package com.ryg.ipcaidl;public interface IBookManager extends android.os.IInterface{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.ryg.ipcaidl.IBookManager{private static final java.lang.String DESCRIPTOR = "com.ryg.ipcaidl.IBookManager";/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an com.ryg.ipcaidl.IBookManager interface, * generating a proxy if needed. */public static com.ryg.ipcaidl.IBookManager asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.ryg.ipcaidl.IBookManager))) {return ((com.ryg.ipcaidl.IBookManager)iin);}return new com.ryg.ipcaidl.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.ryg.ipcaidl.Book> _result = this.getBookList();reply.writeNoException();reply.writeTypedList(_result);return true;}case TRANSACTION_addBook:{data.enforceInterface(DESCRIPTOR);com.ryg.ipcaidl.Book _arg0;if ((0!=data.readInt())) {_arg0 = com.ryg.ipcaidl.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.ryg.ipcaidl.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.ryg.ipcaidl.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.ryg.ipcaidl.Book> _result;try {_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);_reply.readException();_result = _reply.createTypedArrayList(com.ryg.ipcaidl.Book.CREATOR);}finally {_reply.recycle();_data.recycle();}return _result;}@Override public void addBook(com.ryg.ipcaidl.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.ryg.ipcaidl.Book> getBookList() throws android.os.RemoteException;public void addBook(com.ryg.ipcaidl.Book book) throws android.os.RemoteException;}


我们可以把这里面的代码整理一下,便于分析(重点:分析过程已经在代码的注释里面说明,请大家仔细阅读):

package com.ryg.ipcaidl;import android.media.audiofx.AudioEffect;import android.os.Binder;import android.os.IBinder;import android.os.IInterface;import android.os.Parcel;import android.os.RemoteException;import java.util.List;import static com.ryg.ipcaidl.IBookManager.Stub.DESCRIPTOR;import static com.ryg.ipcaidl.IBookManager.Stub.TRANSACTION_getBookList;/** * Created by apple on 17/5/7. */public interface IBookManager extends IInterface{    //创建一个接口对象Stub    public static abstract class Stub extends Binder implements IBookManager{        public Stub(){            this.attachInterface(this, DESCRIPTOR);        }        //这个方法运行在服务端的binder线程池中,将服务端的binder方法转化为客户端所能识别的aidl接口        public static IBookManager asInterface(IBinder obj){            if (obj == null){                return null;            }            return new IBookManager.Stub().Proxy(obj);        }        //用于返回当前的binder对象        @Override        public IBinder asBinder() {            return this;        }        //该方法运行在 客户端        private static class Proxy implements IBookManager{            private Binder mRemote;            Proxy(IBinder remote){            }            @Override            public List<Book> getBookList() throws RemoteException {                //创建输入型Parcel对象                Parcel data = Parcel.obtain();                //创建输出型Parcel对象                Parcel reply = Parcel.obtain();                List<Book> result;                //把参数信息写入data中                data.writeInterfaceToken(DESCRIPTOR);                //调用transact方法发起远程请求,客户端当前线程挂起,服务端此时调用onTransact方法                mRemote.transact(TRANSACTION_getBookList,data,reply,0);                //获取rpc过程中的返回值                reply.readException();                result = reply.createTypedArrayList(Book.CREATOR);                //并将该返回值返回,当前线程继续执行                return result;            }            @Override            public void addBook(Book book) throws RemoteException {            }            @Override            public IBinder asBinder() {                return null;            }        }        //这个方法运行在 服务端 的binder线程池中,当客户端发起远程请求时,会将远程请求通过系统底层封装后,交由此方法处理        //这个方法有四个参数。code:客户端请求的目标方法是什么。data:取出目标方法所需要的参数。repl:执行完毕以后向reply中写数据        //注意这个方法返回的是boolean类型,如果这个方法返回的是fals,说明此客户端没有权限访问这个服务端        @Override        protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {            return super.onTransact(code, data, reply, flags);        }        //具体方法        @Override        public List<Book> getBookList() throws RemoteException {            return null;        }        //具体方法        @Override        public void addBook(Book book) throws RemoteException {        }    }}



 

5、原理看完以后继续,看我们实际当中怎么使用它,在本实例中客户端代码如下:

import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.IBinder;import android.os.RemoteException;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import java.util.List;public class BookClientActivity extends AppCompatActivity {    private static final String TAG = "BookClientActivity";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //启动服务端        Intent intent = new Intent();        intent.setAction("com.ryg.ipcaidl.launch");        intent.setPackage(getPackageName());        bindService(intent,mConnection, Context.BIND_AUTO_CREATE);    }    //获得与服务端链接    private ServiceConnection mConnection =            new ServiceConnection() {                @Override                public void onServiceConnected(ComponentName name, IBinder service) {                    //调用运行在服务端的asinterface()方法                    //将服务端的binder对象转化为客户端所需要的aidl接口对象                    IBookManager bookManager = IBookManager.Stub.asInterface(service);                    try {                        //直接调用服务端方法                        List<Book> list = bookManager.getBookList();                        Log.e(TAG,"获取所有书的list :"+list.toString());                        Book newBook  = new Book(3,"客户端添加的书3");                        bookManager.addBook(newBook);                        list = bookManager.getBookList();                        Log.e(TAG,"客户端添加以后 获取所有书的list :"+list.toString());                    } catch (RemoteException e) {                        e.printStackTrace();                    }                }                @Override                public void onServiceDisconnected(ComponentName name) {                }            };    @Override    protected void onDestroy() {        unbindService(mConnection);        super.onDestroy();    }}
客户端使用IMessenger.Stub.asInterface(target)拿到接口实例进行调用


6、服务端代码如下:

import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;import android.os.RemoteException;import android.support.annotation.Nullable;import android.util.Log;import java.util.List;import java.util.concurrent.CopyOnWriteArrayList;import java.util.concurrent.atomic.AtomicBoolean;/** * Created by apple on 17/5/7. */public class BookManagerService extends Service{    private static final String TAG = "BookManagerService";    //用CopyOnWriteArrayList创建一个线程同步的对象    private CopyOnWriteArrayList<Book> mBookList =            new CopyOnWriteArrayList<Book>();    //创建一个binder对象    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 onCreate() {        super.onCreate();        mBookList.add(new Book(1,"服务端添加的书1"));        mBookList.add(new Book(2,"服务端添加的书2"));    }    //返回这个binder对象    @Nullable    @Override    public IBinder onBind(Intent intent) {        return mBinder;    }}

服务端OnBind利用stub编写接口实现返回


7、 实现了parcelable的对象

package com.ryg.ipcaidl;import android.os.Parcel;import android.os.Parcelable;public class Book implements Parcelable {    public int bookId;    public String bookName;    public Book() {    }    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 Creator<Book> CREATOR = new 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();    }    @Override    public String toString() {        return String.format("[bookId:%s, bookName:%s]", bookId, bookName);    }}


 

 

 

 

 

 

 

 

 

 

 

 

 

0 0
原创粉丝点击