解析 Aidl 文件

之前介绍过Android进程间通信(IPC)的使用,写过一些Demo。但仅仅是拿来用,并没有深入分析aidl是怎样可以做到进程间通信的。

当创建 ITelephony.aidl文件时,aidl会为我们在gen目录中创建相应的文件。

 

 

 

 

package com.android.internal.telephony;

public interface ITelephony extends android.os.IInterface {
/** Local-side IPC implementation stub class. */
//继承binder 实现所定义的aidl文件内的接口 //静态抽象类 服务端用 //Stub重载实现了OnTransact()方法,这样他就可以根据Proxy发来的客服端的请求, //进行解析并且调用对应请求的函数接口 public static abstract class Stub extends android.os.Binder implements com.android.internal.telephony.ITelephony { private static final java.lang.String DESCRIPTOR = "com.android.internal.telephony.ITelephony"; /** Construct the stub at attach it to the interface. */ //stub构造方法 public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.example.aidl.IRemoteService interface, generating a proxy if needed. 如果需要生成一个代理,为com.android.internal.telephony.itelephony接口铸造一个IBinder对象 */ //当bindService之后(绑定服务),客户端会得到一个Binder引用,是Binder,不是接口的实例, //然后就会用 aidl定义的接口.Stub.asInterface函数,去对这是不是跨进程的情况进行统一 //也就是不管你是在同一进程还是不同进程,在拿到Binder引用后, //调用 aidl定义的接口.Stub.asInterface(IBinder obj) //即可得到一个接口的实例


//判断Ibinder是否为空
//为空则返回空
//若不为空且是aidl接口的实例 则返回true
//调用 proxy()方法 并将IBinder传入

public static com.android.internal.telephony.ITelephony asInterface(
android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.android.internal.telephony.ITelephony))) {
return ((com.android.internal.telephony.ITelephony) iin);
}
return new com.android.internal.telephony.ITelephony.Stub.Proxy(obj);
}
//返回自身类里包含的Binder对象实例
public android.os.IBinder asBinder() {
return this;
}

//根据Proxy发来的客服端的请求,
//进行解析并且调用对应请求的函数接口
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_endCall: {
data.enforceInterface(DESCRIPTOR);
boolean _result = this.endCall();
reply.writeNoException();
reply.writeInt(((_result) ? (1) : (0)));
return true;
}
case TRANSACTION_answerRingingCall: {
data.enforceInterface(DESCRIPTOR);
this.answerRingingCall();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

//这是一个静态类 他是一个服务端在客户端的代理 供客户端使用 
// 调用asbinder方法 将定义的aidl文件内的方法发送给服务端
private static class Proxy implements
com.android.internal.telephony.ITelephony {
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 boolean endCall() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_endCall, _data, _reply, 0);
_reply.readException();
_result = (0 != _reply.readInt());
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}

// 挂断电话

@Override
public void answerRingingCall() 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_answerRingingCall, _data,
_reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}

static final int TRANSACTION_endCall = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_answerRingingCall = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}

public boolean endCall() throws android.os.RemoteException;

// 挂断电话

public void answerRingingCall() throws android.os.RemoteException;
}

 

 

 

 

其实,AIDL接口幕后是仰赖着IBinder界面的。所以,我们的应用程序可以选择使用IBinder接口,也可以使用AIDL接口。

如果采取IBinder接口,就不必使用aidl.exe工具去产calInterface.java接口定义文件了,其接口类别较单纯一些。但是由于

IBinder接口只提供单一函数(即transact()函数)来进行远距沟通,呼叫起来比较不方便。例如,当Calculator类别有多个函

数时,myActivity要如何呼叫它们呢? 可以呼叫IBinder接口的transact()函数,再转而呼叫Calculator的各个函数。由于

它并不太方便,所以Android提供Proxy/Stub结构的AIDL接口来化解这个问题。

 

 

 

 

 

 

 

 

 

 

 

 

---恢复内容结束---

posted @ 2015-08-01 16:06  手酒刘  阅读(688)  评论(0编辑  收藏  举报