您的位置:首页 > 移动开发 > Android开发

android 使用AIDL实现进程间通信

2012-02-19 20:19 585 查看
一、编写服务端代码

1. 首先编写AndroidManifest.xml文件:

01

<?xml version="1.0" encoding="utf-8"?>

02

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

03

      package="com.braincol.aidl.service"

04

      android:versionCode="1"

05

      android:versionName="1.0">

06

    <uses-sdk android:minSdkVersion="8" />

07

 

08

    <application android:icon="@drawable/icon" android:label="@string/app_name">

09

 

10

    <service android:name="RemoteService">

11

        <intent-filter>

12

            <action android:name="com.braincol.aidl.remote.webpage"/>

13

        </intent-filter>

14

    </service>

15

 

16

    </application>

17

</manifest>

 

可以看到服务端的包名为:com.braincol.aidl.service,且该服务端只需一个service组件提供AIDL服务,service组件的名称为RemoteService,这是待会要实现的Service子类。其中<action android:name="com.braincol.aidl.remote.webpage"/> ,指定了action名称为"com.braincol.aidl.remote.webpage", 客户端会通过该action的名称来找到并连接该服务端。

2. 创建RemoteWebPage.aidl文件

在包com.braincol.aidl.service下创建RemoteWebPage.aidl文件:

1

package com.braincol.aidl.service;

2

 interface RemoteWebPage {

3

    String getCurrentPageUrl();    

4

}

可以看到内容很简单,该文件中包含一个RemoteWebPage 接口,并且接口中只有getCurrentPageUrl()这么一个方法,后面的客户端将通过这里提供的getCurrentPageUrl()方法获取想要的信息。

3.生成RemoteWebPage.java文件

保存并编译该工程(在eclipse中编译)会看到 gen/ 目录下的com.braincol.aidl.service包下出现了一个RemoteWebPage.java文件:

01

/*

02

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

03

 * Original file: F:\\workspace\\android\\AIDL-simple\\AIDLService\\src\\com\\braincol\\aidl\\service\\RemoteWebPage.aidl

04

 */

05

package com.braincol.aidl.service;

06

public interface RemoteWebPage extends android.os.IInterface

07

{

08

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

09

    public static abstract class Stub extends android.os.Binder implements com.braincol.aidl.service.RemoteWebPage

10

    {

11

        private static final java.lang.String DESCRIPTOR = "com.braincol.aidl.service.RemoteWebPage";

12

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

13

        public Stub()

14

        {

15

            this.attachInterface(this, DESCRIPTOR);

16

        }

17

        /**

18

         * Cast an IBinder object into an com.braincol.aidl.service.RemoteWebPage interface,

19

         * generating a proxy if needed.

20

         */

21

        public static com.braincol.aidl.service.RemoteWebPage asInterface(android.os.IBinder obj)

22

        {

23

            if ((obj==null)) {

24

                return null;

25

            }

26

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

27

            if (((iin!=null)&&(iin instanceof com.braincol.aidl.service.RemoteWebPage))) {

28

                return ((com.braincol.aidl.service.RemoteWebPage)iin);

29

            }

30

            return new com.braincol.aidl.service.RemoteWebPage.Stub.Proxy(obj);

31

        }

32

        public android.os.IBinder asBinder()

33

        {

34

            return this;

35

        }

36

        @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException

37

        {

38

            switch (code)

39

            {

40

            case INTERFACE_TRANSACTION:

41

            {

42

                reply.writeString(DESCRIPTOR);

43

                return true;

44

            }

45

            case TRANSACTION_getCurrentPageUrl:

46

            {

47

                data.enforceInterface(DESCRIPTOR);

48

                java.lang.String _result = this.getCurrentPageUrl();

49

                reply.writeNoException();

50

                reply.writeString(_result);

51

                return true;

52

            }

53

            }

54

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

55

        }

56

        private static class Proxy implements com.braincol.aidl.service.RemoteWebPage

57

        {

58

            private android.os.IBinder mRemote;

59

            Proxy(android.os.IBinder remote)

60

            {

61

                mRemote = remote;

62

            }

63

            public android.os.IBinder asBinder()

64

            {

65

                return mRemote;

66

            }

67

            public java.lang.String getInterfaceDescriptor()

68

            {

69

                return DESCRIPTOR;

70

            }

71

            public java.lang.String getCurrentPageUrl() throws android.os.RemoteException

72

            {

73

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

74

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

75

                java.lang.String _result;

76

                try {

77

                    _data.writeInterfaceToken(DESCRIPTOR);

78

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

79

                    _reply.readException();

80

                    _result = _reply.readString();

81

                }

82

                finally {

83

                    _reply.recycle();

84

                    _data.recycle();

85

                }

86

                return _result;

87

            }

88

        }

89

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

90

    }

91

    public java.lang.String getCurrentPageUrl() throws android.os.RemoteException;

92

}

这个文件是Android SDK工具根据RemoteWebPage.aidl自动生成的,不要尝试着去修改该文件(改了也白改)。可以看到RemoteWebPage接口内包含了一个名为Stub的抽象的内部类,该类声明了RemoteWebPage.aidl中描述的方法getCurrentPageUrl(),并且还定义了少量的辅助方法Stub还定义了少量的辅助方法,尤其是asInterface(),通过它或以获得IBinder(当applicationContext.bindService()成功调用时传递到客户端的onServiceConnected())并且返回用于调用IPC方法的接口实例,更多细节参见Calling an IPC Method

4. 编写RemoteService.java

为了实现AIDL通信,必须在RemoteService类中实现RemoteWebPage.Stub接口,然后RemoteWebPage.Stbu内的相关方法,下面是RemoteService.java的代码:

01

package com.braincol.aidl.service;

02

 

03

import android.app.Service;

04

import android.content.Intent;

05

import android.os.IBinder;

06

import android.os.RemoteException;

07

import android.util.Log;

08

/**

09

 *

10

 * @author briancol

11

 * @description 提供service

12

 *

13

 */

14

public class RemoteService extends Service {

15

    private final static String TAG = "RemoteService";

16

    @Override

17

    public IBinder onBind(Intent intent) {

18

        Log.i(TAG, "OnBind");

19

        return new MyBinder();

20

    }

21

 

22

    private class MyBinder extends RemoteWebPage.Stub{

23

        @Override

24

        public String getCurrentPageUrl() throws RemoteException{

25

            return "http://www.cnblogs.com/hibraincol/";

26

        }

27

    }

28

}

这样MyBinder就是一个RemoteWebPage.Stub类得子类,这样就可以通过RemoteService向客户端暴露AIDL接口了(MyBinder )。现在,如果客户端(比如一个Activity)调用bindService()来连接该服务端(RemoteService) ,客户端的onServiceConnected()回调函数将会获得从服务端(RemoteService )的onBind()返回的MyBinder对象。

在这里总结下服务端的编写流程:

    1. 创建.aidl文件:

        该文件(YourInterface.aidl)定义了客户端可用的方法和数据的接口

    2. 实现这个接口:

        Android SDK将会根据你的.aidl文件产生AIDL接口。生成的接口包含一个名为Stub的抽象内部类,该类声明了所有.aidl中描述的方法,你必须在代码里继承该Stub类并且实现.aidl中定义的方法。

    3.向客户端公开服务端的接口:

        实现一个Service,并且在onBinder方法中返回第2步中实现的那个Stub类的子类(实现类)。

 

至此,服务端的代码就编写完成了。 下面开始编写客户端。

二、编写客户端代码

因为客户端和服务端不在同一个进程(应用程序)中,那么客户端也必须在src/目录下拥有和服务端同样的一份.aidl文件的拷贝(这样的同样是指:包名、类名、内容完全一样,可以把客户端的.aidl文件理解为代理),这样客户端将会通过这个RemoteWebPage.aidl文件在gen/目下生成和服务端一样的RemoteWebPage.java文件,然后客户端就可以通过该接口来访问服务端提供的方法了。下面是客户端的只要代码:

01

package com.braincol.aidl.client;

02

 

03

import android.app.Activity;

04

import android.content.ComponentName;

05

import android.content.Context;

06

import android.content.Intent;

07

import android.content.ServiceConnection;

08

import android.os.Bundle;

09

import android.os.IBinder;

10

import android.os.RemoteException;

11

import android.util.Log;

12

import android.view.View;

13

import android.view.View.OnClickListener;

14

import android.widget.Button;

15

import android.widget.TextView;

16

import com.braincol.aidl.service.RemoteWebPage;

17

 

18

public class ClientActivity extends Activity implements OnClickListener {

19

    private final static String TAG="ClientActivity";

20

    TextView textView ;

21

    Button btn_bind ;

22

    Button btn_getAllInfo;

23

    String actionName = "com.braincol.aidl.remote.webpage";

24

    RemoteWebPage remoteWebPage=null;

25

    String allInfo = null;

26

    boolean isBinded=false;

27

 

28

    @Override

29

    public void onCreate(Bundle savedInstanceState) {

30

        super.onCreate(savedInstanceState);

31

        setContentView(R.layout.main);

32

        textView = (TextView) findViewById(R.id.textView);

33

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

34

        btn_getAllInfo = (Button)findViewById(R.id.btn_allinfo);

35

 

36

        btn_getAllInfo.setEnabled(false);

37

 

38

        btn_bind.setOnClickListener(this);

39

        btn_getAllInfo.setOnClickListener(this);

40

    }

41

    @Override

42

    protected void onPause(){

43

        super.onPause();

44

        Log.d(TAG,"onPause");

45

        if(isBinded){

46

            Log.d(TAG,"unbind");

47

            unbindService(connection);   

48

        }

49

    }

50

    private class MyServiceConnection implements ServiceConnection{

51

 

52

        @Override

53

        public void onServiceConnected(ComponentName name, IBinder service) {

54

            Log.i(TAG, "建立连接...");

55

            remoteWebPage = RemoteWebPage.Stub.asInterface(service);

56

            if(remoteWebPage==null){

57

                textView.setText("bind service failed!");   

58

                return;

59

            }

60

            try {

61

                isBinded=true;

62

                btn_bind.setText("断开");

63

                textView.setText("已连接!");

64

                allInfo = remoteWebPage.getCurrentPageUrl();

65

                btn_getAllInfo.setEnabled(true);   

66

            } catch (RemoteException e) {

67

                e.printStackTrace();

68

            }

69

        }

70

 

71

        @Override

72

        public void onServiceDisconnected(ComponentName name) {

73

            Log.i(TAG, "onServiceDisconnected...");

74

        }

75

 

76

    }

77

    MyServiceConnection connection = new MyServiceConnection();

78

 

79

    @Override

80

    public void onClick(View v) {

81

        if(v==this.btn_bind){

82

            if(!isBinded){

83

                Intent intent  = new Intent(actionName);

84

                bindService(intent, connection, Context.BIND_AUTO_CREATE);               

85

            }else{

86

                Log.i(TAG, "断开连接...");

87

                unbindService(connection);

88

                btn_getAllInfo.setEnabled(false);   

89

                btn_bind.setText("连接");

90

                isBinded = false;

91

                textView.setText("已断开连接!");

92

            }

93

        }else if(v==this.btn_getAllInfo){

94

            textView.setText(allInfo);

95

        }

96

 

97

    }

98

}

 

上面的代码中类MyServiceConnection实现了ServiceConnection类,在MyServiceConnection类的onServiceConnected方法中通过RemoteWebPage.Stub.asInterface(service)获取到远端服务端的RemoteWebPage接口对象remoteWebPage,这样就可以通过remoteWebPage.getCurrentPageUrl()获取到服务端提供的相关的信息。客户端通过bindService()方法绑定远程服务端,通过unbindService()断开连接。连接客户端的相关的代码为:

1

Intent intent  = new Intent(actionName);

2

bindService(intent, connection, Context.BIND_AUTO_CREATE);

客户端就是通过actionName(com.braincol.aidl.remote.webpage)来找到服务端。

下面总结下客户端的编写流程:

    1. 在 src/ 目录下包含.adil文件。

    2. 声明一个IBinder接口(通过.aidl文件生成的)的实例。

    3. 实现ServiceConnection.

    4. 调用Context.bindService()绑定你的ServiceConnection实现类的对象(也就是远程服务端)。

    5. 在onServiceConnected()方法中会接收到IBinder对象(也就是服务端),调用YourInterfaceName.Stub.asInterface((IBinder)service)将返回值转换为YourInterface类型。

    6. 调用接口中定义的方法,并且应该总是捕获连接被打断时抛出的DeadObjectException异常,这是远端方法可能会抛出唯一异常。

    7. 调用Context.unbindService()方法断开连接。

 

下面给出本示例源码的下载地址:

http://download.csdn.net/detail/Niosm/3593187

在附一个稍微复杂点的例子(通过IPC传递Parcelable对象):

http://download.csdn.net/detail/Niosm/3593376

摘自:http://www.cnblogs.com/hibraincol/archive/2011/09/11/2173780.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息