一、简介
AIDL全称是Android Interface Definition Language,也就是Android接口定义语言。
文件类型:用AIDL书写的文件的后缀是 .aidl
数据类型:AIDL默认支持一些数据类型,在使用这些数据类型的时候是不需要导包的,但是除了这些类型之外的数据类型,在使用之前必须导包。
默认支持的数据类型包括:
- Java中的八种基本数据类型,包括 byte,short,int,long,float,double,boolean,char。
- String 类型。
- CharSequence类型。
- List类型:List中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable(下文关于这个会有详解)。List可以使用泛型。
- Map类型:Map中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable。Map是不支持泛型的。
二、AIDL文件
所有的AIDL文件大致可以分为两类。
- 一类是用来定义parcelable对象,以供其他AIDL文件使用AIDL中非默认支持的数据类型的。
- 一类是用来定义方法接口,以供系统使用来完成跨进程通信的。
// Book.aidl
//第一类AIDL文件的例子
//这个文件的作用是引入了一个序列化对象 Book 供其他的AIDL文件使用
//注意:Book.aidl与Book.java的包名应当是一样的
package com.lypeer.ipcclient;
//注意parcelable是小写
parcelable Book;
// BookManager.aidl
//第二类AIDL文件的例子
package com.lypeer.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
1、新建两个AIDL文件:Book.aidl、IBookManager.aidl
package com.example.aidlservice;
parcelable Book;
package com.example.aidlservice;
import com.example.aidlservice.Book;
interface IBookManager {
oneway void setBookPrice(in Book book, int price);
oneway void setBookName(in Book book , String name);
List<Book> getBookList();
void addBookIn(in Book book);
}
2、在java文件夹下新建一个和aidl文件夹一样结构的Book类;实现Parcelable接口,完成实例化操作,重写方法。
public class Book implements Parcelable {
private String name;
private int price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public Book(String n, int p) {
this.name = n;
this.price = p;
}
protected Book(Parcel in) {
name = in.readString();
price = in.readInt();
}
public static final Creator<Book> CREATOR;
static {
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.writeString(name);
dest.writeInt(price);
}
/**
* 参数是一个Parcel,用它来存储与传输数据
* @param dest
*/
public void readFromParcel(Parcel dest) {
//注意,此处的读值顺序应当是和writeToParcel()方法中一致的
name = dest.readString();
price = dest.readInt();
}
}
3、新建一个Service提供服务;
public class MyAIDLService extends Service {
private static final String TAG = "MyAIDLService";
private List<Book> mBookList;
public MyAIDLService() {
}
@Override
public void onCreate() {
super.onCreate();
mBookList = new ArrayList<>();
initData();
Log.e(TAG, "onCreate: ");
}
private void initData() {
for (int i = 0; i < 5; i++) {
Book book = new Book("服务的一本书", i+1);
mBookList.add(book);
}
}
private IBookManager.Stub mStub = new IBookManager.Stub() {
@Override
public void setBookPrice(Book book, int price) throws RemoteException {
book.setPrice(price);
}
@Override
public void setBookName(Book book, String name) throws RemoteException {
book.setName(name);
}
@Override
public List<Book> getBookList() throws RemoteException {
return mBookList;
}
@Override
public void addBookIn(Book book) throws RemoteException {
if (book != null) {
book.setName("服务器改了新书的名字 InOut");
mBookList.add(book);
} else {
Log.e(TAG, "接收到了一个空对象 InOut");
}
}
};
@Override
public IBinder onBind(Intent intent) {
return mStub;
}
}
4、新建一个项目,将本项目下的aidl文件粘贴到新项目下,Book也直接粘贴过去;
5、在Activity中,写如下代码:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private IBookManager mIBookManager;
private boolean connected;
private List<Book> mBookList;
//创建连接
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIBookManager = IBookManager.Stub.asInterface(service);
connected = true;
Log.e(TAG, "onServiceConnected: ");
}
@Override
public void onServiceDisconnected(ComponentName name) {
connected = false;
Log.e(TAG, "onServiceDisconnected: ");
}
};
private View.OnClickListener mClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_getBookList:
Log.e(TAG, "onClick: btn_getBookList" + "---" + connected);
if (connected) {
try {
mBookList = mIBookManager.getBookList();
for (Book book : mBookList) {
Log.e(TAG, "onClick: " + book.getName() + "--" + book.getPrice());
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
break;
case R.id.btn_addBook_inOut:
Log.e(TAG, "onClick: btn_addBook_inOut" + "---" + connected);
if (connected) {
Book book = new Book("小黑", 12);
try {
mIBookManager.addBookIn(book);
for (Book book1 : mBookList) {
Log.e(TAG, "onClick: " + book1.getName() + "--" + book1.getPrice());
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_getBookList).setOnClickListener(mClickListener);
findViewById(R.id.btn_addBook_inOut).setOnClickListener(mClickListener);
}
@Override
protected void onResume() {
Intent intent2 = new Intent();
ComponentName componentName2 = new ComponentName("com.example.aidltest01",
"com.example.aidltest01.MyService");
intent2.setComponent(componentName2);
intent2.setAction("android.intent.action.test.test");
bindService(intent2, mServiceConnection, Context.BIND_AUTO_CREATE);
super.onResume();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (connected) {
unbindService(mServiceConnection);
}
}
}
还有一篇对于AIDL讲解很细的文章,有兴趣可以去看一下:https://blog.csdn.net/luoyanglizi/article/details/51980630