Android AIDL使用详解

Nostalgiachild 2012-05-15

1.什么是aidl:aidl是AndroidInterfacedefinitionlanguage的缩写,一看就明白,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口

icp:interprocesscommunication:内部进程通信

2.既然aidl可以定义并实现进程通信,那么我们怎么使用它呢?文档/android-sdk/docs/guide/developing/tools/aidl.html中对步骤作了详细描述:

--1.Createyour.aidlfile-Thisfiledefinesaninterface(YourInterface.aidl)thatdefinesthemethodsandfieldsavailabletoaclient.

创建你的aidl文件,我在后面给出了一个例子,它的aidl文件定义如下:写法跟java代码类似,但是这里有一点值得注意的就是它可以引用其它aidl文件中定义的接口,但是不能够引用你的java类文件中定义的接口

package com.cao.android.demos.binder.aidl;    
import com.cao.android.demos.binder.aidl.AIDLActivity;  
interface AIDLService {     
    void registerTestCall(AIDLActivity cb);     
    void invokCallBack();  
}

--2.Addthe.aidlfiletoyourmakefile-(theADTPluginforEclipsemanagesthisforyou).Androidincludesthecompiler,calledAIDL,inthetools/directory.

编译你的aidl文件,这个只要是在eclipse中开发,你的adt插件会像资源文件一样把aidl文件编译成java代码生成在gen文件夹下,不用手动去编译:编译生成AIDLService.java如我例子中代码

--3.Implementyourinterfacemethods-TheAIDLcompilercreatesaninterfaceintheJavaprogramminglanguagefromyourAIDLinterface.ThisinterfacehasaninnerabstractclassnamedStubthatinheritstheinterface(andimplementsafewadditionalmethodsnecessaryfortheIPCcall).YoumustcreateaclassthatextendsYourInterface.Stubandimplementsthemethodsyoudeclaredinyour.aidlfile.

实现你定义aidl接口中的内部抽象类Stub,publicstaticabstractclassStubextendsandroid.os.Binderimplementscom.cao.android.demos.binder.aidl.AIDLService

Stub类继承了Binder,并继承我们在aidl文件中定义的接口,我们需要实现接口方法,下面是我在例子中实现的Stub类:

private final AIDLService.Stub mBinder = new AIDLService.Stub() {  
  
    @Override  
    public void invokCallBack() throws RemoteException {  
        Log("AIDLService.invokCallBack");  
        Rect1 rect = new Rect1();  
        rect.bottom=-1;  
        rect.left=-1;  
        rect.right=1;  
        rect.top=1;  
        callback.performAction(rect);  
    }  
  
  
    @Override  
    public void registerTestCall(AIDLActivity cb) throws RemoteException {  
        Log("AIDLService.registerTestCall");  
        callback = cb;  
    }  
};

Stub翻译成中文是存根的意思,注意Stub对象是在被调用端进程,也就是服务端进程,至此,服务端aidl服务端得编码完成了。

--4.Exposeyourinterfacetoclients-Ifyou'rewritingaservice,youshouldextendServiceandoverrideService.onBind(Intent)toreturnaninstanceofyourclassthatimplementsyourinterface.

第四步告诉你怎么在客户端如何调用服务端得aidl描述的接口对象,doc只告诉我们需要实现Service.onBind(Intent)方法,该方法会返回一个IBinder对象到客户端,绑定服务时不是需要一个ServiceConnection对象么,在没有了解aidl用法前一直不知道它是什么作用,其实他就是用来在客户端绑定service时接收service返回的IBinder对象的:

AIDLService mService;  
private ServiceConnection mConnection = new ServiceConnection() {  
    public void onServiceConnected(ComponentName className, IBinder service) {  
        Log("connect service");  
        mService = AIDLService.Stub.asInterface(service);  
        try {  
            mService.registerTestCall(mCallback);  
        } catch (RemoteException e) {  
  
        }  
    }  
  
  
    public void onServiceDisconnected(ComponentName className) {  
        Log("disconnect service");  
        mService = null;  
    }  
};

mService就是AIDLService对象,具体可以看我后面提供的示例代码,需要注意在客户端需要存一个服务端实现了的aidl接口描述文件,但是客户端只是使用该aidl接口,不需要实现它的Stub类,获取服务端得aidl对象后mService=AIDLService.Stub.asInterface(service);,就可以在客户端使用它了,对mService对象方法的调用不是在客户端执行,而是在服务端执行。

4.aidl中使用java类,需要实现Parcelable接口,并且在定义类相同包下面对类进行声明:

上面我定义了Rect1类

之后你就可以在aidl接口中对该类进行使用了

packagecom.cao.android.demos.binder.aidl;

importcom.cao.android.demos.binder.aidl.Rect1;

interfaceAIDLActivity{

voidperformAction(inRect1rect);

}

注意in/out的说明

相关推荐