AIDL 是什么?
在Android开发中IPC(Inter-Process Communication的缩写)多进程通信的使用场景很多。一般地由于某些功能模块需要特殊原因运行在单独的进程中,又或者为了加大一个应用可使用的内存,因为Android对单个应用使用的最大内存是有限制的,又或者需要做一些非常耗内存而又不好回收的事情,在事情完成后直接结束掉进程,等。开启多进程模式很简单,就是给四大组件指定android:process属性即可。IPC的方式有多种,在日常开发中涉及进程间通信时的首选应该就是AIDL了。我们就来以示例的方式学习AIDL的使用。
AIDL 支持的数据类型
- Java 的基本数据类型
- List 和 Map(元素必须是 AIDL 支持的数据类型,Server 端具体的类里则必须是 ArrayList 或者 HashMap)
- 其他 AIDL 生成的接口
- 实现 Parcelable 的实体
AIDL 如何编写
AIDL 的编写主要为以下三部分:
1、创建 AIDL
- 创建要操作的实体类,实现 Parcelable 接口,以便序列化/反序列化,客户端和服务端实体类和aidl包名要一样,或者会报错的
- 新建 aidl 文件夹,在其中创建接口 aidl 文件以及实体类的映射 aidl 文件
- Make project ,生成 Binder 的 Java 文件
2、服务端
- 创建 Service,在其中创建上面生成的 Binder 对象实例,实现aidl接口定义的方法
- 在 onBind() 中返回Binder 对象实例
3、客户端 - 实现 ServiceConnection 接口,在其中拿到 AIDL 类
- bindService()
- 调用 AIDL 类中定义好的操作请求,添加一个按钮,点击按钮后客户端传递参数给服务端返回的结果
代码示例
1、服务端
- 首先创建一个实体People类并且实现Parcelable序列化
public class People implements Parcelable {
private String name;
private int age;
public People(){
}
public People(String name, int age) {
this.name = name;
this.age = age;
}
//读写的顺序必须要一直
public People(Parcel source) {
this.name = source.readString();
this.age = source.readInt();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int describeContents() {
return 0;
}
//该方法是把该People中的变量写进Parcel对象中
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
public static final Creator<People> CREATOR = new Creator<People>() {
@Override
public People createFromParcel(Parcel source) {
return new People(source);
}
@Override
public People[] newArray(int size) {
return new People[size];
}
};
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
- 新建 aidl 文件夹,在其中创建接口 aidl 文件以及实体类的映射 aidl 文件
先创建实体类的映射 aidl 文件People.aidl
// People.aidl
package com.wq.aidlserver;
// Declare any non-default types here with import statements
parcelable People;
- 创建aidl.aidl文件
package com.wq.aidlserver;
import com.wq.aidlserver.People;
interface aidl {
int add1(int num1,int num2);
List<People> add(in People people);
}
- 创建一个MyServer服务
public class MyServer extends Service {
private static final String TAG = "wq892373445";
private ArrayList<People> mPeople = null;
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG,"onCreate()");
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG,"onUnbind()");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG,"onDestroy()");
}
@Override
public IBinder onBind(Intent intent) {
mPeople = new ArrayList<People>();
Log.d(TAG,"onBind()");
return iBinder;
}
private IBinder iBinder = new aidl.Stub() {
@Override
public int add1(int num1, int num2) throws RemoteException {
Log.d(TAG,"add1:num1="+num1+"num2="+num2);
return num1+num2;
}
@Override
public List<People> add(People people) throws RemoteException {
mPeople.add(people);
return mPeople;
}
};
}
- 在AndroidManifest.xml文件中注册服务
<service android:name=".MyServer">
<intent-filter>
<action android:name="com.wq.aidlserver.MyServer"/>
</intent-filter>
</service>
2、客户端
- 首先把服务端的aidl文件和实体类拷贝到客户端这边来,保持一致
- 在Activity中和服务端进程间通信
public class MainActivity extends AppCompatActivity {
private static final String TAG = "wq892373445";
private aidl mAidl;
private ServiceConnection conn = new ServiceConnection() {
//服务连接上的时候调用这个方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG,"onServiceConnected()");
//拿到了远程的服务
mAidl = aidl.Stub.asInterface(service);
}
//当服务断开的时候调用这个方法
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG,"onServiceDisconnected()");
//回收资源
mAidl = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定服务
bindServers();
}
//绑定服务
public void onAidl(View view) {
try {
//调用远程aidl服务,这样就可以实现进程间通信了
int res = mAidl.add1(2,3);
Log.d(TAG,"客户端传递参数给服务端返回的结果:res="+res);
} catch (RemoteException e) {
e.printStackTrace();
}
try {
ArrayList<People> mPeople = (ArrayList<People>) mAidl.add(new People("wang",12));
Log.d(TAG,"mPeople "+mPeople.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void bindServers(){
//获取到服务端
Intent intent = new Intent();
//显示Intent启动服务,5.0后必须这样启动服务
intent.setComponent(new ComponentName("com.wq.aidlserver","com.wq.aidlserver.MyServer"));
bindService(intent,conn, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG,"onDestroy()");
//解绑服务
unbindService(conn);
if(conn != null )
{
unbindService(conn);
conn = null;
}
}
}
最后执行结果如下所示:
2020-04-11 22:20:20.017 4292-4292/com.wq.aidlserver D/wq892373445: onCreate()
2020-04-11 22:20:20.018 4292-4292/com.wq.aidlserver D/wq892373445: onBind()
2020-04-11 22:20:20.032 4803-4803/? D/wq892373445: onServiceConnected()
2020-04-11 22:20:24.210 4292-4317/com.wq.aidlserver D/wq892373445: add1:num1=2num2=3
2020-04-11 22:20:24.211 4803-4803/com.wq.aidlclient D/wq892373445: 客户端传递参数给服务端返回的结果:res=5
2020-04-11 22:20:24.215 4803-4803/com.wq.aidlclient D/wq892373445: mPeople [People{name='wang', age=12}]