继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Android中AIDL详细分析

不负相思意
关注TA
已关注
手记 136
粉丝 12
获赞 69
AIDL是什么

AIDL英文全称Android Interface Definition Language,中文Android接口定义语言,在Android中,
AIDL定义了程序访问接口,并将对象进行序列化,通过该接口,使得进程间采用IPC(进程间通信机制,比如binder)
进行交互、传输数据。

AIDL应用场合

a. 在不同应用程序之间,如果客户端需要访问服务端,并且想要处理多线程任务时,采用AIDL;
b. 如果不需要进行跨进程通信,就可以不使用AIDL,比如绑定本地服务,只需继承binder,在
onBind中返回一个binder对象即可;
c. 如果要跨进程通信,但又不需要多线程操作,就使用Messenger方式,实际上Messenger也是基于AIDL的,
只是把AIDL作为底层使用了。Messenger方式中所有的消息存放在一个队列中,每次只允许一个消息待处理。
如果想让服务能够处理多个请求,就使用AIDL。

AIDL和bindservice(又称为bound services)之间的关系

bindservice一般分为两种情况:绑定本地服务;绑定远程服务。
本地服务就是同一个进程中即同一个应用程序中,绑定远程服务指不同进程中,即不同应用程序中。
AIDL一般用在绑定远程服务中,因为这涉及到跨进程操作,需要通过AIDL定义统一接口,传输序列化数据。
注意:大部分应用程序不应该用AIDL来创建bindservice服务,因为多线程处理,让代码变得复杂,不易维护,特殊情况下才使用AIDL。(参考Android官方文档)

创建AIDL服务分为三步:
创建.aidl文件
实现aidl接口
客户端获取接口
为了更加清晰地描述这个过程,本文给出一个实例辅助分析。

案例

定义一个aidl接口displayInformation,用来显示个人的姓名和年龄信息
左边是服务端,右边是客户端,对比红色方框内的内容,aidl包中的文件结构都是一样的。

案例源码下载地址:http://yunpan.cn/cLippY2ib7RHH  访问密码 9ebb
a. 创建接口(创建aidl文件)

创建服务端IPersonInformation.aidl文件,包含一个displayInformation方法,显示个人的姓名和年龄

1

2

3

4

5

6

7

package com.example.person.aidl;

import com.example.person.aidl.Person;

 

interface IPersonInformation

{

     String displayInformation(in Person requester);

}

接口前面不能加访问权限修饰符public、private等。因为displayInformation传递的参数是对象,属于非基本数据类型,需要加上in、out、inout修饰符,其含义是:

如果在客户端输入本地数据,服务端接受数据,就用in修饰符;

如果在客户端接收数据,服务端把本地修改后的数据向客户端传输,就用out修饰符;

如果同时满足in和out,就用inout修饰。

本文中定义的接口displayInformation从客户端接收数据,在服务端组合后返回给客户端,客户端相当于输入,服务端是输出,用in修饰符,即:

1

 String displayInformation(in Person requester);

除了原始基本数据类型(int, long, char, boolean等)、String 、CharSequence以及包含基本数据类型的list和map外,都需要用import语句把对象引用过来,因为person是对象类型,因此用import引入。

一般情况下,Android中远程接口类型名称都用大写的I开头加上接口的名字,这并不是硬性要求,但为了维护程序风格,这样写可读性较高。因为aidl接口都实现IInterface,字母前缀I的含义是IInterface类,表示这是一个可以提供远程服务的类。

b. 实现接口

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

package com.example.person.service;

 

// This file is   StockQuoteService2.java

 

import com.example.person.R;

import android.app.Notification;

import android.app.NotificationManager;

import android.app.PendingIntent;

import android.app.Service;

import android.content.Intent;

import android.os.IBinder;

import android.os.RemoteException;

 

import com.example.person.activity.TestActivity;

import com.example.person.aidl.Person;

import com.example.person.aidl.IPersonInformation;

 

public class PersonInformationService extends Service {

         private NotificationManager notificationMgr;

 

         public class IPersonInformationImpl extends IPersonInformation.Stub {

                  public String displayInformation(Person   person)

                                     throws RemoteException {

                            return "Hello " + person.getName() + "! Your age is: "

                                              + person.getAge();

                  }

         }

 

         @Override

         public void onCreate() {

                  super.onCreate();

 

                  notificationMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

 

                  displayNotificationMessage("onCreate()   called in StockQuoteService2");

         }

 

         @Override

         public void onDestroy() {

                  displayNotificationMessage("onDestroy()   called in StockQuoteService2");

                  //   Clear all notifications from this service

                  notificationMgr.cancelAll();

                  super.onDestroy();

         }

 

         public int onStartCommand(Intent   intent, int flags, int startId) {

                  return super.onStartCommand(intent, flags, startId);

         }

 

         @Override

         public IBinder onBind(Intent   intent) {

                  displayNotificationMessage("onBind()   called in StockQuoteService2");

                  return new IPersonInformationImpl();

         }

 

         private void displayNotificationMessage(String message) {

                  Notification   notification = new Notification(R.drawable.emo_im_happy,

                                     message, System.currentTimeMillis());

 

                  PendingIntent   contentIntent = PendingIntent.getActivity(this, 0,

                                     new Intent(this, TestActivity.class), 0);

 

                  notification.setLatestEventInfo(this, "StockQuoteService2", message,

                                     contentIntent);

 

                  notification.flags = Notification.FLAG_NO_CLEAR;

 

                  notificationMgr.notify(R.id.app_notification_id, notification);

         }

}

主要实现核心代如下:

1

2

3

4

5

6

7

public class IPersonInformationImpl extends IPersonInformation.Stub {

                  public String displayInformation(Person   person)

                                     throws RemoteException {

                            return "Hello " + person.getName() + "! Your age is: "

                                              + person.getAge();

                  }

}

实现类名为IPersonInformationImpl,继承了IPersonInformation.Stub,IPersonInformation.Stub是一个binder接口,如果在eclipse中建立好aidl文件后,编译时会自动生成与aidl同名的java文件IPersonInformation.java,displayInformation为实现的方法。注意,该接口需要Person类,因此还必须把perons类接口文件import进来才能自动生成IPersonInformation.java,下文会提到Person类。

因为传输的对象为Person,非基本数据类型,需要对其序列化,Android中用Parcelable接口来实现,之所以用Parcelable接口,是因为更快、性能更好,Android中进程间通信中大量使用Parcelable接口。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

package com.example.person.aidl;

 

import android.os.Parcel;

import android.os.Parcelable;

 

public class Person implements Parcelable {

 

         private int age;

         private String name;

         public static final Parcelable.Creator<Person> CREATOR =

                  new Parcelable.Creator<Person>() {

                           public Person createFromParcel(Parcel   in) {

                               return new Person(in);

                           }

 

                           public Person[] newArray(int size) {

                               return new Person[size];

                           }

                       };

    public Person() {

    }

 

         private Person(Parcel   in) {

                  readFromParcel(in);

         }

 

         @Override

         public int describeContents() {

                  //   TODO Auto-generated method stub

                  return 0;

         }

 

         @Override

         public void writeToParcel(Parcel   out, int flags) {

                  //   TODO Auto-generated method stub

        out.writeInt(age);

        out.writeString(name);

         }

 

         public void readFromParcel(Parcel   in) {

        age = in.readInt();

        name = in.readString();

         }

 

    public int getAge() {

        return age;

    }

 

    public void setAge(int age) {

        this.age = age;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

}

Parcelable接口必须实现三个方法:

Parcelable.Creator // 用来产生Person对象

describeContents // 返回特殊对象类型,一般返回0

writeToParcel // 把数据写入到Parcel对象中,Parcel中文含义为包裹,形象地表明先把数据包装好,等待传输,在接收方接收后再解压包裹从中得到数据,起到安全性作用。

IPersonInformation.aidl在编译时需要用到待序列化对象Person,因此还需要创建Person.aidl文件,Person类没有具体方法,代码相对简单:

1

2

package com.example.person.aidl;

parcelable Person;

Person类前加parcelable修饰符,表示这是一个待序列化对象。

在eclipse中编译会自动生成IPersonInformation.java,位于gen目录下,这样服务端文件创建成功。

c. 获取接口

客户端要获取服务端接口,先把aidl目录整体拷贝到客户端,

包名com.example.person.aidl也要一致,这个报名和AndroidManifest的包名不是一回事,前者就是文件目录,后者是APP的包名。

创建PersonClientActivity,继承于Activity:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

package com.example.personclient.activity;

 

import com.example.person.aidl.Person;

import com.example.personclient.R;

import com.example.person.aidl.IPersonInformation;

 

import android.app.Activity;

import android.content.ComponentName;

import android.content.Context;

import android.content.Intent;

import android.content.ServiceConnection;

import android.os.Bundle;

import android.os.IBinder;

import android.os.RemoteException;

import android.util.Log;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.Toast;

 

public class PersonClientActivity extends Activity {

 

         protected static final String TAG = "StockQuoteClient2";

         private IPersonInformation iPersonInformation = null;

 

         private Button bindBtn;

         private Button callBtn;

         private Button unbindBtn;

 

         private ServiceConnection serviceConnection = new ServiceConnection() {

 

                  @Override

                  public void onServiceConnected(ComponentName   name, IBinder service) {

                            Log.v(TAG, "---------------service:   " + service.getClass().toString());

                            iPersonInformation = IPersonInformation.Stub.asInterface(service);

                            Log.v(TAG, "---------------stockService:   " + iPersonInformation.getClass().toString());

                            callService();

                  }

 

                  @Override

                  public void onServiceDisconnected(ComponentName   name) {

                            iPersonInformation = null;

                  }

         };

 

         /** Called when the activity is first   created. */

         @Override

         public void onCreate(Bundle   savedInstanceState) {

                  super.onCreate(savedInstanceState);

                  setContentView(R.layout.main);

 

                  bindBtn = (Button) findViewById(R.id.bindBtn);

                  bindBtn.setOnClickListener(buttonClickListener);

 

                  callBtn = (Button) findViewById(R.id.callBtn);

                  callBtn.setOnClickListener(buttonClickListener);

                  callBtn.setEnabled(false);

 

                  unbindBtn = (Button) findViewById(R.id.unbindBtn);

                  unbindBtn.setOnClickListener(buttonClickListener);

                  unbindBtn.setEnabled(false);

 

         }

 

         OnClickListener buttonClickListener = new OnClickListener() {

 

                  @Override

                  public void onClick(View v) {

                            //   TODO Auto-generated method stub

                            if (v.getId() == R.id.bindBtn) {

                                     bindService(new Intent("com.example.person.PersonInformationService"), serviceConnection,

                                                        Context.BIND_AUTO_CREATE);

                                     bindBtn.setEnabled(false);

                                     callBtn.setEnabled(true);

                                     unbindBtn.setEnabled(true);

                            } else if (v.getId() == R.id.callBtn) {

                                     callService();

                            } else if (v.getId() == R.id.unbindBtn) {

                                     unbindService(serviceConnection);

                                     bindBtn.setEnabled(true);

                                     callBtn.setEnabled(false);

                                     unbindBtn.setEnabled(false);

                            }

                  }

 

         };

 

         private void callService() {

                  try {

                            Person   person = new Person();

                            person.setAge(32);

                            person.setName("zhulf");

                            String response = iPersonInformation.displayInformation(person);

                            Toast.makeText(PersonClientActivity.this,

                                              "Value   get from service is: " + response,

                                              Toast.LENGTH_SHORT).show();

                  } catch (RemoteException   ee) {

                            Log.e("MainActivity", ee.getMessage(), ee);

                  }

         }

 

}

核心代码为:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

private ServiceConnection serviceConnection = new ServiceConnection() {

 

                  @Override

                  public void onServiceConnected(ComponentName   name, IBinder service) {

                            Log.v(TAG, "---------------service:   " + service.getClass().toString());

                            iPersonInformation = IPersonInformation.Stub.asInterface(service);

                            Log.v(TAG, "---------------stockService:   " + iPersonInformation.getClass().toString());

                            callService();

                  }

 

                  @Override

                  public void onServiceDisconnected(ComponentName   name) {

                            iPersonInformation = null;

                  }

         };

 

1

2

bindService(new Intent("com.example.person.PersonInformationService"), serviceConnection,

                                                        Context.BIND_AUTO_CREATE);

单击绑定按钮时调用binderservice把serviceConnection与PersonInformationService服务端绑定,当bindservice绑定成功后,系统会调用onServiceConnected方法,第二个参数service是一个IBinder接口对象,由服务端onBind方法返回给客户端的,IPersonInformation.Stub的asInterface返回一个客户端代理对象proxy,赋值给IPersonInformation对象,这样,客户端就获得了服务端接口。

 

d. 使用服务

既然客户端已经获得了服务端的接口对象,那么就可以调用服务端的方法来得到服务。

1

2

3

4

Person   person = new Person();

person.setAge(32);

person.setName("zhulf");

String response = iPersonInformation.displayInformation(person);

先设置person的内容,而后采用服务端对象iPersonInformation调用服务端的方法displayInformation来获得所需要的数据,这可以形象地描述成客户端得到了服务端的服务!

把生成的服务端、客户端apk安装后,打开客户端,如图3所示,点击bind按钮后显示如图4,客户端设置了姓名”jack”,年龄”100″已经通过远程服务接口displayInformation显示出来了。

点击CALL AGAIN按钮后重复显示toast,点击UNBIND按钮后停止服务。

 

AIDL服务的详细执行过程

a. PersonInformationService启动过程

bindService通过Intent的action——”com.example.person.PersonInformationService”启动PersonInformationService服务,服务启动成功后由onBind返回一个IPersonInformationImpl对象,IPersonInformationImpl继承了IPersonInformation.Stub,IPersonInformation.Stub又继承了Binder,Binder实现了IBinder接口,因此,onBind返回的是一个IBinder接口对象,通过添加Logcat打印发现实际返回的是一个BinderProxy对象,这是什么原因?

这是binder进程间通信机制所决定的,服务启动后,系统会生成一个binder代理对象binderProxy,用作桥梁,与C++层的BpBinder对应,在aidl服务中通过binderProxy生成prox客户端代理对象。

b. 客户端获取代理接口

上文提到binderProxy用来生成proxy对象,如何生成?上文提到aidl文件在编译时会自动生成java文件,即IPersonInformation.java,源码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

/*

 * This file is auto-generated.  DO   NOT MODIFY.

 * Original file:   E:\\demos_from_internet\\PersonInformationClient\\PersonInformationClient\\src\\com\\example\\person\\aidl\\IPersonInformation.aidl

 */

package com.example.person.aidl;

 

public interface IPersonInformation extends android.os.IInterface {

         /** Local-side IPC implementation stub class.   */

         public static abstract class Stub extends android.os.Binder   implements com.example.person.aidl.IPersonInformation {

                  private static final java.lang.String DESCRIPTOR = "com.example.person.aidl.IPersonInformation";

 

                  /**   Construct the stub at attach it to the interface. */

                  public Stub() {

                            this.attachInterface(this, DESCRIPTOR);

                  }

 

                  /**

                    * Cast an IBinder object into an

                    * com.example.person.aidl.IPersonInformation   interface, generating a

                    * proxy if needed.

                    */

                  public static com.example.person.aidl.IPersonInformation   asInterface(android.os.IBinder   obj) {

                            if ((obj == null)) {

                                     return null;

                            }

                            android.os.IInterface   iin = obj.queryLocalInterface(DESCRIPTOR);

                            if (((iin != null) && (iin   instanceof com.example.person.aidl.IPersonInformation))) {

                                     return ((com.example.person.aidl.IPersonInformation) iin);

                            }

                            return new com.example.person.aidl.IPersonInformation.Stub.Proxy(obj);

                  }

 

                  @Override

                  public android.os.IBinder   asBinder() {

                            return this;

                  }

 

                  @Override

                  public boolean onTransact(int code, android.os.Parcel   data, android.os.Parcel   reply, int flags)

                                     throws   android.os.RemoteException {

                            switch (code) {

                            case INTERFACE_TRANSACTION: {

                                     reply.writeString(DESCRIPTOR);

                                     return true;

                            }

                            case TRANSACTION_displayInformation: {

                                     data.enforceInterface(DESCRIPTOR);

                                     com.example.person.aidl.Person   _arg0;

                                     if ((0 != data.readInt())) {

                                               _arg0 = com.example.person.aidl.Person.CREATOR.createFromParcel(data);

                                     } else {

                                              _arg0 = null;

                                     }

                                     java.lang.String _result = this.displayInformation(_arg0);

                                     reply.writeNoException();

                                     reply.writeString(_result);

                                     return true;

                            }

                            }

                            return super.onTransact(code, data, reply, flags);

                  }

 

                  private static class Proxy implements com.example.person.aidl.IPersonInformation {

                            private android.os.IBinder   mRemote;

 

                            Proxy(android.os.IBinder   remote) {

                                     mRemote = remote;

                            }

 

                            @Override

                            public android.os.IBinder   asBinder() {

                                     return mRemote;

                            }

 

                            public java.lang.String getInterfaceDescriptor() {

                                     return DESCRIPTOR;

                            }

 

                            @Override

                            public java.lang.String displayInformation(com.example.person.aidl.Person   requester)

                                              throws   android.os.RemoteException {

                                     android.os.Parcel   _data = android.os.Parcel.obtain();

                                     android.os.Parcel   _reply = android.os.Parcel.obtain();

                                     java.lang.String _result;

                                     try {

                                              _data.writeInterfaceToken(DESCRIPTOR);

                                              if ((requester != null)) {

                                                        _data.writeInt(1);

                                                        requester.writeToParcel(_data, 0);

                                              } else {

                                                        _data.writeInt(0);

                                              }

                                              mRemote.transact(Stub.TRANSACTION_displayInformation, _data, _reply, 0);

                                              _reply.readException();

                                              _result = _reply.readString();

                                     } finally {

                                              _reply.recycle();

                                              _data.recycle();

                                     }

                                     return _result;

                            }

                  }

 

                  static final int TRANSACTION_displayInformation = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);

         }

 

         public java.lang.String displayInformation(com.example.person.aidl.Person   requester)

                            throws   android.os.RemoteException;

}

该文件自动生成后,系统分别创建两个对象:服务端Stub、客户端Proxy。服务端、客户端分别都由这两个对象代理操作,那客户端Proxy如何获得?这就是asInterface方法的作用。

1

iPersonInformation = IPersonInformation.Stub.asInterface(service);

1

2

3

4

5

6

7

8

9

10

public static com.example.person.aidl.IPersonInformation   asInterface(android.os.IBinder   obj) {

                            if ((obj == null)) {

                                     return null;

                            }

                            android.os.IInterface   iin = obj.queryLocalInterface(DESCRIPTOR);

                            if (((iin != null) && (iin   instanceof com.example.person.aidl.IPersonInformation))) {

                                     return ((com.example.person.aidl.IPersonInformation) iin);

                            }

                            return new com.example.person.aidl.IPersonInformation.Stub.Proxy(obj);

                  }

queryLocalInterface返回IInterface接口对象,再判断该对象实际类型是不是IPersonInformation类型,如果是就返回该对象,否则就new一个Proxy对象。参数obj是一个binderProxy对象,其queryLocalInterface方法源码为:

1

2

3

public IInterface queryLocalInterface(String descriptor) {

        return null;

}

该方法什么都没做,直接返回空值,那么iin为空,跳过了下面的if语句:

1

2

3

if (((iin != null) && (iin   instanceof com.example.person.aidl.IPersonInformation))) {

         return ((com.example.person.aidl.IPersonInformation) iin);

}

继续执行:

1

return new com.example.person.aidl.IPersonInformation.Stub.Proxy(obj);

创建一个包含binderProxy对象的Proxy对象。

asInterface方法的主要作用:如果是多进程操作,参数obj是binderProxy对象,就new一个proxy接口;如果是当前进程操作,obj是本地binder对象,就返回本地binder对象,这种情况不存在多进程通信。

Proxy类构造方法为:

1

2

3

Proxy(android.os.IBinder   remote) {

         mRemote = remote;

}

把binderProxy对象保存到mRemote变量,mRemote在aidl中是一个辅助变量。

这样就获得了客户端代理接口proxy。

c. 通过代理接口获得服务

标题叫“通过代理接口获得服务”,意思是proxy调用displayInformation方法获得结果的过程,当系统执行到:

1

String response = iPersonInformation.displayInformation(person);

iPersonInformation变量保存了proxy对象,displayInformation方法的“中间实现”情况为:

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

@Override

            public java.lang.String   displayInformation(com.example.person.aidl.Person requester)

                    throws android.os.RemoteException {

                android.os.Parcel   _data = android.os.Parcel.obtain();

                android.os.Parcel   _reply = android.os.Parcel.obtain();

                java.lang.String   _result;

                try {

                    _data.writeInterfaceToken(DESCRIPTOR);

                    if ((requester != null)) {

                        _data.writeInt(1);

                        requester.writeToParcel(_data,   0);

                    }   else {

                        _data.writeInt(0);

                    }

                    mRemote.transact(Stub.TRANSACTION_displayInformation,   _data, _reply, 0);

                    _reply.readException();

                    _result   = _reply.readString();

                }   finally {

                    _reply.recycle();

                    _data.recycle();

                }

                return _result;

}

 

之所以叫中间实现,是因为displayInformation的最终实现代码在IPersonInformationImpl中,此处只是中间状态。静态方法obtain从Parcel池中获得一个Parcel对象分别保存到_data、_reply中,_data、_reply分别是发送数据和接受数据时的承载器、包裹。writeInterfaceToken写入一个字符串标记,writeInt写入一个标志位,writeToParcel把Person对象中的数据写入到parcel中,然后执行:

1

mRemote.transact(Stub.TRANSACTION_displayInformation, _data, _reply, 0);

客户端对象mRemote(就是binderProxy)调用transact方法向服务端发送请求,第一个参数就是请求命令号,服务端根据这个命令号找到相应的执行方法。

transact方法进入到C++层,交由BpBinder处理,最终经过binder驱动处理后,转交给binder服务端,服务端层层调用到java层,由java层的服务端对象stub的onTransact方法处理:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

@Override

                  public boolean onTransact(int code, android.os.Parcel   data, android.os.Parcel   reply, int flags)

                                     throws   android.os.RemoteException {

                            switch (code) {

                            case INTERFACE_TRANSACTION: {

                                     reply.writeString(DESCRIPTOR);

                                     return true;

                            }

                            case TRANSACTION_displayInformation: {

                                     data.enforceInterface(DESCRIPTOR);

                                     com.example.person.aidl.Person   _arg0;

                                     if ((0 != data.readInt())) {

                                              _arg0 = com.example.person.aidl.Person.CREATOR.createFromParcel(data);

                                     } else {

                                              _arg0 = null;

                                     }

                                     java.lang.String _result = this.displayInformation(_arg0);

                                     reply.writeNoException();

                                     reply.writeString(_result);

                                     return true;

                            }

                            }

                            return super.onTransact(code, data, reply, flags);

}

根据客户端发送请求的命令号TRANSACTION_displayInformation找到case子句,首先由enforceInterface方法读出客户端写入的字符串,验证是否正确。readInt读出标志位,如果是1,就重新组建序列化的Person对象保存到_arg0中。

1

java.lang.String _result = this.displayInformation(_arg0);

this表示当前正在运行的的对象,就是stub对象,在服务端IPersonInformationImpl实现了stub,因此,this就是IPersonInformationImpl对象,进程执行到了:

1

2

3

public String displayInformation(Person   person) throws RemoteException {

         return "Hello " + person.getName() + "! Your age is: " + person.getAge();

}

这个方法就是返回一段字符串,保存到_result变量中。

1

reply.writeString(_result);

writeString方法把结果存到parcel对象中,再次通过进程间通信机制,穿过Binder驱动,C++层,返回到客户端的transact中,客户端从返回的parcel对象中读出返回值,最终返回到PersonClientActivity的这句话:

1

String response = iPersonInformation.displayInformation(person);

就是把结果保存到response里面。

这就完成了客户端、服务端进程全部通信过程,

途中双向箭头表示数据双向传输,发送到服务端后,服务端把处理后的数据又返回给客户端。

 

aild可以说是应用层为了实现两个不同应用程序通信来设计的,用户设计统一的接口方法,然后由系统自动生成java文件,并提供了服务端和客户端代理,客户端通过代理来访问服务端。

原文链接:http://www.apkbus.com/blog-705730-61237.html

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP