Android进程间通信之使用AIDL

AIDLAndroid Interface Definition Language ,可实现进程间的通信,并且允许多线程访问。(如果需要进程间通信,又不需要处理多线程访问,那么使用Messenger的方式更为合适),实现AIDL,需要以下几个步奏。

1.定义AIDL接口

 

AIDL接口使用后缀名为.aidl的文件来定义(例如创建一个IRemoteData.aidl),使用java语法来编写,在编译时,Android sdk工具会在/gen目录下生成一个java文件(IRemoteData.java),此文件内有一个静态内部抽象类Stub,继承了Binder类并实现了接口(IRemoteData)。它提供了一个asInterface(android.os.IBinder obj)IBinder对象转换成我们声明的接口类型(实际上就是在Service端对Stub的实现)。

 

AIDL支持以下五种数据类型:java基本数据类型(int,char,boolean)StringCharSequenceListMap。如果你要在AIDL中使用其他数据类型,那么必须使用import导入,即使该类型和aidl处于同一包中。其次,所有非原始数据类型都必须指定参数方向,传入参数用关键字in表示,传出参数用out,传入传出参数用inout,基本数据类型都是传入值。

 

 1 package com.young.testserver.aidl;

 2 

 3 import com.young.testserver.aidl.Person;

 4 

 5 interface IRemoteData {

 6     int getRemoteData();

 7     void setRemoteData(int data);

 8     

 9     Person getPerson();

10     void setPerson(in Person person);

11 }

由于该aidl文件中使用了非原始数据类型Person,所以需要创建一个aidl文件对Person进行声明

1 package com.young.testserver.aidl;

2 

3 parcelable Person;

2.创建服务端Service,将我们对AIDL接口的实现通过onBind()方法返出去。

 1 public class AidlRemoteService extends Service {

 2 

 3     // IRemoteData.Stub的具体实现

 4     private class RemoteData extends IRemoteData.Stub {

 5         int data;

 6         Person person;

 7         @Override

 8         public int getRemoteData() throws RemoteException {

 9             return data;

10         }

11 

12         @Override

13         public void setRemoteData(int data) throws RemoteException {

14             this.data = data;

15         }

16 

17         @Override

18         public Person getPerson() throws RemoteException {

19             return person;

20         }

21 

22         @Override

23         public void setPerson(Person person) throws RemoteException {

24             this.person = person;

25         }

26 

27     }

28 

29     @Override

30     public IBinder onBind(Intent intent) {

31         // 将实现的IRemoteData.Stub类返出去,客户端可以使用Stub提供的asInterface获得

32         return new RemoteData();

33     }

34 }

3.将服务端对应的aidl文件与java文件拷贝到客户端,在客户端绑定服务时,使用Stub类提供的asInterface获取服务端实现的接口类,然后使用这个已实现的接口类就可以调用AIDL中的函数。

 1 public class AidlClientActivity extends Activity {

 2 

 3     private static final String TAG = "--DEBUG--";

 4   

 5     private static final String BIND_ACTION = "com.young.server.START_AIDL_SERVICE";

 6     private Button mBindBtn;

 7 

 8     @Override

 9     protected void onCreate(Bundle savedInstanceState) {

10         super.onCreate(savedInstanceState);

11         setContentView(R.layout.activity_aidl_client);

12 

13         mBindBtn = (Button) findViewById(R.id.bind_service);

14         mBindBtn.setOnClickListener(new OnClickListener() {

15             @Override

16             public void onClick(View v) {

17                 bindService(new Intent(BIND_ACTION), conn, Context.BIND_AUTO_CREATE);

18             }

19         });

20     }

21 

22     private ServiceConnection conn = new ServiceConnection() {

23 

24         @Override

25         public void onServiceDisconnected(ComponentName name) {

26             Log.v(TAG, "AIDL 服务已断开");

27         }

28 

29         @Override

30         public void onServiceConnected(ComponentName name, IBinder service) {

31             Log.v(TAG, "AIDL 服务已链接");

32 

33             // 获得服务端对Stub的实现

34             IRemoteData remoteData = IRemoteData.Stub.asInterface(service);

35             try {

36                 remoteData.setRemoteData(123456);

37                 int data = remoteData.getRemoteData();

38                 Log.v(TAG, "client get remote data=" + data);

39 

40                 remoteData.setPerson(new Person("Allen", 25));

41                 Person person = remoteData.getPerson();

42                 Log.v(TAG, "client get remote Person=" + person.toString());

43             } catch (RemoteException e) {

44                 e.printStackTrace();

45             }

46         }

47     };

48 }

4.通过AIDL在进程间传递对象,需要符合以下几点要求

(1)实现Parcelable接口。

(2)实现writeToParcel方法,以便将当前对象状态写入Parcel中。

(3)增加一个名为CREATOR的静态变量,实现Parcelable.Creator<T>接口

(4)创建一个AIDL文件来声明这个类(见上文的Person.aidl)

 1 public class Person implements Parcelable {

 2     

 3     private String name;

 4     private int age;

 5     

 6     public Person(String name, int age) {

 7         super();

 8         this.name = name;

 9         this.age = age;

10     }

11 

12     public String getName() {

13         return name;

14     }

15 

16     public void setName(String name) {

17         this.name = name;

18     }

19 

20     public int getAge() {

21         return age;

22     }

23 

24     public void setAge(int age) {

25         this.age = age;

26     }

27 

28     @Override

29     public String toString() {

30         return "Person [name=" + name + ", age=" + age + "]";

31     }

32 

33     // -------------分割线---------------

34 

35     // 注意读入和写出顺序

36     public Person(Parcel parcel) {

37         name = parcel.readString();

38         age = parcel.readInt();

39     }

40 

41     public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {

42 

43         @Override

44         public Person createFromParcel(Parcel source) {

45             return new Person(source);

46         }

47 

48         @Override

49         public Person[] newArray(int size) {

50             return new Person[size];

51         }

52 

53     };

54 

55     @Override

56     public int describeContents() {

57         return 0;

58     }

59 

60     @Override

61     public void writeToParcel(Parcel dest, int flags) {

62         dest.writeString(name);

63         dest.writeInt(age);

64     }

 

最后运行程序,打印日志结果如下,客户端取到了从客户端传给服务端的数据。

11-13 15:56:23.081: V/--DEBUG--(25361): AIDL 服务已链接
11-13 15:56:23.081: V/--DEBUG--(25361): client get remote data=123456
11-13 15:56:23.081: V/--DEBUG--(25361): client get remote Person=Person [name=Allen, age=25]

你可能感兴趣的:(android)