之前介绍过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接口来化解这个问题。
---恢复内容结束---
时间: 2024-10-08 00:15:54