AIDL

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 statements

interface 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 statements

public 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机制进行数据传输实现进程间的调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值