理解了Proxy设计模式的前因后果以及Proxy-Stub模式的设计原因,再来看看Android service开发中的aidl服务就很容易明白了。依然使用上一篇的例子按照AIDL语法进行定义如下:
IPlayer2.aidl
package com.sean.mp3player; interface IPlayer2 { void play(); void stop(); void getStatus(); }
/* * This file is auto-generated. DO NOT MODIFY. * Original file: /home/sean/workspace/MP3Player/src/com/sean/mp3player/IPlayer2.aidl */ package com.sean.mp3player; public interface IPlayer2 extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.sean.mp3player.IPlayer2 { private static final java.lang.String DESCRIPTOR = "com.sean.mp3player.IPlayer2"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.sean.mp3player.IPlayer2 interface, * generating a proxy if needed. */ public static com.sean.mp3player.IPlayer2 asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof com.sean.mp3player.IPlayer2))) { return ((com.sean.mp3player.IPlayer2)iin); } return new com.sean.mp3player.IPlayer2.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_play: { data.enforceInterface(DESCRIPTOR); this.play(); reply.writeNoException(); return true; } case TRANSACTION_stop: { data.enforceInterface(DESCRIPTOR); this.stop(); reply.writeNoException(); return true; } case TRANSACTION_getStatus: { data.enforceInterface(DESCRIPTOR); this.getStatus(); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.sean.mp3player.IPlayer2 { 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 play() 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_play, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } @Override public void stop() 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_stop, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } @Override public void getStatus() 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_getStatus, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } static final int TRANSACTION_play = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_stop = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); static final int TRANSACTION_getStatus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2); } public void play() throws android.os.RemoteException; public void stop() throws android.os.RemoteException; public void getStatus() throws android.os.RemoteException; }
但仔细观察上述代码就会发现,它和上一篇的Proxy-Stub模式几乎一模一样。也就是说AIDL工具的作用是生成一个继承自IBinder并实现了IPlayer.aidl接口的Proxy-Stub模型的java接口。