在Andorid平台中,各个组件运行在自己的进程中,他们之间是不能相互访问的,但是在程序之间是不可避免的要传递一些对象,在进程之间相互通信。为了实现进程之间的相互通信,Andorid采用了一种轻量级的实现方式RPC(Remote Procedure Call远程进程调用)来完成进程之间的通信,并且Android通过接口定义语言(Andorid Interface Definition Language ,AIDL)来生成两个进程之间相互访问的代码,例如,你在Activity里的代码需要访问Service中的一个方法,那么就可以通过这种方式来实现了。

AIDL是Android的一种接口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的. 如果需要在一个Activity中, 访问另一个Service中的某个对象, 需要先将对象转化成 AIDL可识别的参数(可能是多个参数), 然后使用AIDL来传递这些参数, 在消息的接收端, 使用这些参数组装成自己需要的对象。

AIDL RPC机制是通过接口来实现的,类似Windows中的COM或者Corba,但他是轻量级的,客户端和被调用实现之间是通过代理模式实现的,代理类和被代理类实现同一个接口Ibinder接口。

下面是实现Activity访问Service例子的步骤:

一.创建.aidl文件

AIDL使用简单的语法来声明接口,描述其方法以及方法的参数和返回值。这些参数和返回值可以是任何类型,甚至是其他AIDL生成的接口。重要的是必须导入导入除了内建类型(例如:int,boolean等)外的任何其他类型,哪怕是这些类型是在与接口相同的包中。具体的要求如下:

JAVA基本数据类型不需要导入

String,List,Map和CharSequence不需要导入

使用Eclipse的ADT插件创建一个BookInfo.aidl文件,该文件有4个方法:

setName(String name)设置图书的书名,setPrice(int price)设置图书的价格,setPublish(String pname)设置图书的出版社和String display()显示图书的信息.

BookInfo.aidl文件

packagecom.android.aidl;//BookInfo接口interfaceBookInfo{voidsetName(Stringname);voidsetPrice(intprice);voidssetPublish(Stringpname);//显示图书的信息Stringdisplay();}

创建好BookInfo.aidl文件,系统会自动在gen目录下生成Java接口文件BookInfo.java

二.实现AIDL文件生成的JAVA接口

AIDL会生成一个和.aidl文件同名的JAVA接口文件,该接口中有一个静态抽象内部类Stub,该类中声明了AIDL文件中定义的所有方法,其中有一个重要的方法是asInterface(),该方法通过代理模式返回JAVA接口的实现我们可以定义一个实现类,BookImpl,该类继承Stub类,实现我们定义的4个方法

packagecom.android.aidl;importandroid.os.RemoteException;publicclassBookInfoImplextendsBookInfo.Stub{//声明三个个变量privateintprice;privateStringname,pname;//显示书名,价格,出版社publicStringdisplay()throwsRemoteException{return"书名:"+name+";价格:"+price+";出版社:"+price;}@Override//设置书名publicvoidsetName(Stringname)throwsRemoteException{//TODOAutothis.name=name;}@Override//设置价格publicvoidsetPrice(intprice)throwsRemoteException{//TODOAuto-generatedmethodstubthis.price=price;}@Override//设置出版社publicvoidsetPublish(Stringpname)throwsRemoteException{//TODOAutothis.pname=pname;}}

三.向客户端暴露接口

现在已经实现了BookInfo接口,接下来要将该接口暴露给客户端调用。一般通过定义一个Service来实现,在Service的onBind()方法中返回该接口,当我们绑定该接口时调用该方法。

packagecom.android.aidl;importcom.android.aidl.BookInfo.Stub;importandroid.app.Service;importandroid.content.Intent;importandroid.os.IBinder;publicclassRemoteServiceextendsService{//声明BookInfo接口privateStubbookifo=newBookInfoImpl();publicIBinderonBind(Intentintent){returnbookifo;}}

四.在客户端调用

定义一个Activity来绑定远程Service,获得BookInfo接口,通过RPC机制调用接口中的方法。

packagecom.android.aidl;importandroid.app.Activity;importandroid.app.Service;importandroid.content.ComponentName;importandroid.content.Intent;importandroid.content.ServiceConnection;importandroid.os.Bundle;importandroid.os.IBinder;importandroid.os.RemoteException;importandroid.view.View;importandroid.view.View.OnClickListener;importandroid.widget.Button;importandroid.widget.Toast;publicclassMainActivityextendsActivity{//声明IPerson接口privateBookInfobookInfo;//声明ButtonprivateButtonbtn;//实例化ServiceConnectionprivateServiceConnectionconn=newServiceConnection(){@OverridesynchronizedpublicvoidonServiceConnected(ComponentNamename,IBinderservice){//获得IPerson接口bookInfo=BookInfo.Stub.asInterface(service);if(bookInfo!=null)try{//RPC方法调用bookInfo.setName("GoogleAndroidSDK开发范例大全");bookInfo.setPrice(55);bookInfo.setPublish("人民邮电出版社");Stringmsg=bookInfo.display();//显示方法调用返回值Toast.makeText(MainActivity.this,msg,Toast.LENGTH_LONG).show();}catch(RemoteExceptione){e.printStackTrace();}}@OverridepublicvoidonServiceDisconnected(ComponentNamename){}};@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);//设置当前视图布局setContentView(R.layout.main);//实例化Buttonbtn=(Button)findViewById(R.id.Button1);//为Button添加单击事件监听器btn.setOnClickListener(newOnClickListener(){@OverridepublicvoidonClick(Viewv){//实例化IntentIntentintent=newIntent();//设置IntentAction属性intent.setAction("com.android.aidl.action.MY_REMOTE_SERVICE");//绑定服务bindService(intent,conn,Service.BIND_AUTO_CREATE);}});}}

五.main.xml和AndroidManifest.xml文件

main.xml

<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"><Buttonandroid:text="远程调用Service"android:id="@+id/Button1"android:layout_width="wrap_content"android:layout_height="wrap_content"/></LinearLayout>

在AndroidManifest.xml文件16~20声明Service

<?xmlversion="1.0"encoding="utf-8"?><manifestxmlns:android="http://schemas.android.com/apk/res/android"package="com.android.aidl"android:versionCode="1"android:versionName="1.0"><uses-sdkandroid:minSdkVersion="10"/><applicationandroid:icon="@drawable/icon"android:label="@string/app_name"><activityandroid:name=".MainActivity"android:label="@string/app_name"><intent-filter><actionandroid:name="android.intent.action.MAIN"/><categoryandroid:name="android.intent.category.LAUNCHER"/></intent-filter></activity><serviceandroid:name="RemoteService"><intent-filter><actionandroid:name="com.android.aidl.action.MY_REMOTE_SERVICE"/></intent-filter></service></application></manifest>

效果图: