进程间通信机制(IPC)
Linux中IPC机制,主要有管道、消息队列、共享内存、套接字等。
Android中的IPC机制还支持序列化、Messenger、AIDL、Bundle、文件共享、ContentProvider、Binder等。
AIDL全名为Android interface definition Language,即Android接口定义语言,基于 Binder,是实现Binder的一种方式。
Messenger是一种轻量级的IPC方案并对AIDL进行了封装。
ContentProvider底层实现也是Binder。
为了保护用户进程不能直接操作内核,保证内核的安全,操作系统从逻辑上将虚拟空间划分为User space(用户空间 3GB)和Kernel space(内核空间 1GB )。
Binder基于C/S的结构下,定义了4个角色:Server、Client、ServerManager、Binder驱动,其中前三者是在用户空间的,也就是彼此之间无法直接进行交互,Binder驱动是属于内核空间的,属于整个通信的核心。
参考 https://blog.csdn.net/gyh790005156/article/details/88058809
AIDL简介
- AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言。是为了实现 进程间通信。
- 文件类型:用AIDL书写的文件的后缀是 .aidl,而不是 .java。
-数据类型:AIDL默认支持一些数据类型,在使用这些数据类型的时候是不需要导包的,但是除了这些类型之外的数据类型,在使用之前必须导包, 就算目标文件与当前正在编写的 .aidl 文件在同一个包下 ——在 Java 中,这种情况是不需要导包的。比如,现在我们编写了两个文件,一个叫做 Book.java ,另一个叫做 BookManager.aidl ,它们都在 com.lypeer.aidldemo 包下 ,现在我们需要在 .aidl 文件里使用 Book 对象,那么我们就必须在 .aidl 文件里面写上 import com.lypeer.aidldemo.Book; 哪怕 .java 文件和 .aidl 文件就在一个包下。 - 默认支持的数据类型包括:
Java中的八种基本数据类型,包括 byte,short,int,long,float,double,boolean,char。 - String 类型。
CharSequence类型。 - List类型:List中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable(下文关于这个会有详解)。List可以使用泛型。
- Map类型:Map中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable。Map是不支持泛型的。
- 定向tag: AIDL中的定向 tag 表示了在跨进程通信中数据的流向,其中 in 表示数据只能由客户端流向服务端, out 表示数据只能由服务端流向客户端,而 inout 则表示数据可在服务端与客户端之间双向流通。其中,数据流向是针对在客户端中的那个传入方法的对象而言的。in 为定向 tag 的话表现为服务端将会接收到一个那个对象的完整数据,但是客户端的那个对象不会因为服务端对传参的修改而发生变动;out 的话表现为服务端将会接收到那个对象的的空对象,但是在服务端对接收到的空对象有任何修改之后客户端将会同步变动;inout 为定向 tag 的情况下,服务端将会接收到客户端传来对象的完整信息,并且客户端将会同步服务端对该对象的任何变动。
- 两种AIDL文件:在我的理解里,所有的AIDL文件大致可以分为两类。
- 一类是用来定义parcelable对象,以供其他AIDL文件使用AIDL中非默认支持的数据类型的。
- 一类是用来定义方法接口,以供系统使用来完成跨进程通信的。
注: 所有的非默认支持数据类型必须通过第一类AIDL文件定义才能被使用。
-
流程
image.png
- AIDL:客户端通过aidl文件的Stub.asInterface()方法,拿到Proxy代理类
通过调用Proxy代理类的方法,将参数进行封包后,调用底层的transact()方法
transact()方法会回调onTransact()方法,进行参数的解封并调用服务端对应的方法,将结果返回
//myAIDL.aidl
interface myAIDL {
void testMethod();
}
//服务端 AIDLRemoteService.java
public class AIDLRemoteService extends Service {
private static final String TAG = "AIDLRemoteService";
private final myAIDL.Stub mBinder=new myAIDL.Stub(){
@Override
public void testMethod() throws RemoteException {
Log.d(TAG, "testMethod: "+"this is myAIDLTest");
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
//客户端 MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private myAIDL mMyAIDL;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG, "onServiceConnected");
mMyAIDL = myAIDL.Stub.asInterface(service);
try {
mMyAIDL.testMethod();
} catch (RemoteException e) {
Toast.makeText(MainActivity.this, "服务异常", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "onServiceDisconnected");
mMyAIDL = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(MainActivity.this, AIDLRemoteService.class);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
}
}
