6.6.2 扶得起的“阿斗”(aidl)

阿斗(aidl的谐音)本来是扶不起的,可是我们有了AIDL工具,就有可能将他扶起!

1.我能干什么

在Java层中,如果想要利用Binder进行跨进程的通信,也得定义一个类似ITest的接口,不过这是一个aidl文件。现在假设服务端程序都在com.test.service包中。

ITest.aidl文件内容如下:


[—>ITest.aidl]

package com.test.service;

import com.test.complicatedDataStructure

interface ITest{

//complicatedDataStructure类是自己定义的复杂数据结构,in表示输入参数,out表示输出参数。

//in和out的表示一定要准确。切记!

int getTest(out complicatedDataStructure);

int setTest(in String name,in boolean reStartServer);

}


定义完后,如果用Eclipse进行编译,会在gen目录下生成一个com.test.ITest.java文件(也会生成对应包结构的目录)。内容就不具体罗列了,我们只关注它是如何实现服务端的。

说明 Eclipse用的也是aidl工具,可以手动使用这个工具编译aidl文件。

2.实现服务端

com.test.ITest.java只是实现了类似BnTest的一个东西,具体的业务实现还需从ITest.Stub派生,实现代码如下所示:


[—>ITestImpl.java]

/*

ITest.Stub是在aidl生成的那个Java文件中定义的,非常类似Native层的BnTest。

ITestImpl必须从ITest.Stub中派生,用来实现具体的业务函数。

*/

package com.test.service

class ITestImpl extends ITest.Stub{

public void getTest(complicatedDataStructure cds)throws RemoteException{

//在这里实现具体的getTest。

}

public void setTest(in String name,in boolean reStartServer)

throws RemoteException

{

//在这里实现具体的setTest。

}

}


这时,你的Eclipse下会有如下两个目录:

src下有一个com.test.service包结构目录。

gen下也有一个com.test.service包结构目录,其中的内容是由aidl工具生成的。

3.实现代理端

代理端往往在另外一个程序中使用。假设是com.test.client包,把刚才com.test.service工程中gen下的com.test.service目录全部复制到com.test.client中了。这样,client工程也就有两个包结构目录了:

com.test.client.

com.test.service。不过这个目录中仅有aidl生成的Java文件。

服务端一般驻留于Service进程,所以可以在Client端的onServiceConnected函数中获得代理对象,实现代码如下所示:


[—>Client端示例代码]

//不一定是在onServiceConnected中,但它是比较合适的。

private ServiceConnection serviceConnection=new ServiceConnection(){

//@Override

public void onServiceConnected(ComponentName name,IBinder service){

if(ITestProxy==null)

ITestProxy=ITest.Stub.asInterface(service);//这样你就得到BpTest了。

}


4.传递复杂的数据结构

AIDL支持简单数据结构与Java中String类型的数据进行跨进程传递,如果想做到跨进程传递复杂的数据结构,还须另做一些工作。

以ITest.aidl文件中使用的complicatedDataStructure为例:

它必须实现implements Parcelable接口。

内部必须有一个静态的CREATOR类。

定义一个complicatedDataStructure.aidl文件。

说明 可参考Android API文档的parcelable类,里面有一个很简单的例子。

来看这个Java文件的实现:


[—>complicatedDataStructure.java]

package com.test.service;

import android.os.Parcel;

import android.os.Parcelable;

public class complicatedDataStructure implements Parcelable{

public static final int foo1=0;

public static final int foo2=1;

public String fooString1=null;

public String fooString2=null;

//静态Creator类

public static final Parcelable.Creator<complicatedDataStructure>CREATOR=

new Parcelable.Creator<complicatedDataStructure>(){

public complicatedDataStructure createFromParcel(Parcel in)

{

return new complicatedDataStructure(in);

}

public complicatedDataStructure[]newArray(int size)

{

return new complicatedDataStructure[size];//用于传递数组

}

};

public complicatedDataStructure(complicatedDataStructure other){

fooString1=other.fooString1;

fooString2=other.fooString2;

foo1=other.foo1;

foo2=other.foo2;

}

private complicatedDataStructure(Parcel in){

readFromParcel(in);

}

/@Override/

public int describeContents(){

return 0;

}

public void readFromParcel(Parcel in){

foo1=in.readInt();

foo2=in.readInt();

fooString1=in.readString();

fooString2=in.readString();

}

/@Override/

public void writeToParcel(Parcel dest,int flags){

dest.writeInt(foo1);

dest.writeInt(foo2);

dest.writeString(fooString1);

dest.writeString(fooString2);

}

}


complicatedDataStructure.aidl该怎么写呢?如下所示:


[—>complicatedDataStructure.aidl]

package com.test.service;

parcelable complicatedDataStructure;


然后,在使用它的aidl文件中添加下行代码即可:


import com.test.complicatedDataStructure


有了AIDL,再看我们的阿斗是不是能扶得起了呢?当然,想让上面的程序正确工作,还得再努把力,把未尽的业务层事业完成。另外,还要经得起残酷环境的考验(即通过测试来检验自己的程序)。