AIDL

来源:互联网 发布:桂糖微盘软件开发商 编辑:程序博客网 时间:2024/05/16 09:52

AIDL(Android 接口描述语言):作用是用于进程间的通信。编译器会根据AIDL文件生成Java类,通过预先定义的接口以及Binder机制达到进程间的通信。
AIDL其实就是一个接口罢了,客户端通过bindService来与远程服务端建立连接,在该连接建立时会返回一个IBinder对象,该对象是服务端Binder的BinderProxy,客户端通过asinterface将该BinderProxy对象包装成本地的Proxy,并将远程服务端的BinderProxy对象赋值给Proxy类的mRemote字段,就是通过mRemote执行远程函数调用。

下面写一个案例:
先看一下工程结构:

注意:创建完.aidl文件后一定要先编译,如果你是用Eclipse的话会自动编译,否则java文件不会生成!还有,包名和类名一字不差!

aidl文件内容:

package com.yu.myaidl;// Declare any non-default types here with import statementsinterface SsoAuth {    /**     * Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     *//*** 实现授权登录*/     void ssoAuth(String userName,String pwd);}

下面是服务端代码:

public class SinaSsoAuthService extends Service{    SinaSsoImpl mBinder  = new SinaSsoImpl();    @Nullable    @Override    public IBinder onBind(Intent intent) {        return mBinder;    }    @Override    public void onCreate() {        super.onCreate();        Log.e("","### sso auth created");    }    //继承自Stub类实现功能   class SinaSsoImpl extends SsoAuth.Stub{       @Override       public void ssoAuth(String userName, String pwd) throws RemoteException {           Log.e("", "这是新浪客户端,执行SSO登录啦,用户名:" + userName + ",密码是:" + pwd);       }   }}

别忘了注册服务:

   <service            android:name=".SinaSsoAuthService"            android:exported="true"            android:label="@string/app_name"            android:process=":remote">            <intent-filter>                <action android:name="AIDL_Action" />            </intent-filter>        </service>

好了,服务端OK了,先跑起来吧!

客户端代码如下:

public class MainActivity extends Activity {    SsoAuth mSsoAuth;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }    //当点击登录按钮时     public void click(View view){         if(mSsoAuth==null){             //绑定服务并且进行登录             bindSsoAuthService();         }else {             //直接授权登录             doSsoAuth();         }     }    private void bindSsoAuthService() {        //绑定服务        Intent intent   = new Intent("AIDL_Action");        bindService(intent,mConnection, Service.BIND_AUTO_CREATE);    }       ServiceConnection mConnection  =  new ServiceConnection() {     @Override     public void onServiceConnected(ComponentName name, IBinder service) {         //建立连接之后将Binder转换为mSsoAuth         mSsoAuth =  SsoAuth.Stub.asInterface(service);         doSsoAuth();     }     @Override     public void onServiceDisconnected(ComponentName name) {         //合理利用资源          mSsoAuth = null;     } };    @Override    protected void onDestroy() {        super.onDestroy();        unbindService(mConnection);    }    private void doSsoAuth() {        try {            //执行登录操作,调用的是服务端的函数            mSsoAuth.ssoAuth("范冰冰","5201314");        } catch (RemoteException e) {            e.printStackTrace();        }    }}

效果就不演示了,LogCat会打印那句话的。

以上只是小白水平,下面看看大白水平是咋的。
这是aidl转为java的代码:

/* * This file is auto-generated.  DO NOT MODIFY. * Original file: F:\\workingplace\\MyAidl\\aidl_client\\src\\main\\aidl\\com\\yu\\myaidl\\SsoAuth.aidl */package com.yu.myaidl;// Declare any non-default types here with import statementspublic interface SsoAuth extends android.os.IInterface {    /**     * Local-side IPC implementation stub class.     */    public static abstract class Stub extends android.os.Binder implements com.yu.myaidl.SsoAuth {        private static final java.lang.String DESCRIPTOR = "com.yu.myaidl.SsoAuth";        /**         * Construct the stub at attach it to the interface.         */        public Stub() {            this.attachInterface(this, DESCRIPTOR);        }        /**         * Cast an IBinder object into an com.yu.myaidl.SsoAuth interface,         * generating a proxy if needed.         */        public static com.yu.myaidl.SsoAuth asInterface(android.os.IBinder obj) {            if ((obj == null)) {                return null;            }            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);            if (((iin != null) && (iin instanceof com.yu.myaidl.SsoAuth))) {                return ((com.yu.myaidl.SsoAuth) iin);            }            return new com.yu.myaidl.SsoAuth.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_ssoAuth: {                    data.enforceInterface(DESCRIPTOR);                    java.lang.String _arg0;                    _arg0 = data.readString();                    java.lang.String _arg1;                    _arg1 = data.readString();                    this.ssoAuth(_arg0, _arg1);                    reply.writeNoException();                    return true;                }            }            return super.onTransact(code, data, reply, flags);        }        private static class Proxy implements com.yu.myaidl.SsoAuth {            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;            }            /**             * Demonstrates some basic types that you can use as parameters             * and return values in AIDL.             */            @Override            public void ssoAuth(java.lang.String userName, java.lang.String pwd) throws android.os.RemoteException {                android.os.Parcel _data = android.os.Parcel.obtain();                android.os.Parcel _reply = android.os.Parcel.obtain();                try {                    _data.writeInterfaceToken(DESCRIPTOR);                    _data.writeString(userName);                    _data.writeString(pwd);                    mRemote.transact(Stub.TRANSACTION_ssoAuth, _data, _reply, 0);                    _reply.readException();                } finally {                    _reply.recycle();                    _data.recycle();                }            }        }        static final int TRANSACTION_ssoAuth = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);    }    /**     * Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     */    public void ssoAuth(java.lang.String userName, java.lang.String pwd) throws android.os.RemoteException;}

简要分析下:第12行生成了Stub静态内部类,该类继承了Binder,并且实现了SsoAuth接口。看到第26行asInterface(),在这个函数中判断obj的类型,如果是本地的话,将它转换为SsoAuth类型,相反,会生成内一个内部类Proxy来包装obj,将器复制给Proxy的mremote字段。63和84行,Proxy同样实现了SsoAuth接口,它是通过Binder机制来与远程进程进行交互。
客户端的调用会通过Binder机制传递到服务端,最终调用Stub类中的onTransact()。49行,由于客户端发送请求时的类型是TRANSACTION_ssoAuth(通过91行可知),满足这个类型的话,就会执行55行。因此:这二端的Binder机制就对接上了。

 public void onServiceConnected(ComponentName name, IBinder service) {         //建立连接之后将Binder转换为mSsoAuth         mSsoAuth =  SsoAuth.Stub.asInterface(service);         doSsoAuth();     }

上面这行代码:Service对象其实是BinderProxy类型经过asInterface()转换后被包装成了Proxy类型,但在调用的时候,执行的是服务端的ssoAuth(),SinaSsoImpl实例mBinder被服务端包装成BinderProxy类型,再经过客户端的Proxy进行包装,通过Binder机制进行数据传输实现进程间的调用。

0 0