一、序言
该系列文章旨在让AIDL初学者入门,不一定全,但通过自己在Android Studio上的实际编写运行,尽可能会把相关的知识点和编译运行过程中遇到的问题列出来并给出解决方案。
本文主要介绍AIDL的相关原理和开发时的大致框架。要学习AIDL项目的具体开发,可以参考文章:,不过博主建议大家先通过本文将AIDL的原理了解一下,对于后续的AIDL的开发可以起到事半功倍的作用。
二、概述
2.1 AIDL的定义
AIDL是为了实现进程间通信(特别是在多进程并发情况下的进程间通信)而设计的Android接口语言,全称是Android Interface Definition Language,也就是Android接口定义语言。
2.2 优点
BroadcastReceiver , Messenger等也能进行进程间通信,但是:
(1)BroadcastReceiver占用的系统资源较多,不适合频繁进行跨进程通信;
(2)Messenger进行跨进程通信时请求队列时同步进行的,无法并发进行;
2.3 语法
本节只列举大概的语法内容,不进行详细介绍。
2.3.1 数据类型
默认支持的数据类型包括:
(1)Java中的八种基本数据类型,包括byte、short、int、long、float、double、boolean、char;
(2)String类型;
(3)CharSequence类型;
(4)List类型:List中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable(下文关于这个会有详解)。List可以使用泛型;
(5)Map类型:Map中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable。Map是不支持泛型的;
(6)定向tag:
定向 tag
数据流向是针对在客户端中的那个传入方法的对象而言的。1)in 为定向 tag 的情况下表现为服务端将会接收到一个那个对象的完整数据,但是客户端的那个对象不会因为服务端对传参的修改而发生变动;2)out 表现为服务端将会接收到那个对象的的空对象,但是在服务端对接收到的空对象有任何修改之后客户端将会同步变动;3)inout 为定向 tag 的情况下,服务端将会接收到客户端传来对象的完整信息,并且客户端将会同步服务端对该对象的任何变动。
注意:
1) Java 中的基本类型和 String ,CharSequence 的定向 tag 默认且只能是 in;
2)不要滥用定向tag,要根据需求使用,因为排列整理参数的开销很大;
2.3.2 AIDL文件种类
大致分为两类:
(1)用来定义parcelable对象,以供其他AIDL文件使用AIDL中非默认支持的数据类型,示例代码如下:
// Book.aidl
//用于引入了一个序列化对象Book,供其他的AIDL文件使用
//注意:Book.aidl与Book.java的包名应当是一样的
package com.example.ipcclient;
//注意parcelable是小写
parcelable Book;
(2)用来定义方法接口,以供项目使用来完成跨进程通信(简单来说就是通信接口文件,只需要在服务器端和客户端各定义一个就行,两端内容完全一样);
// BookManager.aidl
package com.example.ipcclient;
//导入所需要使用的非默认支持数据类型的包
import com.lypeer.ipcclient.Book;
interface BookManager {
//所有的返回值前都不需要加任何东西,不管是什么数据类型
List<Book> getBooks();
Book getBook();
int getBookCount();
//传参时除了Java基本类型以及String,CharSequence之外的类型
//都需要在前面加上定向tag,具体加什么按需而定
void setBookPrice(in Book book , int price)
void setBookName(in Book book , String name)
void addBookIn(in Book book);
void addBookOut(out Book book);
void addBookInout(inout Book book);
}
三、AIDL运行原理
3.1 AIDL项目结构
在学习AIDL运行的原理之前,需要先把AIDL项目的结构弄清楚;
3.1.1 服务器端
先来了解一下服务器端的项目代码主要结构,完整项目编写见下一章;
(1)一个AIDLService.java类,在com.example.ipcserver包下,大概框架如下:
package com.example.ipcserver;
public class AIDLService extends Service {
//BookManager是aidl通信接口的名字
private final IBinder mBookManager = new BookManager.Stub() {
//实现aidl中声明的方法
}
public void onCreate() {
//可以不用设置视图
}
public IBinder onBind(Intent intent) {
//连接成功,返回获取到的aidl通信接口
return mBookManager;
}
public void onDestroy() {
//结束service
super.onDestroy();
}
(2)一个BookManager.aidl通信接口,在com.example.ipcserver包下,注意后续要与客户端的通信接口同名、同目录;
package com.example.ipcserver;
import com.example.ipcserver.Book;
interface BookManager {
List<Book> getBooks();
void addBook(inout Book book);
}
(3)一个Book.java实现序列化,即实现Parcelable接口,具体代码见下一章;
(4)一个Book.aidl引入序列化对象,代码如下:
package com.example.ipcserver;
parcelable Book;
(5)编译后会生成一个BookManager.java,是BookManager.aidl通信接口的实现类;
3.1.2 客户端
(1)AIDLActivity.java,在com.example.ipcclient包下,客户端界面,在其中与服务器端连接并调用服务器端的方法;
(2)Book.java、Book.aidl、BookManager.aidl,在com.example.ipcserver包下,与服务器端一样;
(3)编译后会生成一个BookManager.java,是BookManager.aidl通信接口的实现类;
3.2 运行原理
3.2.1 项目结构图
AIDL项目的原理结构图如下:
3.2.2 AIDL工作原理
客户端AIDLActivity和服务器端AIDLService是通过BookManager这个aidl接口文件来实现通信的,从用户的角度看,是AIDLService.java和AIDLActivity.java在进行通信,实际上是客户端的本地代理Proxy在和服务器端的Stub类通过transact和onTransact进行通信;
下面来梳理一下Stub-Proxy的工作流程:
(1)AIDLService中的IBinder对象mBookManager是Stub的具体实现,在AIDLService和AIDLActivity绑定的时候被返回;
(2)被返回的mBookManager最终作为客户端onServiceConnnected中的参数;
(3)客户端AIDLActivity会通过本地代理Proxy调用Stub中的静态方法asInterface,mServiceBinder作为参数,最后拿到接口对象mBookManager;
在asInterface方法中,有如下判断流程:
(1)判断Binder是否处于当前进程,若不在,则构建Proxy并返回,构建Proxy时,把mBookManager赋值给mRemote;
(2)Proxy中实现的接口getInformation会调用mRemote的transact方法,而Binder的通信是靠transact和onTransact实现的;
(3)最后会走到Stub的onTransact,完成对mServiceBinder的调用;
3.3 AIDL开发
我们可以使用Android Studio进行AIDL的开发,对于AIDL项目的具体代码和开发过程中的具体问题分析
参考文章
AIDL使用 | Android中AIDL的使用详解 - 简书
AIDL和service使用 | Service和AIDL基本使用 - 简书
AIDL,Stub,Proxy | Android AIDL与proxy,stub - 简书