首先为什么需要aidl?
下面是不需要aidl 的binder的IPC通讯过程,表面上结构很简单,但是有个困难就是,客户端和服务端进行通讯,你得先将你的通讯请求转换成序列化的数据,然后调用transact()函数发送给服务端,而且还得制定一个小协议,参数谁先谁后,服务端和客户端都必须一致,否则就会出错。这样的过程有没有觉的很麻烦,如果有上百个接口,那可就要疯掉了。可不可以就像调用自家函数那样呢?而不需要麻烦的将参数值转化成序列化数据呢?由此AIDL诞生了。
好,我定义一下服务的函数,然后写成一个interface文件
前面的I字母加上去只是一种AIDL文件形式上的标识。
interface IxxxxService (
void ServiceFunctionA();
void ServiceFunctionB();
void ServiceFunctionC();
)
利用aidl工具生成一个IxxxxService.java文件,然后它的uml图如下。
其中的一些函数的理解:
IxxxxService.Stub.asInterface(IBinder obj) :
这个函数是干啥用呢?首先当bindService之后,客户端会得到一个Binder引用,是Binder 哟,不是IxxxxService.Proxy实例,那这样的话,我们第一个想法是利用Binder引用作为参数实例化出一个IxxxxService.Proxy。Ok, 但如果服务端和客户端都是在同一个进程呢,还需要利用IPC吗?这样就不需要了,直接将IxxxxService当做普通的对象调用就成了。Google 的同志们他们利用IxxxxService.Stub.asInterface函数对这两种不同的情况进行了统一,也就是不管你是在同一进程还是不同进程,那么在拿到Binder引用后,调用IxxxxService.Stub.asInterface(IBinder obj) 即可得到一个IxxxxService 实例,然后你只管调用IxxxxService里的函数就成了。
*******asInterface英文字面意思我没能想到合理的解释...有英语好的讲讲********
asBinder
返回自身类里包含的Binder对象实例。
总结:
AIDL的最终效果就是让 IPC的通讯就像调用函数那样简单。自动的帮你完成了参数序列化发送以及解析返回数据的那一系列麻烦。而你所需要做的就是写上一个接口文件,然后利用aidl工具转化一下得到另一个java文件,这个文件在服务和客户端程序各放一份。服务程序继承IxxxxService.Stub 然后将函数接口里面的逻辑代码实现一下。
weather分析:
IWeatherService.aidl
package com.autochips.weather; interface IWeatherService { void getNewestWeather(); }
aidl.exe生产的IWeatherService.java
/* * This file is auto-generated. DO NOT MODIFY. * Original file: /home/mxy/code/last_new/autochips/packages/apps/Weather/src/com/autochips/weather/IWeatherService.aidl */ package com.autochips.weather; public interface IWeatherService extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.autochips.weather.IWeatherService { private static final java.lang.String DESCRIPTOR = "com.autochips.weather.IWeatherService"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.autochips.weather.IWeatherService interface, * generating a proxy if needed. */ public static com.autochips.weather.IWeatherService asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof com.autochips.weather.IWeatherService))) { return ((com.autochips.weather.IWeatherService)iin); } return new com.autochips.weather.IWeatherService.Stub.Proxy(obj); } @Override 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_getNewestWeather: { data.enforceInterface(DESCRIPTOR); this.getNewestWeather(); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.autochips.weather.IWeatherService { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public void getNewestWeather() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getNewestWeather, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } static final int TRANSACTION_getNewestWeather = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); } public void getNewestWeather() throws android.os.RemoteException; }
IWeatherService.java的UML图