AIDL简介
AIDL是 Android Interface Definition Language的缩写。AIDL 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行 IPC的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。
这里我们需要建立两个工程,一个作为客户端,另外一个作为服务端。
一、建立客户端的工程,结构如下:
首先新建一个package(com.zjt.myaidl)。在该package中新建一个名为IMyService.aidl的文件。如下:
package com.zjt.myaidl;
import com.zjt.myaidl.Person;
interface IMyService{
List<Person> getPerson();
void addPerson(in Person person);
}
说明:
AIDL支持java基本类型如: int, long,double, char, boolean等。其他类型必须要用import 导入,即使是在同一个包中。比如本工程中IMyService和Person是在同一个包中。
另外,接口中的参数除了aidl支持的类型,其他类型必须标识其方向:到底是输入还是输出抑或两者兼之,用in,out或者inout来表示,上面的代码我们用in标记,因为它是输入型参数。
如果需要访问自定义对象,还需要建立对象的aidl文件,这里我们由于使用了自定义对象Person,所以还需建立一个Person.aidl文件。
由于使用了自定义对象Person,那么需要对该对象进行序列化。这里我们让Person 类实现Parcelable接口。
Person.java:
public class Person implements Parcelable {
private String name ;
private int age;
private String sex;
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;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Person(String name,int age , String sex){
this.name = name;
this.age = age;
this.sex = sex;
}
public Person(){
}
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
Log.e("xxx", "writeToParcel");
//这里字段写的顺序要和下面读的顺序要一致,从name、age到sex
dest.writeString(name);
dest.writeInt(age);
dest.writeString(sex);
}
public static final Parcelable.Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person[] newArray(int size) {
// TODO Auto-generated method stub
return new Person[size];
}
@Override
public Person createFromParcel(Parcel source) {
// TODO Auto-generated method stub
Person person = new Person();
//这里字段读的顺序要和下面写的顺序要一致,从name、age到sex
person.name = source.readString();
person.age = source.readInt();
person.sex = source.readString();
return person;
}
};
}
Person.aidl文件很简单,如下所示,要注意的是 这里parcelable是个类型,首字母是小写的,和Parcelable接口不是一个东西。
package com.zjt.myaidl;
parcelable Person;
二、建立服务端的Service,MyService.java文件如下:
public class MyService extends Service{
//private IBinder mBinder;
private List<Person> mPersons = new ArrayList<Person>();
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return mBinder;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Person mPerson = new Person("zjt", 28, "male");
mPersons.add(mPerson);
}
//在这里实现aidl中的抽象方法
private final IMyService.Stub mBinder = new IMyService.Stub() {
@Override
public List<Person> getPerson() throws RemoteException {
// TODO Auto-generated method stub
synchronized (mPersons) {
return mPersons;
}
}
@Override
public void addPerson(Person person) throws RemoteException {
// TODO Auto-generated method stub
synchronized (mPersons) {
if(!mPersons.contains(person)){
mPersons.add(person);
}
}
}
};
三、在AndroidManifest.xml文件中声明Service:
<service android:name="com.example.myaidlactivity.MyService"
android:process=":remote"
android:enabled="true">
<intent-filter >
<category
android:name="android.intent.category.DEFAULT"/>
<action
android:name="com.example.myservice.action"/>
</intent-filter>
</service>
说明:上述的 是为了能让其他apk通过action来隐式启动bindService,通过隐式调用的方式来起activity或者service,需要把category设为default,这是因为,隐式调用的时候,intent中的category默认会被设置为default。
以上完成后,新建一个工程来充当客户端。
四、新建一个工程来充当客户端。
1.新建一个名为TestAidlClient的工程充当客户端。把上面的服务端中整个package(com.zjt.myaidl)copy到本项目的src目录下,
工程结构如下:
这个时候,客户端com.zjt.myaidl包是和服务端工程完全一样的。
MainActivity.java:
public class MainActivity extends Activity {
private IMyService myService;
private List<Person> mPersons = new ArrayList<Person>();
private Button bindService;
private final static String SERVICE_ACTION = "com.example.myservice.action";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService = (Button) findViewById(R.id.bindService);
bindService.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent mIntent = new Intent(SERVICE_ACTION);
bindService(mIntent, mServiceConnection, BIND_AUTO_CREATE);
}
});
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
myService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
//通过服务端onBind方法返回的binder对象得到IMyService的实例,得到实例就可以调用它的方法了
myService = IMyService.Stub.asInterface(service);
try {
//通过IMyService接口来添加Person对象
myService.addPerson(new Person("wj", 26, "female"));
mPersons = myService.getPerson();
for(int i=0; i<mPersons.size();i++){
Person person = mPersons.get(i);
Log.e("----", "name = "+person.getName()+"\n age = "+person.getAge()+"\n sex = "+person.getSex());
Log.d("...", ".............");
}
} catch (Exception e) {
// TODO: handle exception
}
}
};
}
运行结果如下:
可以看到我们通过aidl的方式获取到另一apk的数据。
源码下载地址:http://download.csdn.net/detail/zhujiangtaotaise/9384987