Android 接口定义语言 (AIDL)–传递对象
通过 IPC 传递对象
通过 IPC 接口把某个类从一个进程发送到另一个进程是可以实现的。 不过,您必须确保该类的代码对 IPC 通道的另一端可用,并且该类必须支持 Parcelable 接口(也可支持java的Serializable序列化接口)。支持 Parcelable 接口很重要,因为 Android 系统可通过它将对象分解成可编组到各进程的原语。
如需创建支持 Parcelable 协议的类
您必须执行以下操作:
1.让您的类实现 Parcelable 接口。
2.实现 writeToParcel,它会获取对象的当前状态并将其写入 Parcel。
3.为您的类添加一个名为 CREATOR 的静态字段,这个字段是一个实现 Parcelable.Creator 接口的对象。
//Person.java
public class Person implements Parcelable {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
protected Person(Parcel in) {
//读的顺序必须和写的顺序一致
this.name = in.readString();
this.age = in.readInt();
}
public Person(String name, int age) {
//读的顺序必须和写的顺序一致
this.name = name;
this.age = age;
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@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 dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
@Override
public String toString() {
return "[name:" + name + "age:" + age + "]";
}
}
- 4.最后,创建一个声明可打包类的 .aidl 文件(按照下文 Rect.aidl 文件所示步骤)。
// Person21.aidl
package com.example.admin.aidlservice;
//声明Person
parcelable Person;
如图:
给出IRemoteService.aidl代码
//IRemoteService.aidl
package com.example.admin.aidlservice;
//就算在同一个包下也需要导包
import com.example.admin.aidlservice.Person;
interface IRemoteService {
//不是基本类型的参数需要表明方向(in/out...)
List<Person> add(in Person person);
}
调用 IPC 方法
调用类必须执行以下步骤,才能调用使用 AIDL 定义的远程接口:
- 1.在项目 src/ 目录中加入 .aidl 文件。
- 2.声明一个 IBinder 接口实例(基于 AIDL 生成)。
- 3.实现 ServiceConnection。
- 4.调用 Context.bindService(),以传入您的 ServiceConnection 实现。
- 5.在您的 onServiceConnected() 实现中,您将收到一个 IBinder 实例(名为 service)。调用 IRemoteService.Stub.asInterface((IBinder)service),以将返回的参数转换为 YourInterface 类型。
- 6.调用您在接口上定义的方法。您应该始终捕获 DeadObjectException 异常,它们是在连接中断时引发的;这将是远程方法引发的唯一异常。
- 7.如需断开连接,请使用您的接口实例调用 Context.unbindService()。
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "lynnlee36";
private ArrayList<Person> persons;
private IRemoteService iRemoteService;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iRemoteService = IRemoteService.Stub.asInterface(service);
addPerson();
}
@Override
public void onServiceDisconnected(ComponentName name) {
iRemoteService = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService();
}
public void addPerson(View view) {
addPerson();
}
private void addPerson() {
try {
persons = (ArrayList<Person>) iRemoteService.add(new Person("lucy", 23));
Log.i(TAG, "调用远程服务,结果是:" + persons.toString());
} catch (RemoteException e) {
e.printStackTrace();
Log.i(TAG, "执行失败!");
}
}
private void bindService() {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.example.admin.aidlservice", "com.example.admin.aidlservice.RemoteService"));
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
}