转载注明出处:http://blog.csdn.net/u012861467/article/details/51684484
AIdl 中文意思是Android 接口定义语言,用于跨进程通讯定义接口用的。跨进程通讯在android中用得最多的就是Binder了,而AIDL就是配套Binder使用的一种接口定义语言,它会转化生成对应的接口文件。
Binder跨进程通讯传递的数据类型是有限制的,如下:package com.example.aidlservicetest;
import com.example.aidlservicetest.Person;
interface IMyServiceInterface {
// 自己定义的一些方法声明
int add(int a,int b);
// 实现Parcelable 接口的复杂类需要import包
String showPerson(in Person person);
List getPersonList(in Person person);
Map getMap(String key, in Person person);
Person getPerson();
}
把里面生成的多余的代码删掉,添加自己的一些方法声明,可以注意到不同的数据类型的写法应该遵循上面列出的限制。
上面的 Person类实现了Parcelable接口。
下面补充一下实现Parcelable接口注意的地方:
先定义一个Person类实现Parcelable接口,生成的代码如下:public class Person implements Parcelable {
protected Person(Parcel in) {
}
public static final Creator CREATOR = new Creator() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
}
}
Parcelable需要实现两个方法和一个接口:
package com.example.aidlservicetest;
import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable{
private String name;//名字
private int sex;//性别
public Person(){}
//从Parcel解析出Person
protected Person(Parcel in) {
readFromParcel(in);
}
public static final Creator CREATOR = new Creator() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
//注意读取变量和写入变量的顺序应该一致 不然得不到正确的结果
parcel.writeString(name);
parcel.writeInt(sex);
}
//注意读取变量和写入变量的顺序应该一致 不然得不到正确的结果
public void readFromParcel(Parcel source) {
name = source.readString();
sex = source.readInt();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
@Override
public String toString() {
return "name=" + name +", sex=" + sex;
}
}
因为自定义的Person类是复杂数据类型,在同一包下还需要新建一个对应的Person.aidl文件告诉系统我们需要序列化和反序列化的类型。每一个实现了Parcelable接口的复杂类都需要对应的.aidl文件。AIDL编译器在编译AIDL文件时会自动查找此类文件。
文件目录结构:
Person.aidl 内容如下:
package com.example.aidlservicetest;
parcelable Person;
增加一个自定义action,可以让客户端使用隐式Intent绑定服务。
class ServiceBinder extends IMyServiceInterface.Stub{
@Override
public int add(int a, int b) throws RemoteException {
return a+b;
}
@Override
public String showPerson(Person person) throws RemoteException {
return person.toString();
}
@Override
public List getPersonList(Person person) throws RemoteException {
List personList = new ArrayList<>();
personList.add(person);
return personList;
}
@Override
public Map getMap(String key, Person person) throws RemoteException {
Map map = new HashMap();
map.put(key,key);
map.put("name",person.getName());
map.put("sex",person.getSex());
return map;
}
@Override
public Person getPerson() throws RemoteException {
Person person = new Person();
person.setName("Tom");
person.setSex(0);
return person;
}
}
我们自定义的类ServiceBinder继承了Stub类,所以可以在Service的onBind(Intent intent)方法中作为参数返回。
@Override
public IBinder onBind(Intent intent) {
Log.i(Tag,"onBind");
return new ServiceBinder();
}
Intent intent = new Intent("com.example.aidlservicetest.myservice");
bindService(intent,serviceConnection, Context.BIND_AUTO_CREATE);
bindService方法里面的参数serviceConnection是一个实现 ServiceConnection接口的对象,我们可以这样创建它:
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
serviceBinder = IMyServiceInterface.Stub.asInterface(iBinder);
try {
Person p = serviceBinder.getPerson();
Log.i(Tag,"getPerson:"+p.toString());
int res = serviceBinder.add(2,3);
Log.i(Tag,"add(2,3):"+res);
Person pp = new Person();
pp.setName("JOHN");
pp.setSex(0);
Map mm = serviceBinder.getMap("Key",pp);
Log.i(Tag,"getMap(\"Key\",pp):"+mm);
String str = serviceBinder.showPerson(pp);
Log.i(Tag,"showPerson:"+str);
List list = serviceBinder.getPersonList(pp);
Log.i(Tag,"getPersonList:"+list);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.i(Tag,"onServiceDisconnected:unbind");
}
};
当Service绑定之后会回调 onServiceConnected 方法,传入的参数有一个IBinder 对象,通过IMyAidlInterface.Stub.asInterface(iBinder); 可以获取远程服务的Binder对象。有了这个Binder对象就可以调用远程服务的方法了。
输出的结果为:
转载注明出处:http://blog.csdn.net/u012861467/article/details/51684484
源码地址
服务器端:https://github.com/StarsAaron/AIDLServiceTest.git
客户端:https://github.com/StarsAaron/AIDLClientTest.git
这是两个不同的应用,在服务器端也可以绑定远程服务,,当服务器端和客户端同时绑定了远程服务,这时候有两个Activity绑定了远程服务,当其中的一个解绑了,远程服务还是没有销毁的,直到两个绑定都解绑了才会调用onDestroy销毁。