package com.example.advanceandroid.aidl;
interface ILogin {
String login();
}
注意看,接口和方法声明都不用public,方法加入public会提示错误。编写完后如果eclipse开启了自动编译则会在gen/com.example.advanceandroid.aidl下生成一个ILogin.java类,内容大致如下:
package com.example.advanceandroid.aidl; public interface ILogin extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.example.advanceandroid.aidl.ILogin { private static final java.lang.String DESCRIPTOR = "com.example.advanceandroid.aidl.ILogin"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.example.advanceandroid.aidl.ILogin * interface, generating a proxy if needed. */ public static com.example.advanceandroid.aidl.ILogin asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.example.advanceandroid.aidl.ILogin))) { return ((com.example.advanceandroid.aidl.ILogin) iin); } return new com.example.advanceandroid.aidl.ILogin.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_login: { // 1、登录请求,执行的是this.login(); data.enforceInterface(DESCRIPTOR); java.lang.String _result = this.login(); reply.writeNoException(); reply.writeString(_result); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.example.advanceandroid.aidl.ILogin { 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 java.lang.String login() throws android.os.RemoteException // 2、Proxy中的login,通过Binder机制实现IPC { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.lang.String _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_login, _data, _reply, 0); _reply.readException(); _result = _reply.readString(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_login = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); } public java.lang.String login() throws android.os.RemoteException; }可以看到,该类中自动生成了ILogin接口,该接口中又一个login()函数。但最重要的是里面生成了一个Stub类,该类集成子Binder类,并且实现了ILogin接口。Stub里面最重要的就是asInterface()这个函数,在这个函数中会判断obj参数的类型,如果是该obj是本地的接口类似,则认为不是IPC,会将该obj转换成ILogin类型;否则会通过自动生成的另一个内部类Proxy来包装obj,将其赋值给Proxy中的mRemote属性。Proxy类也实现了ILogin接口,在login()函数中,Proxy将通过Binder机制向服务端传递请求和数据,如上面代码中的注释2。这是客户端的工作算是完成了。
服务端还没有完,最重要的一步时建立一个Service,内容大致如下 :
/** * AIDL服务端接口,LoginStubImpl实现了ILogin接口. * * @author mrsimple */ public class LoginService extends Service { /** * */ IBinder mBinder = new LoginStubImpl(); /** * @author mrsimple */ class LoginStubImpl extends Stub { @Override public String login() throws RemoteException { return "这是从 " + this.getClass().getName() + " 返回的字符串"; } } /* * 返回Binder实例,即实现了ILogin接口的Stub的子类,这里为LoginStubImpl * [url=home.php?mod=space&uid=133757]@see[/url] android.app.Service#onBind(android.content.Intent) */ @Override public IBinder onBind(Intent intent) { return mBinder; } }该Service我们这里命名为LoginService,继承自Service,然后建一个名为LoginServiceImpl的内部类,该类继承自自动生成的Stub,然后实现login()方法。在LoginService中声明一个IBinder字段mBinder :
IBinder mBinder = new LoginStubImpl();
在服务端程序的AndroidManifest.xml中注册LoginService,如下 :
<!-- aidl server service --> <service android:name="com.example.advanceandroid.aidl.LoginService" > <intent-filter> <action android:name="com.example.advanceandroid.aidl.LoginService" /> </intent-filter> </service>
在Activity中加入如下代码 :
ServiceConnection mLoginConnection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { Log.d("", "### aidl disconnected."); } @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d("", "### aidl onServiceConnected. service : " + service.getClass().getName()); ILogin login = Stub.asInterface(service); Log.d("", "### after asInterface : " + login.getClass().getName()); try { Log.d("", "### login : " + login.login()); // Toast.makeText(MainActivity.this, "onServiceConnected : " + // login.login(), // Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { e.printStackTrace(); } } }; @Override protected void onResume() { super.onResume(); // 服务端的action Intent aidlIntent = new Intent("com.example.advanceandroid.aidl.LoginService"); bindService(aidlIntent, mLoginConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // unbind unbindService(mLoginConnection); }运行
先运行服务端程序,然后在启动客户端程序,可以看到客户端输出如下Log:
09-02 10:40:54.662: D/(9589): ### aidl onServiceConnected. service : android.os.BinderProxy 09-02 10:40:54.662: D/(9589): ### after asInterface : com.example.advanceandroid.aidl.ILogin$Stub$Proxy 09-02 10:40:54.662: D/(9589): ### login : 这是从 com.example.advanceandroid.aidl.LoginService$LoginStubImpl 返回的字符串可以看淡onServiceConnected(ComponentName name, IBinder service)中的service对象是BinderProxy类型,经过asInterface转换后被包装成了Proxy类型,但是调用的时候,执行的是服务端LoginStubImpl中的login()函数。因此,LoginStubImpl实例mBinder被服务端包装成BinderProxy类型,再经过客户端的Proxy进行包装,通过Binder机制进行数据传输,实现IPC。
原文地址:http://blog.csdn.net/bboyfeiyu/article/details/39003759