AIDL
2016-05-15 17:11
218 查看
AIDL(Android 接口描述语言):作用是用于进程间的通信。编译器会根据AIDL文件生成Java类,通过预先定义的接口以及Binder机制达到进程间的通信。
AIDL其实就是一个接口罢了,客户端通过bindService来与远程服务端建立连接,在该连接建立时会返回一个IBinder对象,该对象是服务端Binder的BinderProxy,客户端通过asinterface将该BinderProxy对象包装成本地的Proxy,并将远程服务端的BinderProxy对象赋值给Proxy类的mRemote字段,就是通过mRemote执行远程函数调用。
下面写一个案例:
先看一下工程结构:
注意:创建完.aidl文件后一定要先编译,如果你是用Eclipse的话会自动编译,否则java文件不会生成!还有,包名和类名一字不差!
aidl文件内容:
下面是服务端代码:
别忘了注册服务:
好了,服务端OK了,先跑起来吧!
客户端代码如下:
效果就不演示了,LogCat会打印那句话的。
以上只是小白水平,下面看看大白水平是咋的。
这是aidl转为java的代码:
简要分析下:第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机制就对接上了。
上面这行代码:Service对象其实是BinderProxy类型经过asInterface()转换后被包装成了Proxy类型,但在调用的时候,执行的是服务端的ssoAuth(),SinaSsoImpl实例mBinder被服务端包装成BinderProxy类型,再经过客户端的Proxy进行包装,通过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机制进行数据传输实现进程间的调用。
相关文章推荐
- 51Nod-1305-Pairwise Sum and Divide
- 打印一个楼梯(Staircase)
- Git学习 -- 远程操作遇到error: failed to push some refs to问题解决方法
- A failure of one rush
- Synchronized关键字与线程通信
- 人工智能假如失控 将会带来何种危害程度?
- URAL 1890 . Money out of Thin Air (dfs序hash + 线段树)
- 列车调度(Train)
- svn服务器搭建和使用:Custom action GenerateSSLKey failed: Command terminated with non-zero exit code
- saiku之行速度优化(三)
- saiku之行速度优化(三)
- 杭电1023 train problem2
- hdu 1789 Doing Homework again(贪心)
- 【Leetcode】Duplicate Emails
- 杭电1022 train problem
- Writing a ServiceMain Function(使用RegisterServiceCtrlHandler函数)
- 具有超强阅读理解能力的人工智能(Maluuba机器人)
- http://blog.csdn.net/jhg1204/article/details/45013987
- STL中的Pair方法详解
- HDU 2115 I Love This Game(结构体排序 or pair)