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

最后更新于:2022-04-02 05:51:04

阿斗(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(outcomplicatedDataStructure); int setTest(inString 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(complicatedDataStructurecds) throws RemoteException { //在这里实现具体的getTest } public voidsetTest(in String name,in boolean reStartServer) throwsRemoteException { //在这里实现具体的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 = newServiceConnection() { //@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 implementsParcelable { publicstatic final int foo1 = 0; publicstatic final int foo2 = 1; publicString fooString1 = null; publicString fooString2 = null; //静态Creator类 public static final Parcelable.Creator< complicatedDataStructure> CREATOR = newParcelable.Creator< complicatedDataStructure >() { public complicatedDataStructure createFromParcel(Parcel in) { return new complicatedDataStructure (in); } public complicatedDataStructure [] newArray(int size) { return new complicatedDataStructure [size];//用于传递数组 } }; public complicatedDataStructure(complicatedDataStructureother) { fooString1= other. fooString1; fooString2= other. fooString2; foo1= other. foo1; foo2 =other. foo2; } private complicatedDataStructure(Parcel in) { readFromParcel(in); } /*@Override */ publicint describeContents() { return 0; } publicvoid readFromParcel(Parcel in) { foo1= in. readInt (); foo2= in. readInt (); fooString1= in.readString(); fooString2= in.readString(); } /*@Override */ publicvoid 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,再看我们的阿斗是不是能扶得起了呢?当然,想让上面的程序正确工作,还得再努把力,把未尽的业务层事业完成。另外,还要经得起残酷环境的考验(即通过测试来检验自己的程序)。
';