AIDL(Android Interface Definition Language) 是一种IDL语言,用于生成可以在Android设备上两个进程之间进行进程间通信(IPC)的代码。
以下的文件创建过程是基于Android Studio。
该文件结构类似与Java中的接口,定义了可用的方法和数据的接口。
右键点击程序包 –> new –> AIDL –> AIDL File 创建IMyAidlInterface.aidl文件,这时Android Studio会自动创建一个和java同级的目录aidl,并在此目录下生成包和.aidl文件。如图:
现在定义一个求和的方法,修改后的IMyAidlInterface文件如下:
package ***.***.***;
interface IMyAidlInterface {
int sum(int a, int b);
}
通过 Build –> Rebuild Project 重新构建项目生成.aidl文件对应的.java文件,如图所示:
创建一个Service用于和其他进程共享数据和方法
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
@Override
public int sum(int a, int b) throws RemoteException {
return a+b;
}
};
}
Stub是生成IMyAidlInterface.java时自动生成的一个抽象内部类,继承自Binder。
由于在其他进程中并不能知道这个Service的名字,所以启动这个Service的时候需要使用隐式的Intent,因此需要给Service添加过滤器:
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.mm.action.aidl" />
intent-filter>
service>
然后在启动Service的时候使用”com.mm.action.aidl”作为Action即可。
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 获取定义的接口
IMyAidlInterface aidlInterface = IMyAidlInterface.Stub.asInterface(service);
try {
// 调用接口中的方法
System.out.println(aidlInterface.sum(100, 3));
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
// 使用bindService启动Service
bindService(new Intent("com.mm.action.aidl"), connection, BIND_AUTO_CREATE);
有了以上的这些配置,就能先运行当前项目测试一下了,如果能正确打印数字的和,则以上配置就没有问题了。
新建一个项目,拷贝上面的.aidl文件到项目的同名目录下,然后Rebuild一下生成对应的.java文件,然后根据上面启动Service的方法启动即可。发布应用时,共享Service的APK要使用同一个签名,否则无法正常共享。
使用AIDL可以直接传递基本数据类型(int long float double)、String、List和Map,如果要传递复杂对象,需要使该对象实现Parcelable接口,并创建同名的.aidl文件。
现在我们创建Person.aidl和Person.java
Person.aidl:
package ***;
parcelable Person;
Person.java :
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by shichaohui on 15/11/4.
*/
public class Person implements Parcelable {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
}
public Person() {
}
protected Person(Parcel in) {
this.name = in.readString();
}
public static final Creator CREATOR = new Creator() {
public Person createFromParcel(Parcel source) {
return new Person(source);
}
public Person[] newArray(int size) {
return new Person[size];
}
};
}
修改IMyAidlInterface.aidl,添加一个获取Person的方法,修改后的IMyAidlInterface.aidl文件:
import com.***.androidtest.Person;
interface IMyAidlInterface {
int sum(int a, int b);
Person getPerson();
}
这里一定要记得import Person.java所在的包,不然会构建失败。
修改MyService,实现getPerson()方法:
public class MyService extends Service {
...
IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
...
@Override
public Person getPerson() throws RemoteException {
Person person = new Person();
person.setName("nammmmme");
return person;
}
};
}
最后就可以和使用sum()方法一样使用getPerson()方法了。