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); }}
- android AIDL实现进程间的通信
- AIDL实现Android进程间的通信
- AIDL实现Android的进程通信
- android 使用AIDL实现进程间通信
- Android Aidl实现进程间通信
- Android使用AIDL实现进程间通信
- Android使用AIDL实现进程间通信
- android笔记 AIDL 实现进程间通信
- Android使用AIDL实现进程间通信
- Android使用AIDL实现进程间通信
- Android使用AIDL实现进程间通信
- Android AIDL IPC实现进程间通信
- AIDL实现Android进程间通信实例
- Android使用AIDL实现进程间通信
- Android实现进程间通信aidl的使用
- android使用aidl实现进程间通信的实例
- Android基础--使用AIDL实现进程间的通信
- android 用aidl实现进程间的通信
- 使用js来判断客户端当前网络的状态
- 第四届蓝桥杯第十题连号区间数
- 二二
- 【leedcode】53. Maximum Subarray
- 【Java 5】Unknown column 'user_name' in 'field list'
- AIDL实现Android进程间的通信
- 产品经理之互联网产品-全栈工程师熊盼
- RabbitMQ基础概念详细介绍
- MD5加密的C++实现代码
- NIO实现的简单的客户端与服务端通信(非阻塞)
- ExpandableListView的一些基本语法以及用法,程序员须知的基本标准
- Word Vector
- zhu的Oracle数据库笔记
- 05-树7 堆中的路径 (25分)