aidl理解

来源:互联网 发布:尤克里里 调音软件 编辑:程序博客网 时间:2024/06/06 23:12

aidl笔记,

aidl文件代码如下:

package com.zhy.calc.aidl;interface ICalcAIDL{int add(int x , int y);int min(int x , int y );}

生成的java文件代码如下(编辑了一下,方便参考):

package com.example.zhy_binder;public interface ICalcAIDL extends android.os.IInterface {public static abstract class Stub extends android.os.Binder implements com.zhy.calc.aidl.ICalcAIDL {private static final java.lang.String DESCRIPTOR = "com.zhy.calc.aidl.ICalcAIDL";public Stub() {this.attachInterface(this, DESCRIPTOR);}public static com.zhy.calc.aidl.ICalcAIDL asInterface(android.os.IBinder obj) {if ((obj == null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin != null) && (iin instanceof com.zhy.calc.aidl.ICalcAIDL))) {return ((com.zhy.calc.aidl.ICalcAIDL) iin);}return new com.zhy.calc.aidl.ICalcAIDL.Stub.Proxy(obj);}@Overridepublic android.os.IBinder asBinder() {return this;}@Overridepublic 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_add: {data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();int _arg1;_arg1 = data.readInt();int _result = this.add(_arg0, _arg1);reply.writeNoException();reply.writeInt(_result);return true;}case TRANSACTION_min: {data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();int _arg1;_arg1 = data.readInt();int _result = this.min(_arg0, _arg1);reply.writeNoException();reply.writeInt(_result);return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.zhy.calc.aidl.ICalcAIDL {private android.os.IBinder mRemote;Proxy(android.os.IBinder remote) {mRemote = remote;}@Overridepublic android.os.IBinder asBinder() {return mRemote;}public java.lang.String getInterfaceDescriptor() {return DESCRIPTOR;}@Overridepublic int add(int x, int y) throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();int _result;try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(x);_data.writeInt(y);mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);_reply.readException();_result = _reply.readInt();} finally {_reply.recycle();_data.recycle();}return _result;}@Overridepublic int min(int x, int y) throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();int _result;try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(x);_data.writeInt(y);mRemote.transact(Stub.TRANSACTION_min, _data, _reply, 0);_reply.readException();_result = _reply.readInt();} finally {_reply.recycle();_data.recycle();}return _result;}}static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);static final int TRANSACTION_min = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);}public int add(int x, int y) throws android.os.RemoteException;public int min(int x, int y) throws android.os.RemoteException;}
以上是项目中aidl文件自动生成.java文件。此java文件ICalcAIDL包含一个抽象类Stub,以及两个未实现的方法add,min,因为都是抽象的,所以把ICalcAIDL定义为interface。
其内部的抽象类Stub,extends了Binder类而且 implements了其外部类 com.zhy.calc.aidl.ICalcAIDL。

内部类Stub中又定义了一个内部类Proxy,也implements了其外部类 com.zhy.calc.aidl.ICalcAIDL。


客户端的代码如下:

package com.example.zhy_binder_client;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.util.Log;import android.view.View;import android.widget.Toast;import com.zhy.calc.aidl.ICalcAIDL;public class MainActivity extends Activity{private ICalcAIDL mCalcAidl;private ServiceConnection mServiceConn = new ServiceConnection(){@Overridepublic void onServiceDisconnected(ComponentName name){Log.e("client", "onServiceDisconnected");mCalcAidl = null;}@Overridepublic void onServiceConnected(ComponentName name, IBinder service){Log.e("client", "onServiceConnected");//mCalcAidl = ICalcAIDL.Stub.asInterface(service);}};@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}/** * 点击BindService按钮时调用 * @param view */public void bindService(View view){Intent intent = new Intent();intent.setAction("com.zhy.aidl.calc");bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);}/** * 点击unBindService按钮时调用 * @param view */public void unbindService(View view){unbindService(mServiceConn);}/** * 点击12+12按钮时调用 * @param view */public void addInvoked(View view) throws Exception{if (mCalcAidl != null){int addRes = mCalcAidl.add(12, 12);Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();} else{Toast.makeText(this, "服务器被异常杀死,请重新绑定服务端", Toast.LENGTH_SHORT).show();}}/** * 点击50-12按钮时调用 * @param view */public void minInvoked(View view) throws Exception{if (mCalcAidl != null){int addRes = mCalcAidl.min(50, 12);Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();} else{Toast.makeText(this, "服务器未绑定或被异常杀死,请重新绑定服务端", Toast.LENGTH_SHORT).show();}}}

服务器端代码如下:
package com.example.zhy_binder;import com.zhy.calc.aidl.ICalcAIDL;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;public class CalcService extends Service{private static final String TAG = "server";public void onCreate(){Log.e(TAG, "onCreate");}public IBinder onBind(Intent t){Log.e(TAG, "onBind");return mBinder;}public void onDestroy(){Log.e(TAG, "onDestroy");super.onDestroy();}public boolean onUnbind(Intent intent){Log.e(TAG, "onUnbind");return super.onUnbind(intent);}public void onRebind(Intent intent){Log.e(TAG, "onRebind");super.onRebind(intent);}private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub(){@Overridepublic int add(int x, int y) throws RemoteException{return x + y;}@Overridepublic int min(int x, int y) throws RemoteException{return x - y;}};}

客户端启动服务端之后,服务端返回一个binder对象,客户端通过此binder对象来对服务端提供的方法进行调用。

分析代码如下:

在服务端的onBind方法中返回了一个mBinder,此mBinder在其44行,如下:

private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub(){@Overridepublic int add(int x, int y) throws RemoteException{return x + y;}@Overridepublic int min(int x, int y) throws RemoteException{return x - y;}};
可以看到此mBinder是抽象类ICalcAIDL.Stub的对象,而此类继承了Binder而且implements其父类,所以mBinder必须实现抽象类ICalcAIDL.Stub的抽象方法add和min。


而在客户端的代码第34行如下:

mCalcAidl = ICalcAIDL.Stub.asInterface(service);
把服务端返回回来的binder对象作为Proxy类的构造参数new了一个Proxy类的对象。而后在客户端就是利用这个Proxy类的对象mCalcAidl来调用方法add或者min。


此mCalcAidl对方法add的调用在客户端73行如下:
 int addRes = mCalcAidl.add(12, 12);  
实际上调用的是生成文件的第87-103行,如下:

public int add(int x, int y) throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();int _result;try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(x);_data.writeInt(y);mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);_reply.readException();_result = _reply.readInt();} finally {_reply.recycle();_data.recycle();}return _result;}

注意此第9行,即产生文件的第95行,如下:

mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
调用者mRemote就是上面所说的服务端传过来作为Proxy构造参数的binder对象,而此binder是stub类的对象,所以此行代码实际调用的是stub类中的onTransact方法,即生成文件的第34行。

参考:http://blog.csdn.net/lmj623565791/article/details/38461079


4.3日,总结一下:自动生成的文件中,有两个抽象的内部类,一个是extends binder的同时实现了外部抽象类A,另一个则是只实现了外部抽象类B,这里B时A的代理类(此处用到了设计模式中的代理模式)。service中返回的binder是A类的实例,Activity中收到了之后把其转换成B类的实例,也就是代理类的实例,然后进行其方法的调用,比如调用代理类B的add方法(mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0))就相当于调用A类的onTransact方法。


0 0
原创粉丝点击