关键词:
写在前面
上一篇我们介绍了binder机制的基本知识,如果还不太了解binder机制,可进行点击查看:让你一看就明白的Binder机制
binder和AIDL的关系
从应用层的角度来说,Binder类是android中的一个类,它实现了IBinder接口,是binder机制在应用层的核心代理,Binder是客户端和服务端进行通讯的“桥梁”。在android开发中,Binder主要用在service中,包括AIDL和Messenger。普通的service不涉及进程间通讯,无法涉及到binder机制的核心。Messenger的底层其实也是AIDL的实现,那么一直说的AIDL到底是什么呢?其实AIDL文件本质上就是为了方便开发者减少代码编写量,由IDE自动编译生成对应的java文件提供给开发者使用。下面我们将一步一步的去实现。
跨进程通讯对于数据实体的要求
android中的基于binder的跨进程通讯要求实体类需要实现Parcelable接口,只有实现了parcelable接口的实体类才能够成功被传递。下面总结AIDL文件中可以被使用的数据类型:
基本数据类型(int、char、long、boolean等)
String和CharSequence
List:只支持ArrayList,并且里面的元素都可以被AIDL支持
Map:只支持HashMap,并且里面的每个元素都可以被AIDL支持
Parcelable:所有实现了Parcelable接口的对象
AIDL:所有的AIDL接口本身也可以在AIDL中进行使用
使用AIDL进行进程间通讯的大概流程
服务端:
服务端首先创建一个service用来监听客户端连接请求,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件的声明,最后在service中进行实现
客户端
客户端需要绑定服务端的service,绑定成功之后将服务端返回的binder对象转成AIDL接口所属的类型,接着就可以调用AIDL的方法了。
项目Demo实现
首先我们需要准备好开发android应用的必要的工具:android studio
在Android Studio中新建一个项目,首先创建一个实现parcelable接口的实体类book。代码细节如下:
创建实现Parcelable接口的实体类
package com.example.zwjian.myapplication;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by zwjian
*/
public class Book implements Parcelable
private int bookId;
private String bookName;
public Book(int id, String name)
bookId = id;
bookName = name;
protected Book(Parcel in)
bookId = in.readInt();
bookName = in.readString();
public static final Creator<Book> CREATOR = new Creator<Book>()
@Override
public Book createFromParcel(Parcel in)
return new Book(in);
@Override
public Book[] newArray(int size)
return new Book[size];
;
@Override
public int describeContents()
return 0;
@Override
public void writeToParcel(Parcel dest, int flags)
dest.writeInt(bookId);
dest.writeString(bookName);
@Override
public String toString()
return "名字:" + this.bookName + ",ID:" + this.bookId;
上面我们定义了一个Book类,实现了Parcelable接口,在该类中包含两个字段bookID和bookName。
创建Book.aidl文件
AIDL文件要求如果需要使用自己定义的Parcelable对象,那么必须要新建一个和他同名字的AIDL文件,并在其中声明他为parcelable类型。所以我们需要新建一个book.aidl文件
我们在android studio中新建一个aidl文件,然后会发现IDE创建了一个和java文件同级的aidl文件夹
接下来我们在新建的Book.aidl文件中加入book的parcelable声明:
// Book.aidl
package com.example.zwjian.myapplication;
// Declare any non-default types here with import statements
parcelable Book;
创建service将要暴露的接口方法
接下来我们要创建一个接口,将service要提供的方法放在该接口文件中:在aidl文件夹下新建IBookManager.aidl文件,代码如下:
// IBookManager.aidl
package com.example.zwjian.myapplication;
// 虽然book.aidl和IBookManager.aidl都在同一包下,但是还需要import进来
import com.example.zwjian.myapplication.Book;
interface IBookManager
//声明2个方法,这两个方法会在service中进行实现
List<Book> getBookList();
void addBook( in Book book);
完成上述操作,我们点击“build—-> make project”,build之后,我们就可以得到IDE智能帮我们创建的IBookManager.java文件了。
那么生成的IBookManager.java文件在哪里呢?我们可以在以下路径中找到:build—>generated—>source—>aidl—>debug,然后我们就可以看到包名中的java文件了。其内容如下:
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: /Users/zwjian/AndroidStudioProjects/MyApplication/aidlTest/src/main/aidl/com/example/zwjian/myapplication/IBookManager.aidl
*/
package com.example.zwjian.myapplication;
public interface IBookManager extends android.os.IInterface
/**
* Local-side IPC implementation stub class.
* stub是一个BInder类,当客户端和服务器端都在同一进程,方法调用不会走跨进程的transact过程。
* 反之,需要走transact过程,这个逻辑由Stub.Proxy来实现
*/
public static abstract class Stub extends android.os.Binder implements com.example.zwjian.myapplication.IBookManager
// Binder的唯一标示,一般用当前的binder类名表示
private static final java.lang.String DESCRIPTOR = "com.example.zwjian.myapplication.IBookManager";
/**
* Construct the stub at attach it to the interface.
*/
public Stub()
this.attachInterface(this, DESCRIPTOR);
/**
*用于将服务器端的Binder对象转换成客户端所需要的AIDL接口类型对象,这种操作区分进程:统一进程时,此方法返回服务端的stub对象本身。
反之返回的是stub.proxy对象
*/
public static com.example.zwjian.myapplication.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.zwjian.myapplication.IBookManager)))
return ((com.example.zwjian.myapplication.IBookManager) iin);
return new com.example.zwjian.myapplication.IBookManager.Stub.Proxy(obj);
//返回当前binder对象
@Override
public android.os.IBinder asBinder()
return this;
//该方法运行在服务器端的Binder线程池中,当客户端发起跨进程请求时,远程请求会通过系统底层封装后交给该方法执行。
//服务器端通过code可以确定客户端要请求的方法是哪个,接着从data中取出请求参数(如果有的话),然后去执行目标方法。
//执行完毕之后将结果放入reply参数中进行返回
@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.zwjian.myapplication.Book> _result = this.getBookList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
case TRANSACTION_addBook:
data.enforceInterface(DESCRIPTOR);
com.example.zwjian.myapplication.Book _arg0;
if ((0 != data.readInt()))
_arg0 = com.example.zwjian.myapplication.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.example.zwjian.myapplication.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;
//该方法和下面的addBook方法一样,都运行在客户端,客户端调用该方法的流程如下:
//首先创建该方法需要的输入型参数_data,输出Parcel型参数_reply和返回值list,然后如果有输入参数则将数据放进_data中,
//接着调用transact方法发起远程过程调用(RPC)请求,同时线程挂起,然后服务器端的onTransact方法会执行,直到RPC过程返回。
//当前线程继续执行,并从_reply中取出RPC过程的返回值
@Override
public java.util.List<com.example.zwjian.myapplication.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.zwjian.myapplication.Book> _result;
try
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(com.example.zwjian.myapplication.Book.CREATOR);
finally
_reply.recycle();
_data.recycle();
return _result;
@Override
public void addBook(com.example.zwjian.myapplication.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();
//这两个静态变量ID标识在transact过程中客户端请求的到底是哪个方法
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.example.zwjian.myapplication.Book> getBookList() throws android.os.RemoteException;
public void addBook(com.example.zwjian.myapplication.Book book) throws android.os.RemoteException;
以上我们基本上将AIDL文件生成对应java文件的过程讲述完毕,并且做了比较详细的函数说明,下面开始实现自定义的service类
创建service类
上部分我们定义了aidl接口,我们接下来需要在service中实现这个接口。我们在Android Studio中创建一个BookManagerService类:
package com.example.zwjian.myapplication;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class BookManagerService extends Service
private static final String TAG = "BookManagerService";
private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<Book>();
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, "android"));
mBookList.add(new Book(2, "ios"));
@Override
public IBinder onBind(Intent intent)
return mBinder;
上面的代码比较简单,核心就在于onBinder方法返回的mBinder对象了,我们可以发现mBinder代表的是IBookManager类中的Stub这个binder类,并且在service中进行了方法实现。
值得注意的一点是,由于是在同一个应用中的项目Demo,为了突出跨进程通讯,我们需要给该service设置另外一个进程执行(android:process属性):
<service
android:name=".BookManagerService"
android:enabled="true"
android:exported="true"
android:process=":myService">
</service>
实现client端代码
client端其实也就是指的是各种activity中的代码实现了。主要流程:首先绑定远程服务,绑定成功之后将服务端返回的Binder对象转化成为AIDL接口,然后通过这个接口去调用服务端的远程方法就好。代码如下:
package com.example.zwjian.myapplication;
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 MainActivity extends AppCompatActivity
private static final String TAG = "MainActivity";
private ServiceConnection mConnection = new ServiceConnection()
@Override
public void onServiceConnected(ComponentName name, IBinder service)
//通过binder得到IBookManager的引用
IBookManager iBookManager = IBookManager.Stub.asInterface(service);
try
List<Book> list = iBookManager.getBookList();
for (Book book : list)
Log.d(TAG, "bookInfo:" + book.toString());
catch (RemoteException e)
e.printStackTrace();
@Override
public void onServiceDisconnected(ComponentName name)
;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//开始绑定service
Intent intent = new Intent(this, BookManagerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
@Override
protected void onDestroy()
unbindService(mConnection);
super.onDestroy();
同样,代码实现很简单,我们主要是注意要在onDestory中不要忘记解绑service。
以上,我们的demo就大功告成了,可以去运行下,运行结果如下:
android跨进程通信binder机制与aidl实例(代码片段)
...间划分1.2跨进程通信IPC1.3Linux跨进程通信1.4Android进程通信Binder跨进程通信2.1Binder简介2.2Binder驱动2.3Binder原理AIDL编程Demo3.1服务端3.2客户端在操作系统中,进程与进程间的内存和数据都是不共享的。这样做的目的,是为了避... 查看详情
android跨进程通信binder机制与aidl实例(代码片段)
...间划分1.2跨进程通信IPC1.3Linux跨进程通信1.4Android进程通信Binder跨进程通信2.1Binder简介2.2Binder驱动2.3Binder原理AIDL编程Demo3.1服务端3.2客户端在操作系统中,进程与进程间的内存和数据都是不共享的。这样做的目的,是为了避... 查看详情
跨进程通信之messenger
...在Message中放入我们需要的入局,就可以轻松实现数据的跨进程传递了。Messenger是一种轻量级的IPC方案,其底层实现是AIDL。Messenger的使用方法很简单,它对AIDL进程了封装,并且由于它一次只处理一个请求,因此在服务端我们不需... 查看详情
安卓ipc跨进程通讯:aidl+retrofit——andlinker的初步使用
参考技术A需要用到安卓跨进程通讯,IPC(进程间通信)的时候,AndLinker是一款Android上的IPC(进程间通信)库,结合了AIDL和Retrofit的诸多特性,且可以与RxJava和RxJava2的CallAdapters无缝结合使用。个人简单理解就是:简化AIDL流程的一个第... 查看详情
androidframework实战开发-binder专题讲解之aidl文件的详细分析(代码片段)
...l,service。确实这个aidl和service的方式是应用开发中对binder接触层面应该属于最为接近的一层。因为其他的接口方式跨进程通信,比如startActivtiy,ContentProvider,broadc 查看详情
基于aidl结合localsocket的跨进程在android上的运用
在android上有很多跨进程的通讯方法例如aidl,messenger,ContentProvider,BroadCast,Socket等等,想要了解这些IPC机制具体可以参考这篇文章,这是一个序列,他讲述了androd中的跨进程方法。但是本文讲述的是... 查看详情
androidframework实战开发-binder专题讲解之aidl文件的详细分析(代码片段)
csdn在线学习课程,课程咨询答疑和新课信息:QQ交流群:422901085进行课程讨论android跨进程通信实战视频课程(加群获取优惠)大家平时做应用开发时候也经常会遇到有跨进程通信的需求,这里大部分通信... 查看详情
ipc——浅谈aidl的架构原理
在IPC(一)利用纯Binder通信(非aidl)中实现了,如何通过纯粹的Binder实现进程间的通信。然后在IPC(四)_Aidl的基本使用过程实现了如何通过Aidl实现进程间的通信。翻看代码的编写过程,其实大体... 查看详情
binder机制在aidl中的实现分析(代码片段)
本篇主要通过结合已经阅读的Binder机制相关资料(《Android开发艺术探索》和http://weishu.me/2016/01/12/binder-index-for-newer/),通过AIDL来进行Binder机制的初步理解感谢两位作者:任玉刚和WeiShu一一个AIDLDemo的组成部分二通信机制的... 查看详情
android基于共享内存实现跨进程大数据的高效传输(代码片段)
前言提到Android进程间的通信方式,即使是Android客户端开发初学者,也能列举出来几种,无外乎:bundle文件共享AIDL(Binder)MessengerContentProviderSocket然而都2022年了,本文如果只是介绍下以上的几种进程间... 查看详情
android跨进程通信aidl的使用及注意事项
...免App被垃圾回收机制回收;QQ的网路通信使用的就是跨进程通讯。创建Aidl接口文件创建一个File,命名为:xxx.aidl;此处命名为:IIncrementUpdateSer 查看详情
aidl跨进程通信
注:慕课网详细教程:http://www.imooc.com/learn/606 一、线程通信应用场景AIDL IPC 多个应用程序 多线程Binder IPC 多个应用程序 没有多线程Messenger IPC 没有多线程什么是IPC:http://www.jianshu.com/p/c0a5bdbba3c 查看详情
android使用aidl传输超大型文件(代码片段)
...从技术的角度考虑能不能实现。众所周知,AIDL是一种基于Binder实现的跨进程调用方案,Binder对传输数据大小有限制,传输超过1M的文件就会报android.os.TransactionTooLargeException异常。如果文件相对比较小,还可以将文... 查看详情
千里马androidframework实战开发-binder通信之messenger介绍(代码片段)
...程(加群获取优惠)Messenger是什么?Messenger是基于AIDL实现的轻量级IPC方案。这里立马就会有疑问为什么要它呢?明明有了aidl上节课大家学完了aidl进行bi 查看详情
千里马androidframework实战开发-binder通信之messenger介绍(代码片段)
...程(加群获取优惠)Messenger是什么?Messenger是基于AIDL实现的轻量级IPC方案。这里立马就会有疑问为什么要它呢?明明有了aidl上节课大家学完了aidl进行bi 查看详情
千里马androidframework实战开发-binder通信之startactivity跨进程源码分析(代码片段)
...课程(加群获取优惠)上节课我们已经讲解完了Binder常见使用的一些方法,下面这节课我们来讲解一些Binder跨进程通信在平时Framework及SystemServer源码分析场景。 查看详情
千里马androidframework实战开发-binder通信之startactivity跨进程源码分析(代码片段)
...课程(加群获取优惠)上节课我们已经讲解完了Binder常见使用的一些方法,下面这节课我们来讲解一些Binder跨进程通信在平时Framework及SystemServer源码分析场景。 查看详情
android跨进程通信aidl和messenger详解(代码片段)
...程中的,像AMS,PMS,WMS等,它们都是通过binder来进程远程调用,说到这就不得不说多进程之间的通信问题,进程不像线程那样,多线程可以共享内存,而每个进程的内存都是独立的,无法直接访... 查看详情