AIDL服务只支持有限的数据类型,因此,如果用AIDL服务传递一些复杂的数据时,就需要做进一步的处理。
AIDL服务支持的数据类型如下:
java的简单类型(int、char、boolean等)。不需要导入import
String和CharSequence。不需要导入import
List和Map。但要注意,List和Map对象的元素类型必现是AIDL服务支持的数据类型。不需要导入import
AIDL自动生成的接口。需要导入import
实现android.os.Parcelable接口的类。需要导入import
传递一个需要import的数据类型的步骤略显复杂。除了要建立一个实现android.os.Parcelable接口的类外,还需要为这个类单独建立一个aidl文件,并使用parcelable关键字进行定义。
aidl:
package com.example.aidl4;
import java.util.List;
import com.example.aidl4.PersionParcel;
interface IPersionBinder {
String getName(in PersionParcel p);
List<PersionParcel> getAllPersions();
}
在编写上面代码时需要注意如下两点:
PersionParcel是一个实现android.os.Parcelable接口的类,需要使用import导入这个类。
如果方法的类型是非简单类型,如String、List或自定义的类,需要使用in、out或inout修饰。其中in表示这个值被客户端设置;out表示这个值被服务端设置;inout表示这个值既被客户端设置,又被服务端设置。
PersionParcel的aidl文件:
package com.example.aidl4;
parcelable PersionParcel;
PersionParcel类:
package com.example.aidl4;
import android.os.Parcel;
import android.os.Parcelable;
public class PersionParcel implements Parcelable {
private String mName;
private int mAge;
private String mSex;
public PersionParcel() {
}
public PersionParcel(Parcel in) {
mName = in.readString();
mAge = in.readInt();
mSex = in.readString();
}
public String getName() {
return mName;
}
public void setName(String name) {
mName = name;
}
public int getAge() {
return mAge;
}
public void setmAge(int age) {
mAge = age;
}
public String getSex() {
return mSex;
}
public void setmSex(String sex) {
mSex = sex;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mName);
dest.writeInt(mAge);
dest.writeString(mSex);
}
public static final Parcelable.Creator<PersionParcel> CREATOR = new Creator<PersionParcel>() {
@Override
public PersionParcel[] newArray(int size) {
return new PersionParcel[size];
}
@Override
public PersionParcel createFromParcel(Parcel source) {
return new PersionParcel(source);
}
};
}
在编写PersionParcel类时应注意如下3点:
PersionParcel类必须实现android.os.Parcelable接口。该接口用于序列化对象。在Android中之所以使用Parcelable接口序列化,而不用java.io.Serializable接口,是因为Google在开发Android时发现Serializable序列化的效率并不高,因此,特意提供了一个Parcelable接口来序列化对象。
在PersionParcel类中必须有一个静态常量,常量名必现是CREATOR,而且CREATOR常量的数据类型必须是Parcelable.Creator。
在writeToParcel方法中需要将要序列化的值写入Parcel对象。
远程服务:
public class AidlService extends Service {
@Override
public IBinder onBind(Intent intent) {
return new AidlBinder();
}
public class AidlBinder extends IPersionBinder.Stub {
@Override
public String getName(PersionParcel p) throws RemoteException {
return p.getName();
}
@Override
public List<PersionParcel> getAllPersions() throws RemoteException {
List<PersionParcel> list = new ArrayList<PersionParcel>();
PersionParcel p = new PersionParcel();
p.setName("zhangsan");
p.setmAge(20);
p.setmSex("boy");
list.add(p);
return list;
}
}
}
其他应用调用,需要将aidl文件拷贝到对应目录下的同时,也需要将PersionParcel.java文件拷贝到对应目录下。
public class MainActivity extends Activity {
private IPersionBinder mBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindAidlService();
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mBinder != null) {
try {
List<PersionParcel> list = mBinder.getAllPersions();
for (PersionParcel item : list) {
System.out.println("姓名:" + item.getName() + ", 年龄:"
+ item.getAge() + ", 性别:" + item.getSex());
System.out.println("姓名:" + mBinder.getName(item));
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mBinder != null) {
unbindService(mConn);
}
mBinder = null;
}
private void bindAidlService() {
Intent service = new Intent("com.example.aidl4.AidlService");
bindService(service, mConn, Context.BIND_AUTO_CREATE);
}
private ServiceConnection mConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinder = IPersionBinder.Stub.asInterface(service);
}
};
}