AIDL实现进程间通信

关于AIDL的介绍及实现步调等请参考:

http://www.cnblogs.com/hibraincol/archive/2011/09/06/2169325.html

本篇文章只是用一个实例来解析AIDL的实现。

本示例实现的是:AIDL客户端经由过程AIDL接口获取AIDL办事端中供给的webPage信息,下面胪陈AIDL通信的实现步调:

 



2. 创建RemoteWebPage.aidl文件



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



package com.braincol.aidl.service;

 interface RemoteWebPage {

    String getCurrentPageUrl();     

}



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



3.生成RemoteWebPage.java文件



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



/*

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

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

 */

package com.braincol.aidl.service;

public interface RemoteWebPage extends android.os.IInterface

{

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

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

    {

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

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

        public Stub()

        {

            this.attachInterface(this, DESCRIPTOR);

        }

        /**

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

         * generating a proxy if needed.

         */

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

        {

            if ((obj==null)) {

                return null;

            }

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

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

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

            }

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

        }

        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_getCurrentPageUrl:

            {

                data.enforceInterface(DESCRIPTOR);

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

                reply.writeNoException();

                reply.writeString(_result);

                return true;

            }

            }

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

        }

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

        {

            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote)

            {

                mRemote = remote;

            }

            public android.os.IBinder asBinder()

            {

                return mRemote;

            }

            public java.lang.String getInterfaceDescriptor()

            {

                return DESCRIPTOR;

            }

            public java.lang.String getCurrentPageUrl() 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);

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

                    _reply.readException();

                    _result = _reply.readString();

                }

                finally {

                    _reply.recycle();

                    _data.recycle();

                }

                return _result;

            }

        }

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

    }

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

}



这个文件是Android SDK对象按照RemoteWebPage.aidl主动生成的,不要测验测验着去批改该文件(改了也白改)。可以看到RemoteWebPage接口内包含了一个名为Stub的抽象的内部类,该类声了然RemoteWebPage.aidl中描述的办法getCurrentPageUrl(),并且还定义了少量的帮助办法Stub还定义了少量的帮助办法,尤其是asInterface(),经由过程它或以获得IBinder(当applicationContext.bindService()成功调用时传递到客户端的onServiceConnected())并且返回用于调用IPC办法的接话柄例,更多细节拜见Calling an IPC Method



4. 编写RemoteService.java



package com.braincol.aidl.service;



import android.app.Service;

import android.content.Intent;

import android.os.IBinder;

import android.os.RemoteException;

import android.util.Log;

/**

 * 

 * @author briancol

 * @description 供给service

 *

 */

public class RemoteService extends Service {

    private final static String TAG = "RemoteService";

    @Override

    public IBinder onBind(Intent intent) {

        Log.i(TAG, "OnBind");

        return new MyBinder();

    }



    private class MyBinder extends RemoteWebPage.Stub{

        @Override

        public String getCurrentPageUrl() throws RemoteException{

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

        }

    }

}

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




package com.braincol.aidl.service;



import android.app.Service;

import android.content.Intent;

import android.os.IBinder;

import android.os.RemoteException;

import android.util.Log;

/**

 * 

 * @author briancol

 * @description 供给service

 *

 */

public class RemoteService extends Service {

    private final static String TAG = "RemoteService";

    @Override

    public IBinder onBind(Intent intent) {

        Log.i(TAG, "OnBind");

        return new MyBinder();

    }



    private class MyBinder extends RemoteWebPage.Stub{

        @Override

        public String getCurrentPageUrl() throws RemoteException{

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

        }

    }

}

package com.braincol.aidl.service;



import android.app.Service;

import android.content.Intent;

import android.os.IBinder;

import android.os.RemoteException;

import android.util.Log;

/**

 * 

 * @author briancol

 * @description 供给service

 *

 */

public class RemoteService extends Service {

    private final static String TAG = "RemoteService";

    @Override

    public IBinder onBind(Intent intent) {

        Log.i(TAG, "OnBind");

        return new MyBinder();

    }



    private class MyBinder extends RemoteWebPage.Stub{

        @Override

        public String getCurrentPageUrl() throws RemoteException{

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

        }

    }

}

如许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文件,然后客户端就可以经由过程该接口来接见办事端供给的办法了。下面是客户端的只要代码:



package com.braincol.aidl.client;



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.TextView;

import com.braincol.aidl.service.RemoteWebPage;



public class ClientActivity extends Activity implements OnClickListener {

    private final static String TAG="ClientActivity";

    TextView textView ;

    Button btn_bind ;

    Button btn_getAllInfo;

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

    RemoteWebPage remoteWebPage=null;

    String allInfo = null;

    boolean isBinded=false;



    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

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

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

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



        btn_getAllInfo.setEnabled(false);



        btn_bind.setOnClickListener(this);

        btn_getAllInfo.setOnClickListener(this);

    }

    @Override

    protected void onPause(){

        super.onPause();

        Log.d(TAG,"onPause");

        if(isBinded){

            Log.d(TAG,"unbind");

            unbindService(connection);    

        }

    }

    private class MyServiceConnection implements ServiceConnection{



        @Override

        public void onServiceConnected(ComponentName name, IBinder service) {

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

            remoteWebPage = RemoteWebPage.Stub.asInterface(service);

            if(remoteWebPage==null){

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

                return;

            }

            try {

                isBinded=true;

                btn_bind.setText("断开");

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

                allInfo = remoteWebPage.getCurrentPageUrl();

                btn_getAllInfo.setEnabled(true);    

            } catch (RemoteException e) {

                e.printStackTrace();

            }

        }



        @Override

        public void onServiceDisconnected(ComponentName name) {

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

        }



    }

    MyServiceConnection connection = new MyServiceConnection();



    @Override

    public void onClick(View v) {

        if(v==this.btn_bind){

            if(!isBinded){

                Intent intent  = new Intent(actionName);

                bindService(intent, connection, Context.BIND_AUTO_CREATE);                

            }else{

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

                unbindService(connection);

                btn_getAllInfo.setEnabled(false);    

                btn_bind.setText("连接");

                isBinded = false;

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

            }

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

            textView.setText(allInfo);

        }



    }

}



 



上方的代码中类MyServiceConnection实现了ServiceConnection类,在MyServiceConnection类的onServiceConnected办法中经由过程RemoteWebPage.Stub.asInterface(service)获取到远端办事端的RemoteWebPage接口对象remoteWebPage,如许就可以经由过程remoteWebPage.getCurrentPageUrl()获取到办事端供给的相干的信息。客户端经由过程bindService()办法绑定长途办事端,经由过程unbindService()断开连接。连接客户端的相干的代码为:



    
Intent intent  = new Intent(actionName);

    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

你可能感兴趣的:(AIDL实现进程间通信)