定义
AIDL(Android Interface Definition Language)Android接口定义语言,主要帮助开发者完成进程间通信,我们知道Android中进程间通信有一种是Binder,AIDL就是帮助开发者简化Binder的一些操作,主动帮我们生成了需要Binder的代码。
AIDL所支持的数据类型
- 基本数据类型
- String以及Charsequence
- List:只支持ArrayList,且里面的每个元素也必须是AIDL支持的类型
- Map:只支持HashMap,且里面的每个元素也必须是AIDL支持的类型
- Parcelable:支持java的对象,也就是javabean,但是要求该实体类必须实现Parcelable
使用步骤
既然是进程间通信,那么我们就新建两个项目aidlserver和aidlclient
aidlserver项目
- 新建aidlserver项目,然后新建aidl文件夹
- 在该文件夹下面新建Book.aidl类,(这个时候Android Studio会自动在与java同级的目录下面生成aidl文件夹,并且刚才新建的Book.aidl文件也在该目录下面)
- 在aidl文件夹下面新建Book.java实体类,并且要实现Parcelable接口,复写里面的方法(注意不是AS为我们生成的aidl文件夹,而是在我们自己新建的aidl文件夹下面新建该实体类),这个时候该实体类是报错的
- 实体类报错并不是我们代码写错了,修改Book.aidl,将系统为我们生成的代码改写为 parcelable Book;然后rebuild即可
- 同样,在aidl文件夹下面新建IBookController.aidl文件,用来处理查找与添加的操作,在添加数据的时候这里由个tag要注意,也就是数据的流向。另外,操作实体类Book话要手动导包
package www.wfq.com.aidlserver.aidl;
import www.wfq.com.aidlserver.aidl.Book;
interface IBookController {
List<Book> findAllBook();
//新增一本书 使用定向tag inout
// AIDL中的定向 tag 表示了在跨进程通信中数据的流向,其中
// in 表示数据只能由客户端流向服务端,
// out 表示数据只能由服务端流向客户端,
// inout 则表示数据可在服务端与客户端之间双向流通
void addBook(inout Book book);
}
复制代码
- 在aidl文件夹下面新建BookService,用来作为服务跟客户端通信
public class BookService extends Service {
// 使用线程安全的CopyOnWriteArrayList
private List<Book> books = new CopyOnWriteArrayList<>();
private IBookController.Stub stub = new IBookController.Stub() {
@Override
public List<Book> findAllBook() throws RemoteException {
return books;
}
@Override
public void addBook(Book book) throws RemoteException {
if (null != book) books.add(book);
}
};
@Override
public void onCreate() {
super.onCreate();
for (int i = 0; i < 5; i++) {
books.add(new Book("book" + i));
}
}
@Override
public IBinder onBind(Intent intent) {
return stub;
}
}
复制代码
- 如果想跟客户端通信的话还需要在清单文件中注册service,并且把exported = 'true',然后客户端访问的时候可以使用包名加action的形式进行连接
<service android:name=".aidl.BookService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="www.wfq.com.aidiserver.aidl.BookService"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</service>
复制代码
至此服务端编写完成,整体的目录结构如下图:
aidlclient项目
客户端项目的编写当对简单,步骤
- 将服务端中Android Studio为我们生成的整个aidl文件夹拷贝到客户端,不要换包名,所在位置跟在服务端的位置一样(在拷贝文件夹的时候,可以将目录结构调整为Project模式)
- 在客户端java文件夹下面新建aidl文件夹,整体的包名跟服务端保持一致,将服务端的Book.java这个实体类拷贝到该目录下。至此,文件拷贝工作完成
- 编写代码,可在Activity中直接绑定服务端的service
public class MainActivity extends AppCompatActivity {
private Button findBooks, addBook;
private Boolean isConnected;
private IBookController controller;
private List<Book> bookList;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findBooks = findViewById(R.id.btn_get);
addBook = findViewById(R.id.btn_add);
bindService();
findBooks.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
bookList = controller.findAllBook();
print();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
addBook.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
Book book = new Book("客户端新增一本书");
controller.addBook(book);
print();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
private void print() {
for (Book book : bookList) {
Log.e("WFQ客户端", "value is: " + book);
}
}
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
isConnected = true;
Log.e("WFQ客户端", "连接上服务");
controller = IBookController.Stub.asInterface(iBinder);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.e("WFQ客户端", "断开服务");
isConnected = false;
}
};
private void bindService() {
Intent intent = new Intent();
//设置服务端项目的包名
intent.setPackage("www.wfq.com.aidlserver");
//设置服务端在清单文件中注册服务时设置的action的值
intent.setAction("www.wfq.com.aidiserver.aidl.BookService");
bindService(intent, connection, BIND_AUTO_CREATE);
}
private void unBindService() {
if (isConnected) unbindService(connection);
}
@Override
protected void onDestroy() {
super.onDestroy();
unBindService();
}
}
复制代码
代码以上传到github:
服务端代码:github.com/wfqdroid/ai…
客户端代码:github.com/wfqdroid/ai…