从Proxy-Stub到aidl


理解了Proxy设计模式的前因后果以及Proxy-Stub模式的设计原因,再来看看Android service开发中的aidl服务就很容易明白了。依然使用上一篇的例子按照AIDL语法进行定义如下:

IPlayer2.aidl

package com.sean.mp3player;

interface IPlayer2 {
	 void play();

	 void stop();

	 void getStatus();
}

使用aidl.exe工具生成IPlayer2.java接口如下:

/*
 * 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;
}

aidl接口生成的java接口看起来非常复杂是因为其中的数据类型除了基本类型,String,List,Map和CharSequence之外全都需要导入包,即使在同一个包中也一样,所以名字看起来特别长。

但仔细观察上述代码就会发现,它和上一篇的Proxy-Stub模式几乎一模一样。也就是说AIDL工具的作用是生成一个继承自IBinder并实现了IPlayer.aidl接口的Proxy-Stub模型的java接口。



相关内容

    暂无相关文章

评论关闭