您的位置:首页 > 大数据 > 人工智能

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文件内容:

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机制进行数据传输实现进程间的调用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: